Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .venv/lib/python3.11/site-packages/mpmath/__init__.py +468 -0
- .venv/lib/python3.11/site-packages/mpmath/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_base.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_mp.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/ctx_base.py +494 -0
- .venv/lib/python3.11/site-packages/mpmath/ctx_fp.py +253 -0
- .venv/lib/python3.11/site-packages/mpmath/ctx_iv.py +551 -0
- .venv/lib/python3.11/site-packages/mpmath/ctx_mp.py +1339 -0
- .venv/lib/python3.11/site-packages/mpmath/ctx_mp_python.py +1149 -0
- .venv/lib/python3.11/site-packages/mpmath/function_docs.py +0 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/__init__.py +14 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/orthogonal.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/qfunctions.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/signals.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/theta.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/bessel.py +1108 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/elliptic.py +1431 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/expintegrals.py +425 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/factorials.py +187 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/functions.py +645 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/hypergeometric.py +1413 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/orthogonal.py +493 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/qfunctions.py +280 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/rszeta.py +1403 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/signals.py +32 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/theta.py +1049 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/zeta.py +1154 -0
- .venv/lib/python3.11/site-packages/mpmath/functions/zetazeros.py +1018 -0
- .venv/lib/python3.11/site-packages/mpmath/identification.py +844 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__init__.py +77 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/backend.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/gammazeta.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libelefun.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libhyper.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libintmath.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libmpc.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libmpf.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libmpi.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/backend.py +115 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/gammazeta.py +2167 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/libhyper.py +1150 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/libintmath.py +584 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/libmpc.py +835 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/libmpf.py +1414 -0
- .venv/lib/python3.11/site-packages/mpmath/libmp/libmpi.py +935 -0
- .venv/lib/python3.11/site-packages/mpmath/math2.py +672 -0
- .venv/lib/python3.11/site-packages/mpmath/rational.py +240 -0
- .venv/lib/python3.11/site-packages/mpmath/tests/test_calculus.py +216 -0
- .venv/lib/python3.11/site-packages/mpmath/tests/test_division.py +143 -0
.venv/lib/python3.11/site-packages/mpmath/__init__.py
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__version__ = '1.3.0'
|
| 2 |
+
|
| 3 |
+
from .usertools import monitor, timing
|
| 4 |
+
|
| 5 |
+
from .ctx_fp import FPContext
|
| 6 |
+
from .ctx_mp import MPContext
|
| 7 |
+
from .ctx_iv import MPIntervalContext
|
| 8 |
+
|
| 9 |
+
fp = FPContext()
|
| 10 |
+
mp = MPContext()
|
| 11 |
+
iv = MPIntervalContext()
|
| 12 |
+
|
| 13 |
+
fp._mp = mp
|
| 14 |
+
mp._mp = mp
|
| 15 |
+
iv._mp = mp
|
| 16 |
+
mp._fp = fp
|
| 17 |
+
fp._fp = fp
|
| 18 |
+
mp._iv = iv
|
| 19 |
+
fp._iv = iv
|
| 20 |
+
iv._iv = iv
|
| 21 |
+
|
| 22 |
+
# XXX: extremely bad pickle hack
|
| 23 |
+
from . import ctx_mp as _ctx_mp
|
| 24 |
+
_ctx_mp._mpf_module.mpf = mp.mpf
|
| 25 |
+
_ctx_mp._mpf_module.mpc = mp.mpc
|
| 26 |
+
|
| 27 |
+
make_mpf = mp.make_mpf
|
| 28 |
+
make_mpc = mp.make_mpc
|
| 29 |
+
|
| 30 |
+
extraprec = mp.extraprec
|
| 31 |
+
extradps = mp.extradps
|
| 32 |
+
workprec = mp.workprec
|
| 33 |
+
workdps = mp.workdps
|
| 34 |
+
autoprec = mp.autoprec
|
| 35 |
+
maxcalls = mp.maxcalls
|
| 36 |
+
memoize = mp.memoize
|
| 37 |
+
|
| 38 |
+
mag = mp.mag
|
| 39 |
+
|
| 40 |
+
bernfrac = mp.bernfrac
|
| 41 |
+
|
| 42 |
+
qfrom = mp.qfrom
|
| 43 |
+
mfrom = mp.mfrom
|
| 44 |
+
kfrom = mp.kfrom
|
| 45 |
+
taufrom = mp.taufrom
|
| 46 |
+
qbarfrom = mp.qbarfrom
|
| 47 |
+
ellipfun = mp.ellipfun
|
| 48 |
+
jtheta = mp.jtheta
|
| 49 |
+
kleinj = mp.kleinj
|
| 50 |
+
eta = mp.eta
|
| 51 |
+
|
| 52 |
+
qp = mp.qp
|
| 53 |
+
qhyper = mp.qhyper
|
| 54 |
+
qgamma = mp.qgamma
|
| 55 |
+
qfac = mp.qfac
|
| 56 |
+
|
| 57 |
+
nint_distance = mp.nint_distance
|
| 58 |
+
|
| 59 |
+
plot = mp.plot
|
| 60 |
+
cplot = mp.cplot
|
| 61 |
+
splot = mp.splot
|
| 62 |
+
|
| 63 |
+
odefun = mp.odefun
|
| 64 |
+
|
| 65 |
+
jacobian = mp.jacobian
|
| 66 |
+
findroot = mp.findroot
|
| 67 |
+
multiplicity = mp.multiplicity
|
| 68 |
+
|
| 69 |
+
isinf = mp.isinf
|
| 70 |
+
isnan = mp.isnan
|
| 71 |
+
isnormal = mp.isnormal
|
| 72 |
+
isint = mp.isint
|
| 73 |
+
isfinite = mp.isfinite
|
| 74 |
+
almosteq = mp.almosteq
|
| 75 |
+
nan = mp.nan
|
| 76 |
+
rand = mp.rand
|
| 77 |
+
|
| 78 |
+
absmin = mp.absmin
|
| 79 |
+
absmax = mp.absmax
|
| 80 |
+
|
| 81 |
+
fraction = mp.fraction
|
| 82 |
+
|
| 83 |
+
linspace = mp.linspace
|
| 84 |
+
arange = mp.arange
|
| 85 |
+
|
| 86 |
+
mpmathify = convert = mp.convert
|
| 87 |
+
mpc = mp.mpc
|
| 88 |
+
|
| 89 |
+
mpi = iv._mpi
|
| 90 |
+
|
| 91 |
+
nstr = mp.nstr
|
| 92 |
+
nprint = mp.nprint
|
| 93 |
+
chop = mp.chop
|
| 94 |
+
|
| 95 |
+
fneg = mp.fneg
|
| 96 |
+
fadd = mp.fadd
|
| 97 |
+
fsub = mp.fsub
|
| 98 |
+
fmul = mp.fmul
|
| 99 |
+
fdiv = mp.fdiv
|
| 100 |
+
fprod = mp.fprod
|
| 101 |
+
|
| 102 |
+
quad = mp.quad
|
| 103 |
+
quadgl = mp.quadgl
|
| 104 |
+
quadts = mp.quadts
|
| 105 |
+
quadosc = mp.quadosc
|
| 106 |
+
quadsubdiv = mp.quadsubdiv
|
| 107 |
+
|
| 108 |
+
invertlaplace = mp.invertlaplace
|
| 109 |
+
invlaptalbot = mp.invlaptalbot
|
| 110 |
+
invlapstehfest = mp.invlapstehfest
|
| 111 |
+
invlapdehoog = mp.invlapdehoog
|
| 112 |
+
|
| 113 |
+
pslq = mp.pslq
|
| 114 |
+
identify = mp.identify
|
| 115 |
+
findpoly = mp.findpoly
|
| 116 |
+
|
| 117 |
+
richardson = mp.richardson
|
| 118 |
+
shanks = mp.shanks
|
| 119 |
+
levin = mp.levin
|
| 120 |
+
cohen_alt = mp.cohen_alt
|
| 121 |
+
nsum = mp.nsum
|
| 122 |
+
nprod = mp.nprod
|
| 123 |
+
difference = mp.difference
|
| 124 |
+
diff = mp.diff
|
| 125 |
+
diffs = mp.diffs
|
| 126 |
+
diffs_prod = mp.diffs_prod
|
| 127 |
+
diffs_exp = mp.diffs_exp
|
| 128 |
+
diffun = mp.diffun
|
| 129 |
+
differint = mp.differint
|
| 130 |
+
taylor = mp.taylor
|
| 131 |
+
pade = mp.pade
|
| 132 |
+
polyval = mp.polyval
|
| 133 |
+
polyroots = mp.polyroots
|
| 134 |
+
fourier = mp.fourier
|
| 135 |
+
fourierval = mp.fourierval
|
| 136 |
+
sumem = mp.sumem
|
| 137 |
+
sumap = mp.sumap
|
| 138 |
+
chebyfit = mp.chebyfit
|
| 139 |
+
limit = mp.limit
|
| 140 |
+
|
| 141 |
+
matrix = mp.matrix
|
| 142 |
+
eye = mp.eye
|
| 143 |
+
diag = mp.diag
|
| 144 |
+
zeros = mp.zeros
|
| 145 |
+
ones = mp.ones
|
| 146 |
+
hilbert = mp.hilbert
|
| 147 |
+
randmatrix = mp.randmatrix
|
| 148 |
+
swap_row = mp.swap_row
|
| 149 |
+
extend = mp.extend
|
| 150 |
+
norm = mp.norm
|
| 151 |
+
mnorm = mp.mnorm
|
| 152 |
+
|
| 153 |
+
lu_solve = mp.lu_solve
|
| 154 |
+
lu = mp.lu
|
| 155 |
+
qr = mp.qr
|
| 156 |
+
unitvector = mp.unitvector
|
| 157 |
+
inverse = mp.inverse
|
| 158 |
+
residual = mp.residual
|
| 159 |
+
qr_solve = mp.qr_solve
|
| 160 |
+
cholesky = mp.cholesky
|
| 161 |
+
cholesky_solve = mp.cholesky_solve
|
| 162 |
+
det = mp.det
|
| 163 |
+
cond = mp.cond
|
| 164 |
+
hessenberg = mp.hessenberg
|
| 165 |
+
schur = mp.schur
|
| 166 |
+
eig = mp.eig
|
| 167 |
+
eig_sort = mp.eig_sort
|
| 168 |
+
eigsy = mp.eigsy
|
| 169 |
+
eighe = mp.eighe
|
| 170 |
+
eigh = mp.eigh
|
| 171 |
+
svd_r = mp.svd_r
|
| 172 |
+
svd_c = mp.svd_c
|
| 173 |
+
svd = mp.svd
|
| 174 |
+
gauss_quadrature = mp.gauss_quadrature
|
| 175 |
+
|
| 176 |
+
expm = mp.expm
|
| 177 |
+
sqrtm = mp.sqrtm
|
| 178 |
+
powm = mp.powm
|
| 179 |
+
logm = mp.logm
|
| 180 |
+
sinm = mp.sinm
|
| 181 |
+
cosm = mp.cosm
|
| 182 |
+
|
| 183 |
+
mpf = mp.mpf
|
| 184 |
+
j = mp.j
|
| 185 |
+
exp = mp.exp
|
| 186 |
+
expj = mp.expj
|
| 187 |
+
expjpi = mp.expjpi
|
| 188 |
+
ln = mp.ln
|
| 189 |
+
im = mp.im
|
| 190 |
+
re = mp.re
|
| 191 |
+
inf = mp.inf
|
| 192 |
+
ninf = mp.ninf
|
| 193 |
+
sign = mp.sign
|
| 194 |
+
|
| 195 |
+
eps = mp.eps
|
| 196 |
+
pi = mp.pi
|
| 197 |
+
ln2 = mp.ln2
|
| 198 |
+
ln10 = mp.ln10
|
| 199 |
+
phi = mp.phi
|
| 200 |
+
e = mp.e
|
| 201 |
+
euler = mp.euler
|
| 202 |
+
catalan = mp.catalan
|
| 203 |
+
khinchin = mp.khinchin
|
| 204 |
+
glaisher = mp.glaisher
|
| 205 |
+
apery = mp.apery
|
| 206 |
+
degree = mp.degree
|
| 207 |
+
twinprime = mp.twinprime
|
| 208 |
+
mertens = mp.mertens
|
| 209 |
+
|
| 210 |
+
ldexp = mp.ldexp
|
| 211 |
+
frexp = mp.frexp
|
| 212 |
+
|
| 213 |
+
fsum = mp.fsum
|
| 214 |
+
fdot = mp.fdot
|
| 215 |
+
|
| 216 |
+
sqrt = mp.sqrt
|
| 217 |
+
cbrt = mp.cbrt
|
| 218 |
+
exp = mp.exp
|
| 219 |
+
ln = mp.ln
|
| 220 |
+
log = mp.log
|
| 221 |
+
log10 = mp.log10
|
| 222 |
+
power = mp.power
|
| 223 |
+
cos = mp.cos
|
| 224 |
+
sin = mp.sin
|
| 225 |
+
tan = mp.tan
|
| 226 |
+
cosh = mp.cosh
|
| 227 |
+
sinh = mp.sinh
|
| 228 |
+
tanh = mp.tanh
|
| 229 |
+
acos = mp.acos
|
| 230 |
+
asin = mp.asin
|
| 231 |
+
atan = mp.atan
|
| 232 |
+
asinh = mp.asinh
|
| 233 |
+
acosh = mp.acosh
|
| 234 |
+
atanh = mp.atanh
|
| 235 |
+
sec = mp.sec
|
| 236 |
+
csc = mp.csc
|
| 237 |
+
cot = mp.cot
|
| 238 |
+
sech = mp.sech
|
| 239 |
+
csch = mp.csch
|
| 240 |
+
coth = mp.coth
|
| 241 |
+
asec = mp.asec
|
| 242 |
+
acsc = mp.acsc
|
| 243 |
+
acot = mp.acot
|
| 244 |
+
asech = mp.asech
|
| 245 |
+
acsch = mp.acsch
|
| 246 |
+
acoth = mp.acoth
|
| 247 |
+
cospi = mp.cospi
|
| 248 |
+
sinpi = mp.sinpi
|
| 249 |
+
sinc = mp.sinc
|
| 250 |
+
sincpi = mp.sincpi
|
| 251 |
+
cos_sin = mp.cos_sin
|
| 252 |
+
cospi_sinpi = mp.cospi_sinpi
|
| 253 |
+
fabs = mp.fabs
|
| 254 |
+
re = mp.re
|
| 255 |
+
im = mp.im
|
| 256 |
+
conj = mp.conj
|
| 257 |
+
floor = mp.floor
|
| 258 |
+
ceil = mp.ceil
|
| 259 |
+
nint = mp.nint
|
| 260 |
+
frac = mp.frac
|
| 261 |
+
root = mp.root
|
| 262 |
+
nthroot = mp.nthroot
|
| 263 |
+
hypot = mp.hypot
|
| 264 |
+
fmod = mp.fmod
|
| 265 |
+
ldexp = mp.ldexp
|
| 266 |
+
frexp = mp.frexp
|
| 267 |
+
sign = mp.sign
|
| 268 |
+
arg = mp.arg
|
| 269 |
+
phase = mp.phase
|
| 270 |
+
polar = mp.polar
|
| 271 |
+
rect = mp.rect
|
| 272 |
+
degrees = mp.degrees
|
| 273 |
+
radians = mp.radians
|
| 274 |
+
atan2 = mp.atan2
|
| 275 |
+
fib = mp.fib
|
| 276 |
+
fibonacci = mp.fibonacci
|
| 277 |
+
lambertw = mp.lambertw
|
| 278 |
+
zeta = mp.zeta
|
| 279 |
+
altzeta = mp.altzeta
|
| 280 |
+
gamma = mp.gamma
|
| 281 |
+
rgamma = mp.rgamma
|
| 282 |
+
factorial = mp.factorial
|
| 283 |
+
fac = mp.fac
|
| 284 |
+
fac2 = mp.fac2
|
| 285 |
+
beta = mp.beta
|
| 286 |
+
betainc = mp.betainc
|
| 287 |
+
psi = mp.psi
|
| 288 |
+
#psi0 = mp.psi0
|
| 289 |
+
#psi1 = mp.psi1
|
| 290 |
+
#psi2 = mp.psi2
|
| 291 |
+
#psi3 = mp.psi3
|
| 292 |
+
polygamma = mp.polygamma
|
| 293 |
+
digamma = mp.digamma
|
| 294 |
+
#trigamma = mp.trigamma
|
| 295 |
+
#tetragamma = mp.tetragamma
|
| 296 |
+
#pentagamma = mp.pentagamma
|
| 297 |
+
harmonic = mp.harmonic
|
| 298 |
+
bernoulli = mp.bernoulli
|
| 299 |
+
bernfrac = mp.bernfrac
|
| 300 |
+
stieltjes = mp.stieltjes
|
| 301 |
+
hurwitz = mp.hurwitz
|
| 302 |
+
dirichlet = mp.dirichlet
|
| 303 |
+
bernpoly = mp.bernpoly
|
| 304 |
+
eulerpoly = mp.eulerpoly
|
| 305 |
+
eulernum = mp.eulernum
|
| 306 |
+
polylog = mp.polylog
|
| 307 |
+
clsin = mp.clsin
|
| 308 |
+
clcos = mp.clcos
|
| 309 |
+
gammainc = mp.gammainc
|
| 310 |
+
gammaprod = mp.gammaprod
|
| 311 |
+
binomial = mp.binomial
|
| 312 |
+
rf = mp.rf
|
| 313 |
+
ff = mp.ff
|
| 314 |
+
hyper = mp.hyper
|
| 315 |
+
hyp0f1 = mp.hyp0f1
|
| 316 |
+
hyp1f1 = mp.hyp1f1
|
| 317 |
+
hyp1f2 = mp.hyp1f2
|
| 318 |
+
hyp2f1 = mp.hyp2f1
|
| 319 |
+
hyp2f2 = mp.hyp2f2
|
| 320 |
+
hyp2f0 = mp.hyp2f0
|
| 321 |
+
hyp2f3 = mp.hyp2f3
|
| 322 |
+
hyp3f2 = mp.hyp3f2
|
| 323 |
+
hyperu = mp.hyperu
|
| 324 |
+
hypercomb = mp.hypercomb
|
| 325 |
+
meijerg = mp.meijerg
|
| 326 |
+
appellf1 = mp.appellf1
|
| 327 |
+
appellf2 = mp.appellf2
|
| 328 |
+
appellf3 = mp.appellf3
|
| 329 |
+
appellf4 = mp.appellf4
|
| 330 |
+
hyper2d = mp.hyper2d
|
| 331 |
+
bihyper = mp.bihyper
|
| 332 |
+
erf = mp.erf
|
| 333 |
+
erfc = mp.erfc
|
| 334 |
+
erfi = mp.erfi
|
| 335 |
+
erfinv = mp.erfinv
|
| 336 |
+
npdf = mp.npdf
|
| 337 |
+
ncdf = mp.ncdf
|
| 338 |
+
expint = mp.expint
|
| 339 |
+
e1 = mp.e1
|
| 340 |
+
ei = mp.ei
|
| 341 |
+
li = mp.li
|
| 342 |
+
ci = mp.ci
|
| 343 |
+
si = mp.si
|
| 344 |
+
chi = mp.chi
|
| 345 |
+
shi = mp.shi
|
| 346 |
+
fresnels = mp.fresnels
|
| 347 |
+
fresnelc = mp.fresnelc
|
| 348 |
+
airyai = mp.airyai
|
| 349 |
+
airybi = mp.airybi
|
| 350 |
+
airyaizero = mp.airyaizero
|
| 351 |
+
airybizero = mp.airybizero
|
| 352 |
+
scorergi = mp.scorergi
|
| 353 |
+
scorerhi = mp.scorerhi
|
| 354 |
+
ellipk = mp.ellipk
|
| 355 |
+
ellipe = mp.ellipe
|
| 356 |
+
ellipf = mp.ellipf
|
| 357 |
+
ellippi = mp.ellippi
|
| 358 |
+
elliprc = mp.elliprc
|
| 359 |
+
elliprj = mp.elliprj
|
| 360 |
+
elliprf = mp.elliprf
|
| 361 |
+
elliprd = mp.elliprd
|
| 362 |
+
elliprg = mp.elliprg
|
| 363 |
+
agm = mp.agm
|
| 364 |
+
jacobi = mp.jacobi
|
| 365 |
+
chebyt = mp.chebyt
|
| 366 |
+
chebyu = mp.chebyu
|
| 367 |
+
legendre = mp.legendre
|
| 368 |
+
legenp = mp.legenp
|
| 369 |
+
legenq = mp.legenq
|
| 370 |
+
hermite = mp.hermite
|
| 371 |
+
pcfd = mp.pcfd
|
| 372 |
+
pcfu = mp.pcfu
|
| 373 |
+
pcfv = mp.pcfv
|
| 374 |
+
pcfw = mp.pcfw
|
| 375 |
+
gegenbauer = mp.gegenbauer
|
| 376 |
+
laguerre = mp.laguerre
|
| 377 |
+
spherharm = mp.spherharm
|
| 378 |
+
besselj = mp.besselj
|
| 379 |
+
j0 = mp.j0
|
| 380 |
+
j1 = mp.j1
|
| 381 |
+
besseli = mp.besseli
|
| 382 |
+
bessely = mp.bessely
|
| 383 |
+
besselk = mp.besselk
|
| 384 |
+
besseljzero = mp.besseljzero
|
| 385 |
+
besselyzero = mp.besselyzero
|
| 386 |
+
hankel1 = mp.hankel1
|
| 387 |
+
hankel2 = mp.hankel2
|
| 388 |
+
struveh = mp.struveh
|
| 389 |
+
struvel = mp.struvel
|
| 390 |
+
angerj = mp.angerj
|
| 391 |
+
webere = mp.webere
|
| 392 |
+
lommels1 = mp.lommels1
|
| 393 |
+
lommels2 = mp.lommels2
|
| 394 |
+
whitm = mp.whitm
|
| 395 |
+
whitw = mp.whitw
|
| 396 |
+
ber = mp.ber
|
| 397 |
+
bei = mp.bei
|
| 398 |
+
ker = mp.ker
|
| 399 |
+
kei = mp.kei
|
| 400 |
+
coulombc = mp.coulombc
|
| 401 |
+
coulombf = mp.coulombf
|
| 402 |
+
coulombg = mp.coulombg
|
| 403 |
+
barnesg = mp.barnesg
|
| 404 |
+
superfac = mp.superfac
|
| 405 |
+
hyperfac = mp.hyperfac
|
| 406 |
+
loggamma = mp.loggamma
|
| 407 |
+
siegeltheta = mp.siegeltheta
|
| 408 |
+
siegelz = mp.siegelz
|
| 409 |
+
grampoint = mp.grampoint
|
| 410 |
+
zetazero = mp.zetazero
|
| 411 |
+
riemannr = mp.riemannr
|
| 412 |
+
primepi = mp.primepi
|
| 413 |
+
primepi2 = mp.primepi2
|
| 414 |
+
primezeta = mp.primezeta
|
| 415 |
+
bell = mp.bell
|
| 416 |
+
polyexp = mp.polyexp
|
| 417 |
+
expm1 = mp.expm1
|
| 418 |
+
log1p = mp.log1p
|
| 419 |
+
powm1 = mp.powm1
|
| 420 |
+
unitroots = mp.unitroots
|
| 421 |
+
cyclotomic = mp.cyclotomic
|
| 422 |
+
mangoldt = mp.mangoldt
|
| 423 |
+
secondzeta = mp.secondzeta
|
| 424 |
+
nzeros = mp.nzeros
|
| 425 |
+
backlunds = mp.backlunds
|
| 426 |
+
lerchphi = mp.lerchphi
|
| 427 |
+
stirling1 = mp.stirling1
|
| 428 |
+
stirling2 = mp.stirling2
|
| 429 |
+
squarew = mp.squarew
|
| 430 |
+
trianglew = mp.trianglew
|
| 431 |
+
sawtoothw = mp.sawtoothw
|
| 432 |
+
unit_triangle = mp.unit_triangle
|
| 433 |
+
sigmoid = mp.sigmoid
|
| 434 |
+
|
| 435 |
+
# be careful when changing this name, don't use test*!
|
| 436 |
+
def runtests():
|
| 437 |
+
"""
|
| 438 |
+
Run all mpmath tests and print output.
|
| 439 |
+
"""
|
| 440 |
+
import os.path
|
| 441 |
+
from inspect import getsourcefile
|
| 442 |
+
from .tests import runtests as tests
|
| 443 |
+
testdir = os.path.dirname(os.path.abspath(getsourcefile(tests)))
|
| 444 |
+
importdir = os.path.abspath(testdir + '/../..')
|
| 445 |
+
tests.testit(importdir, testdir)
|
| 446 |
+
|
| 447 |
+
def doctests(filter=[]):
|
| 448 |
+
import sys
|
| 449 |
+
from timeit import default_timer as clock
|
| 450 |
+
for i, arg in enumerate(sys.argv):
|
| 451 |
+
if '__init__.py' in arg:
|
| 452 |
+
filter = [sn for sn in sys.argv[i+1:] if not sn.startswith("-")]
|
| 453 |
+
break
|
| 454 |
+
import doctest
|
| 455 |
+
globs = globals().copy()
|
| 456 |
+
for obj in globs: #sorted(globs.keys()):
|
| 457 |
+
if filter:
|
| 458 |
+
if not sum([pat in obj for pat in filter]):
|
| 459 |
+
continue
|
| 460 |
+
sys.stdout.write(str(obj) + " ")
|
| 461 |
+
sys.stdout.flush()
|
| 462 |
+
t1 = clock()
|
| 463 |
+
doctest.run_docstring_examples(globs[obj], {}, verbose=("-v" in sys.argv))
|
| 464 |
+
t2 = clock()
|
| 465 |
+
print(round(t2-t1, 3))
|
| 466 |
+
|
| 467 |
+
if __name__ == '__main__':
|
| 468 |
+
doctests()
|
.venv/lib/python3.11/site-packages/mpmath/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (14.7 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_base.cpython-311.pyc
ADDED
|
Binary file (24.4 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_mp.cpython-311.pyc
ADDED
|
Binary file (71.2 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/ctx_base.py
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from operator import gt, lt
|
| 2 |
+
|
| 3 |
+
from .libmp.backend import xrange
|
| 4 |
+
|
| 5 |
+
from .functions.functions import SpecialFunctions
|
| 6 |
+
from .functions.rszeta import RSCache
|
| 7 |
+
from .calculus.quadrature import QuadratureMethods
|
| 8 |
+
from .calculus.inverselaplace import LaplaceTransformInversionMethods
|
| 9 |
+
from .calculus.calculus import CalculusMethods
|
| 10 |
+
from .calculus.optimization import OptimizationMethods
|
| 11 |
+
from .calculus.odes import ODEMethods
|
| 12 |
+
from .matrices.matrices import MatrixMethods
|
| 13 |
+
from .matrices.calculus import MatrixCalculusMethods
|
| 14 |
+
from .matrices.linalg import LinearAlgebraMethods
|
| 15 |
+
from .matrices.eigen import Eigen
|
| 16 |
+
from .identification import IdentificationMethods
|
| 17 |
+
from .visualization import VisualizationMethods
|
| 18 |
+
|
| 19 |
+
from . import libmp
|
| 20 |
+
|
| 21 |
+
class Context(object):
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
class StandardBaseContext(Context,
|
| 25 |
+
SpecialFunctions,
|
| 26 |
+
RSCache,
|
| 27 |
+
QuadratureMethods,
|
| 28 |
+
LaplaceTransformInversionMethods,
|
| 29 |
+
CalculusMethods,
|
| 30 |
+
MatrixMethods,
|
| 31 |
+
MatrixCalculusMethods,
|
| 32 |
+
LinearAlgebraMethods,
|
| 33 |
+
Eigen,
|
| 34 |
+
IdentificationMethods,
|
| 35 |
+
OptimizationMethods,
|
| 36 |
+
ODEMethods,
|
| 37 |
+
VisualizationMethods):
|
| 38 |
+
|
| 39 |
+
NoConvergence = libmp.NoConvergence
|
| 40 |
+
ComplexResult = libmp.ComplexResult
|
| 41 |
+
|
| 42 |
+
def __init__(ctx):
|
| 43 |
+
ctx._aliases = {}
|
| 44 |
+
# Call those that need preinitialization (e.g. for wrappers)
|
| 45 |
+
SpecialFunctions.__init__(ctx)
|
| 46 |
+
RSCache.__init__(ctx)
|
| 47 |
+
QuadratureMethods.__init__(ctx)
|
| 48 |
+
LaplaceTransformInversionMethods.__init__(ctx)
|
| 49 |
+
CalculusMethods.__init__(ctx)
|
| 50 |
+
MatrixMethods.__init__(ctx)
|
| 51 |
+
|
| 52 |
+
def _init_aliases(ctx):
|
| 53 |
+
for alias, value in ctx._aliases.items():
|
| 54 |
+
try:
|
| 55 |
+
setattr(ctx, alias, getattr(ctx, value))
|
| 56 |
+
except AttributeError:
|
| 57 |
+
pass
|
| 58 |
+
|
| 59 |
+
_fixed_precision = False
|
| 60 |
+
|
| 61 |
+
# XXX
|
| 62 |
+
verbose = False
|
| 63 |
+
|
| 64 |
+
def warn(ctx, msg):
|
| 65 |
+
print("Warning:", msg)
|
| 66 |
+
|
| 67 |
+
def bad_domain(ctx, msg):
|
| 68 |
+
raise ValueError(msg)
|
| 69 |
+
|
| 70 |
+
def _re(ctx, x):
|
| 71 |
+
if hasattr(x, "real"):
|
| 72 |
+
return x.real
|
| 73 |
+
return x
|
| 74 |
+
|
| 75 |
+
def _im(ctx, x):
|
| 76 |
+
if hasattr(x, "imag"):
|
| 77 |
+
return x.imag
|
| 78 |
+
return ctx.zero
|
| 79 |
+
|
| 80 |
+
def _as_points(ctx, x):
|
| 81 |
+
return x
|
| 82 |
+
|
| 83 |
+
def fneg(ctx, x, **kwargs):
|
| 84 |
+
return -ctx.convert(x)
|
| 85 |
+
|
| 86 |
+
def fadd(ctx, x, y, **kwargs):
|
| 87 |
+
return ctx.convert(x)+ctx.convert(y)
|
| 88 |
+
|
| 89 |
+
def fsub(ctx, x, y, **kwargs):
|
| 90 |
+
return ctx.convert(x)-ctx.convert(y)
|
| 91 |
+
|
| 92 |
+
def fmul(ctx, x, y, **kwargs):
|
| 93 |
+
return ctx.convert(x)*ctx.convert(y)
|
| 94 |
+
|
| 95 |
+
def fdiv(ctx, x, y, **kwargs):
|
| 96 |
+
return ctx.convert(x)/ctx.convert(y)
|
| 97 |
+
|
| 98 |
+
def fsum(ctx, args, absolute=False, squared=False):
|
| 99 |
+
if absolute:
|
| 100 |
+
if squared:
|
| 101 |
+
return sum((abs(x)**2 for x in args), ctx.zero)
|
| 102 |
+
return sum((abs(x) for x in args), ctx.zero)
|
| 103 |
+
if squared:
|
| 104 |
+
return sum((x**2 for x in args), ctx.zero)
|
| 105 |
+
return sum(args, ctx.zero)
|
| 106 |
+
|
| 107 |
+
def fdot(ctx, xs, ys=None, conjugate=False):
|
| 108 |
+
if ys is not None:
|
| 109 |
+
xs = zip(xs, ys)
|
| 110 |
+
if conjugate:
|
| 111 |
+
cf = ctx.conj
|
| 112 |
+
return sum((x*cf(y) for (x,y) in xs), ctx.zero)
|
| 113 |
+
else:
|
| 114 |
+
return sum((x*y for (x,y) in xs), ctx.zero)
|
| 115 |
+
|
| 116 |
+
def fprod(ctx, args):
|
| 117 |
+
prod = ctx.one
|
| 118 |
+
for arg in args:
|
| 119 |
+
prod *= arg
|
| 120 |
+
return prod
|
| 121 |
+
|
| 122 |
+
def nprint(ctx, x, n=6, **kwargs):
|
| 123 |
+
"""
|
| 124 |
+
Equivalent to ``print(nstr(x, n))``.
|
| 125 |
+
"""
|
| 126 |
+
print(ctx.nstr(x, n, **kwargs))
|
| 127 |
+
|
| 128 |
+
def chop(ctx, x, tol=None):
|
| 129 |
+
"""
|
| 130 |
+
Chops off small real or imaginary parts, or converts
|
| 131 |
+
numbers close to zero to exact zeros. The input can be a
|
| 132 |
+
single number or an iterable::
|
| 133 |
+
|
| 134 |
+
>>> from mpmath import *
|
| 135 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 136 |
+
>>> chop(5+1e-10j, tol=1e-9)
|
| 137 |
+
mpf('5.0')
|
| 138 |
+
>>> nprint(chop([1.0, 1e-20, 3+1e-18j, -4, 2]))
|
| 139 |
+
[1.0, 0.0, 3.0, -4.0, 2.0]
|
| 140 |
+
|
| 141 |
+
The tolerance defaults to ``100*eps``.
|
| 142 |
+
"""
|
| 143 |
+
if tol is None:
|
| 144 |
+
tol = 100*ctx.eps
|
| 145 |
+
try:
|
| 146 |
+
x = ctx.convert(x)
|
| 147 |
+
absx = abs(x)
|
| 148 |
+
if abs(x) < tol:
|
| 149 |
+
return ctx.zero
|
| 150 |
+
if ctx._is_complex_type(x):
|
| 151 |
+
#part_tol = min(tol, absx*tol)
|
| 152 |
+
part_tol = max(tol, absx*tol)
|
| 153 |
+
if abs(x.imag) < part_tol:
|
| 154 |
+
return x.real
|
| 155 |
+
if abs(x.real) < part_tol:
|
| 156 |
+
return ctx.mpc(0, x.imag)
|
| 157 |
+
except TypeError:
|
| 158 |
+
if isinstance(x, ctx.matrix):
|
| 159 |
+
return x.apply(lambda a: ctx.chop(a, tol))
|
| 160 |
+
if hasattr(x, "__iter__"):
|
| 161 |
+
return [ctx.chop(a, tol) for a in x]
|
| 162 |
+
return x
|
| 163 |
+
|
| 164 |
+
def almosteq(ctx, s, t, rel_eps=None, abs_eps=None):
|
| 165 |
+
r"""
|
| 166 |
+
Determine whether the difference between `s` and `t` is smaller
|
| 167 |
+
than a given epsilon, either relatively or absolutely.
|
| 168 |
+
|
| 169 |
+
Both a maximum relative difference and a maximum difference
|
| 170 |
+
('epsilons') may be specified. The absolute difference is
|
| 171 |
+
defined as `|s-t|` and the relative difference is defined
|
| 172 |
+
as `|s-t|/\max(|s|, |t|)`.
|
| 173 |
+
|
| 174 |
+
If only one epsilon is given, both are set to the same value.
|
| 175 |
+
If none is given, both epsilons are set to `2^{-p+m}` where
|
| 176 |
+
`p` is the current working precision and `m` is a small
|
| 177 |
+
integer. The default setting typically allows :func:`~mpmath.almosteq`
|
| 178 |
+
to be used to check for mathematical equality
|
| 179 |
+
in the presence of small rounding errors.
|
| 180 |
+
|
| 181 |
+
**Examples**
|
| 182 |
+
|
| 183 |
+
>>> from mpmath import *
|
| 184 |
+
>>> mp.dps = 15
|
| 185 |
+
>>> almosteq(3.141592653589793, 3.141592653589790)
|
| 186 |
+
True
|
| 187 |
+
>>> almosteq(3.141592653589793, 3.141592653589700)
|
| 188 |
+
False
|
| 189 |
+
>>> almosteq(3.141592653589793, 3.141592653589700, 1e-10)
|
| 190 |
+
True
|
| 191 |
+
>>> almosteq(1e-20, 2e-20)
|
| 192 |
+
True
|
| 193 |
+
>>> almosteq(1e-20, 2e-20, rel_eps=0, abs_eps=0)
|
| 194 |
+
False
|
| 195 |
+
|
| 196 |
+
"""
|
| 197 |
+
t = ctx.convert(t)
|
| 198 |
+
if abs_eps is None and rel_eps is None:
|
| 199 |
+
rel_eps = abs_eps = ctx.ldexp(1, -ctx.prec+4)
|
| 200 |
+
if abs_eps is None:
|
| 201 |
+
abs_eps = rel_eps
|
| 202 |
+
elif rel_eps is None:
|
| 203 |
+
rel_eps = abs_eps
|
| 204 |
+
diff = abs(s-t)
|
| 205 |
+
if diff <= abs_eps:
|
| 206 |
+
return True
|
| 207 |
+
abss = abs(s)
|
| 208 |
+
abst = abs(t)
|
| 209 |
+
if abss < abst:
|
| 210 |
+
err = diff/abst
|
| 211 |
+
else:
|
| 212 |
+
err = diff/abss
|
| 213 |
+
return err <= rel_eps
|
| 214 |
+
|
| 215 |
+
def arange(ctx, *args):
|
| 216 |
+
r"""
|
| 217 |
+
This is a generalized version of Python's :func:`~mpmath.range` function
|
| 218 |
+
that accepts fractional endpoints and step sizes and
|
| 219 |
+
returns a list of ``mpf`` instances. Like :func:`~mpmath.range`,
|
| 220 |
+
:func:`~mpmath.arange` can be called with 1, 2 or 3 arguments:
|
| 221 |
+
|
| 222 |
+
``arange(b)``
|
| 223 |
+
`[0, 1, 2, \ldots, x]`
|
| 224 |
+
``arange(a, b)``
|
| 225 |
+
`[a, a+1, a+2, \ldots, x]`
|
| 226 |
+
``arange(a, b, h)``
|
| 227 |
+
`[a, a+h, a+h, \ldots, x]`
|
| 228 |
+
|
| 229 |
+
where `b-1 \le x < b` (in the third case, `b-h \le x < b`).
|
| 230 |
+
|
| 231 |
+
Like Python's :func:`~mpmath.range`, the endpoint is not included. To
|
| 232 |
+
produce ranges where the endpoint is included, :func:`~mpmath.linspace`
|
| 233 |
+
is more convenient.
|
| 234 |
+
|
| 235 |
+
**Examples**
|
| 236 |
+
|
| 237 |
+
>>> from mpmath import *
|
| 238 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 239 |
+
>>> arange(4)
|
| 240 |
+
[mpf('0.0'), mpf('1.0'), mpf('2.0'), mpf('3.0')]
|
| 241 |
+
>>> arange(1, 2, 0.25)
|
| 242 |
+
[mpf('1.0'), mpf('1.25'), mpf('1.5'), mpf('1.75')]
|
| 243 |
+
>>> arange(1, -1, -0.75)
|
| 244 |
+
[mpf('1.0'), mpf('0.25'), mpf('-0.5')]
|
| 245 |
+
|
| 246 |
+
"""
|
| 247 |
+
if not len(args) <= 3:
|
| 248 |
+
raise TypeError('arange expected at most 3 arguments, got %i'
|
| 249 |
+
% len(args))
|
| 250 |
+
if not len(args) >= 1:
|
| 251 |
+
raise TypeError('arange expected at least 1 argument, got %i'
|
| 252 |
+
% len(args))
|
| 253 |
+
# set default
|
| 254 |
+
a = 0
|
| 255 |
+
dt = 1
|
| 256 |
+
# interpret arguments
|
| 257 |
+
if len(args) == 1:
|
| 258 |
+
b = args[0]
|
| 259 |
+
elif len(args) >= 2:
|
| 260 |
+
a = args[0]
|
| 261 |
+
b = args[1]
|
| 262 |
+
if len(args) == 3:
|
| 263 |
+
dt = args[2]
|
| 264 |
+
a, b, dt = ctx.mpf(a), ctx.mpf(b), ctx.mpf(dt)
|
| 265 |
+
assert a + dt != a, 'dt is too small and would cause an infinite loop'
|
| 266 |
+
# adapt code for sign of dt
|
| 267 |
+
if a > b:
|
| 268 |
+
if dt > 0:
|
| 269 |
+
return []
|
| 270 |
+
op = gt
|
| 271 |
+
else:
|
| 272 |
+
if dt < 0:
|
| 273 |
+
return []
|
| 274 |
+
op = lt
|
| 275 |
+
# create list
|
| 276 |
+
result = []
|
| 277 |
+
i = 0
|
| 278 |
+
t = a
|
| 279 |
+
while 1:
|
| 280 |
+
t = a + dt*i
|
| 281 |
+
i += 1
|
| 282 |
+
if op(t, b):
|
| 283 |
+
result.append(t)
|
| 284 |
+
else:
|
| 285 |
+
break
|
| 286 |
+
return result
|
| 287 |
+
|
| 288 |
+
def linspace(ctx, *args, **kwargs):
|
| 289 |
+
"""
|
| 290 |
+
``linspace(a, b, n)`` returns a list of `n` evenly spaced
|
| 291 |
+
samples from `a` to `b`. The syntax ``linspace(mpi(a,b), n)``
|
| 292 |
+
is also valid.
|
| 293 |
+
|
| 294 |
+
This function is often more convenient than :func:`~mpmath.arange`
|
| 295 |
+
for partitioning an interval into subintervals, since
|
| 296 |
+
the endpoint is included::
|
| 297 |
+
|
| 298 |
+
>>> from mpmath import *
|
| 299 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 300 |
+
>>> linspace(1, 4, 4)
|
| 301 |
+
[mpf('1.0'), mpf('2.0'), mpf('3.0'), mpf('4.0')]
|
| 302 |
+
|
| 303 |
+
You may also provide the keyword argument ``endpoint=False``::
|
| 304 |
+
|
| 305 |
+
>>> linspace(1, 4, 4, endpoint=False)
|
| 306 |
+
[mpf('1.0'), mpf('1.75'), mpf('2.5'), mpf('3.25')]
|
| 307 |
+
|
| 308 |
+
"""
|
| 309 |
+
if len(args) == 3:
|
| 310 |
+
a = ctx.mpf(args[0])
|
| 311 |
+
b = ctx.mpf(args[1])
|
| 312 |
+
n = int(args[2])
|
| 313 |
+
elif len(args) == 2:
|
| 314 |
+
assert hasattr(args[0], '_mpi_')
|
| 315 |
+
a = args[0].a
|
| 316 |
+
b = args[0].b
|
| 317 |
+
n = int(args[1])
|
| 318 |
+
else:
|
| 319 |
+
raise TypeError('linspace expected 2 or 3 arguments, got %i' \
|
| 320 |
+
% len(args))
|
| 321 |
+
if n < 1:
|
| 322 |
+
raise ValueError('n must be greater than 0')
|
| 323 |
+
if not 'endpoint' in kwargs or kwargs['endpoint']:
|
| 324 |
+
if n == 1:
|
| 325 |
+
return [ctx.mpf(a)]
|
| 326 |
+
step = (b - a) / ctx.mpf(n - 1)
|
| 327 |
+
y = [i*step + a for i in xrange(n)]
|
| 328 |
+
y[-1] = b
|
| 329 |
+
else:
|
| 330 |
+
step = (b - a) / ctx.mpf(n)
|
| 331 |
+
y = [i*step + a for i in xrange(n)]
|
| 332 |
+
return y
|
| 333 |
+
|
| 334 |
+
def cos_sin(ctx, z, **kwargs):
|
| 335 |
+
return ctx.cos(z, **kwargs), ctx.sin(z, **kwargs)
|
| 336 |
+
|
| 337 |
+
def cospi_sinpi(ctx, z, **kwargs):
|
| 338 |
+
return ctx.cospi(z, **kwargs), ctx.sinpi(z, **kwargs)
|
| 339 |
+
|
| 340 |
+
def _default_hyper_maxprec(ctx, p):
|
| 341 |
+
return int(1000 * p**0.25 + 4*p)
|
| 342 |
+
|
| 343 |
+
_gcd = staticmethod(libmp.gcd)
|
| 344 |
+
list_primes = staticmethod(libmp.list_primes)
|
| 345 |
+
isprime = staticmethod(libmp.isprime)
|
| 346 |
+
bernfrac = staticmethod(libmp.bernfrac)
|
| 347 |
+
moebius = staticmethod(libmp.moebius)
|
| 348 |
+
_ifac = staticmethod(libmp.ifac)
|
| 349 |
+
_eulernum = staticmethod(libmp.eulernum)
|
| 350 |
+
_stirling1 = staticmethod(libmp.stirling1)
|
| 351 |
+
_stirling2 = staticmethod(libmp.stirling2)
|
| 352 |
+
|
| 353 |
+
def sum_accurately(ctx, terms, check_step=1):
|
| 354 |
+
prec = ctx.prec
|
| 355 |
+
try:
|
| 356 |
+
extraprec = 10
|
| 357 |
+
while 1:
|
| 358 |
+
ctx.prec = prec + extraprec + 5
|
| 359 |
+
max_mag = ctx.ninf
|
| 360 |
+
s = ctx.zero
|
| 361 |
+
k = 0
|
| 362 |
+
for term in terms():
|
| 363 |
+
s += term
|
| 364 |
+
if (not k % check_step) and term:
|
| 365 |
+
term_mag = ctx.mag(term)
|
| 366 |
+
max_mag = max(max_mag, term_mag)
|
| 367 |
+
sum_mag = ctx.mag(s)
|
| 368 |
+
if sum_mag - term_mag > ctx.prec:
|
| 369 |
+
break
|
| 370 |
+
k += 1
|
| 371 |
+
cancellation = max_mag - sum_mag
|
| 372 |
+
if cancellation != cancellation:
|
| 373 |
+
break
|
| 374 |
+
if cancellation < extraprec or ctx._fixed_precision:
|
| 375 |
+
break
|
| 376 |
+
extraprec += min(ctx.prec, cancellation)
|
| 377 |
+
return s
|
| 378 |
+
finally:
|
| 379 |
+
ctx.prec = prec
|
| 380 |
+
|
| 381 |
+
def mul_accurately(ctx, factors, check_step=1):
|
| 382 |
+
prec = ctx.prec
|
| 383 |
+
try:
|
| 384 |
+
extraprec = 10
|
| 385 |
+
while 1:
|
| 386 |
+
ctx.prec = prec + extraprec + 5
|
| 387 |
+
max_mag = ctx.ninf
|
| 388 |
+
one = ctx.one
|
| 389 |
+
s = one
|
| 390 |
+
k = 0
|
| 391 |
+
for factor in factors():
|
| 392 |
+
s *= factor
|
| 393 |
+
term = factor - one
|
| 394 |
+
if (not k % check_step):
|
| 395 |
+
term_mag = ctx.mag(term)
|
| 396 |
+
max_mag = max(max_mag, term_mag)
|
| 397 |
+
sum_mag = ctx.mag(s-one)
|
| 398 |
+
#if sum_mag - term_mag > ctx.prec:
|
| 399 |
+
# break
|
| 400 |
+
if -term_mag > ctx.prec:
|
| 401 |
+
break
|
| 402 |
+
k += 1
|
| 403 |
+
cancellation = max_mag - sum_mag
|
| 404 |
+
if cancellation != cancellation:
|
| 405 |
+
break
|
| 406 |
+
if cancellation < extraprec or ctx._fixed_precision:
|
| 407 |
+
break
|
| 408 |
+
extraprec += min(ctx.prec, cancellation)
|
| 409 |
+
return s
|
| 410 |
+
finally:
|
| 411 |
+
ctx.prec = prec
|
| 412 |
+
|
| 413 |
+
def power(ctx, x, y):
|
| 414 |
+
r"""Converts `x` and `y` to mpmath numbers and evaluates
|
| 415 |
+
`x^y = \exp(y \log(x))`::
|
| 416 |
+
|
| 417 |
+
>>> from mpmath import *
|
| 418 |
+
>>> mp.dps = 30; mp.pretty = True
|
| 419 |
+
>>> power(2, 0.5)
|
| 420 |
+
1.41421356237309504880168872421
|
| 421 |
+
|
| 422 |
+
This shows the leading few digits of a large Mersenne prime
|
| 423 |
+
(performing the exact calculation ``2**43112609-1`` and
|
| 424 |
+
displaying the result in Python would be very slow)::
|
| 425 |
+
|
| 426 |
+
>>> power(2, 43112609)-1
|
| 427 |
+
3.16470269330255923143453723949e+12978188
|
| 428 |
+
"""
|
| 429 |
+
return ctx.convert(x) ** ctx.convert(y)
|
| 430 |
+
|
| 431 |
+
def _zeta_int(ctx, n):
|
| 432 |
+
return ctx.zeta(n)
|
| 433 |
+
|
| 434 |
+
def maxcalls(ctx, f, N):
|
| 435 |
+
"""
|
| 436 |
+
Return a wrapped copy of *f* that raises ``NoConvergence`` when *f*
|
| 437 |
+
has been called more than *N* times::
|
| 438 |
+
|
| 439 |
+
>>> from mpmath import *
|
| 440 |
+
>>> mp.dps = 15
|
| 441 |
+
>>> f = maxcalls(sin, 10)
|
| 442 |
+
>>> print(sum(f(n) for n in range(10)))
|
| 443 |
+
1.95520948210738
|
| 444 |
+
>>> f(10) # doctest: +IGNORE_EXCEPTION_DETAIL
|
| 445 |
+
Traceback (most recent call last):
|
| 446 |
+
...
|
| 447 |
+
NoConvergence: maxcalls: function evaluated 10 times
|
| 448 |
+
|
| 449 |
+
"""
|
| 450 |
+
counter = [0]
|
| 451 |
+
def f_maxcalls_wrapped(*args, **kwargs):
|
| 452 |
+
counter[0] += 1
|
| 453 |
+
if counter[0] > N:
|
| 454 |
+
raise ctx.NoConvergence("maxcalls: function evaluated %i times" % N)
|
| 455 |
+
return f(*args, **kwargs)
|
| 456 |
+
return f_maxcalls_wrapped
|
| 457 |
+
|
| 458 |
+
def memoize(ctx, f):
|
| 459 |
+
"""
|
| 460 |
+
Return a wrapped copy of *f* that caches computed values, i.e.
|
| 461 |
+
a memoized copy of *f*. Values are only reused if the cached precision
|
| 462 |
+
is equal to or higher than the working precision::
|
| 463 |
+
|
| 464 |
+
>>> from mpmath import *
|
| 465 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 466 |
+
>>> f = memoize(maxcalls(sin, 1))
|
| 467 |
+
>>> f(2)
|
| 468 |
+
0.909297426825682
|
| 469 |
+
>>> f(2)
|
| 470 |
+
0.909297426825682
|
| 471 |
+
>>> mp.dps = 25
|
| 472 |
+
>>> f(2) # doctest: +IGNORE_EXCEPTION_DETAIL
|
| 473 |
+
Traceback (most recent call last):
|
| 474 |
+
...
|
| 475 |
+
NoConvergence: maxcalls: function evaluated 1 times
|
| 476 |
+
|
| 477 |
+
"""
|
| 478 |
+
f_cache = {}
|
| 479 |
+
def f_cached(*args, **kwargs):
|
| 480 |
+
if kwargs:
|
| 481 |
+
key = args, tuple(kwargs.items())
|
| 482 |
+
else:
|
| 483 |
+
key = args
|
| 484 |
+
prec = ctx.prec
|
| 485 |
+
if key in f_cache:
|
| 486 |
+
cprec, cvalue = f_cache[key]
|
| 487 |
+
if cprec >= prec:
|
| 488 |
+
return +cvalue
|
| 489 |
+
value = f(*args, **kwargs)
|
| 490 |
+
f_cache[key] = (prec, value)
|
| 491 |
+
return value
|
| 492 |
+
f_cached.__name__ = f.__name__
|
| 493 |
+
f_cached.__doc__ = f.__doc__
|
| 494 |
+
return f_cached
|
.venv/lib/python3.11/site-packages/mpmath/ctx_fp.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .ctx_base import StandardBaseContext
|
| 2 |
+
|
| 3 |
+
import math
|
| 4 |
+
import cmath
|
| 5 |
+
from . import math2
|
| 6 |
+
|
| 7 |
+
from . import function_docs
|
| 8 |
+
|
| 9 |
+
from .libmp import mpf_bernoulli, to_float, int_types
|
| 10 |
+
from . import libmp
|
| 11 |
+
|
| 12 |
+
class FPContext(StandardBaseContext):
|
| 13 |
+
"""
|
| 14 |
+
Context for fast low-precision arithmetic (53-bit precision, giving at most
|
| 15 |
+
about 15-digit accuracy), using Python's builtin float and complex.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
def __init__(ctx):
|
| 19 |
+
StandardBaseContext.__init__(ctx)
|
| 20 |
+
|
| 21 |
+
# Override SpecialFunctions implementation
|
| 22 |
+
ctx.loggamma = math2.loggamma
|
| 23 |
+
ctx._bernoulli_cache = {}
|
| 24 |
+
ctx.pretty = False
|
| 25 |
+
|
| 26 |
+
ctx._init_aliases()
|
| 27 |
+
|
| 28 |
+
_mpq = lambda cls, x: float(x[0])/x[1]
|
| 29 |
+
|
| 30 |
+
NoConvergence = libmp.NoConvergence
|
| 31 |
+
|
| 32 |
+
def _get_prec(ctx): return 53
|
| 33 |
+
def _set_prec(ctx, p): return
|
| 34 |
+
def _get_dps(ctx): return 15
|
| 35 |
+
def _set_dps(ctx, p): return
|
| 36 |
+
|
| 37 |
+
_fixed_precision = True
|
| 38 |
+
|
| 39 |
+
prec = property(_get_prec, _set_prec)
|
| 40 |
+
dps = property(_get_dps, _set_dps)
|
| 41 |
+
|
| 42 |
+
zero = 0.0
|
| 43 |
+
one = 1.0
|
| 44 |
+
eps = math2.EPS
|
| 45 |
+
inf = math2.INF
|
| 46 |
+
ninf = math2.NINF
|
| 47 |
+
nan = math2.NAN
|
| 48 |
+
j = 1j
|
| 49 |
+
|
| 50 |
+
# Called by SpecialFunctions.__init__()
|
| 51 |
+
@classmethod
|
| 52 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 53 |
+
if wrap:
|
| 54 |
+
def f_wrapped(ctx, *args, **kwargs):
|
| 55 |
+
convert = ctx.convert
|
| 56 |
+
args = [convert(a) for a in args]
|
| 57 |
+
return f(ctx, *args, **kwargs)
|
| 58 |
+
else:
|
| 59 |
+
f_wrapped = f
|
| 60 |
+
f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__)
|
| 61 |
+
setattr(cls, name, f_wrapped)
|
| 62 |
+
|
| 63 |
+
def bernoulli(ctx, n):
|
| 64 |
+
cache = ctx._bernoulli_cache
|
| 65 |
+
if n in cache:
|
| 66 |
+
return cache[n]
|
| 67 |
+
cache[n] = to_float(mpf_bernoulli(n, 53, 'n'), strict=True)
|
| 68 |
+
return cache[n]
|
| 69 |
+
|
| 70 |
+
pi = math2.pi
|
| 71 |
+
e = math2.e
|
| 72 |
+
euler = math2.euler
|
| 73 |
+
sqrt2 = 1.4142135623730950488
|
| 74 |
+
sqrt5 = 2.2360679774997896964
|
| 75 |
+
phi = 1.6180339887498948482
|
| 76 |
+
ln2 = 0.69314718055994530942
|
| 77 |
+
ln10 = 2.302585092994045684
|
| 78 |
+
euler = 0.57721566490153286061
|
| 79 |
+
catalan = 0.91596559417721901505
|
| 80 |
+
khinchin = 2.6854520010653064453
|
| 81 |
+
apery = 1.2020569031595942854
|
| 82 |
+
glaisher = 1.2824271291006226369
|
| 83 |
+
|
| 84 |
+
absmin = absmax = abs
|
| 85 |
+
|
| 86 |
+
def is_special(ctx, x):
|
| 87 |
+
return x - x != 0.0
|
| 88 |
+
|
| 89 |
+
def isnan(ctx, x):
|
| 90 |
+
return x != x
|
| 91 |
+
|
| 92 |
+
def isinf(ctx, x):
|
| 93 |
+
return abs(x) == math2.INF
|
| 94 |
+
|
| 95 |
+
def isnormal(ctx, x):
|
| 96 |
+
if x:
|
| 97 |
+
return x - x == 0.0
|
| 98 |
+
return False
|
| 99 |
+
|
| 100 |
+
def isnpint(ctx, x):
|
| 101 |
+
if type(x) is complex:
|
| 102 |
+
if x.imag:
|
| 103 |
+
return False
|
| 104 |
+
x = x.real
|
| 105 |
+
return x <= 0.0 and round(x) == x
|
| 106 |
+
|
| 107 |
+
mpf = float
|
| 108 |
+
mpc = complex
|
| 109 |
+
|
| 110 |
+
def convert(ctx, x):
|
| 111 |
+
try:
|
| 112 |
+
return float(x)
|
| 113 |
+
except:
|
| 114 |
+
return complex(x)
|
| 115 |
+
|
| 116 |
+
power = staticmethod(math2.pow)
|
| 117 |
+
sqrt = staticmethod(math2.sqrt)
|
| 118 |
+
exp = staticmethod(math2.exp)
|
| 119 |
+
ln = log = staticmethod(math2.log)
|
| 120 |
+
cos = staticmethod(math2.cos)
|
| 121 |
+
sin = staticmethod(math2.sin)
|
| 122 |
+
tan = staticmethod(math2.tan)
|
| 123 |
+
cos_sin = staticmethod(math2.cos_sin)
|
| 124 |
+
acos = staticmethod(math2.acos)
|
| 125 |
+
asin = staticmethod(math2.asin)
|
| 126 |
+
atan = staticmethod(math2.atan)
|
| 127 |
+
cosh = staticmethod(math2.cosh)
|
| 128 |
+
sinh = staticmethod(math2.sinh)
|
| 129 |
+
tanh = staticmethod(math2.tanh)
|
| 130 |
+
gamma = staticmethod(math2.gamma)
|
| 131 |
+
rgamma = staticmethod(math2.rgamma)
|
| 132 |
+
fac = factorial = staticmethod(math2.factorial)
|
| 133 |
+
floor = staticmethod(math2.floor)
|
| 134 |
+
ceil = staticmethod(math2.ceil)
|
| 135 |
+
cospi = staticmethod(math2.cospi)
|
| 136 |
+
sinpi = staticmethod(math2.sinpi)
|
| 137 |
+
cbrt = staticmethod(math2.cbrt)
|
| 138 |
+
_nthroot = staticmethod(math2.nthroot)
|
| 139 |
+
_ei = staticmethod(math2.ei)
|
| 140 |
+
_e1 = staticmethod(math2.e1)
|
| 141 |
+
_zeta = _zeta_int = staticmethod(math2.zeta)
|
| 142 |
+
|
| 143 |
+
# XXX: math2
|
| 144 |
+
def arg(ctx, z):
|
| 145 |
+
z = complex(z)
|
| 146 |
+
return math.atan2(z.imag, z.real)
|
| 147 |
+
|
| 148 |
+
def expj(ctx, x):
|
| 149 |
+
return ctx.exp(ctx.j*x)
|
| 150 |
+
|
| 151 |
+
def expjpi(ctx, x):
|
| 152 |
+
return ctx.exp(ctx.j*ctx.pi*x)
|
| 153 |
+
|
| 154 |
+
ldexp = math.ldexp
|
| 155 |
+
frexp = math.frexp
|
| 156 |
+
|
| 157 |
+
def mag(ctx, z):
|
| 158 |
+
if z:
|
| 159 |
+
return ctx.frexp(abs(z))[1]
|
| 160 |
+
return ctx.ninf
|
| 161 |
+
|
| 162 |
+
def isint(ctx, z):
|
| 163 |
+
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5
|
| 164 |
+
if z.imag:
|
| 165 |
+
return False
|
| 166 |
+
z = z.real
|
| 167 |
+
try:
|
| 168 |
+
return z == int(z)
|
| 169 |
+
except:
|
| 170 |
+
return False
|
| 171 |
+
|
| 172 |
+
def nint_distance(ctx, z):
|
| 173 |
+
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5
|
| 174 |
+
n = round(z.real)
|
| 175 |
+
else:
|
| 176 |
+
n = round(z)
|
| 177 |
+
if n == z:
|
| 178 |
+
return n, ctx.ninf
|
| 179 |
+
return n, ctx.mag(abs(z-n))
|
| 180 |
+
|
| 181 |
+
def _convert_param(ctx, z):
|
| 182 |
+
if type(z) is tuple:
|
| 183 |
+
p, q = z
|
| 184 |
+
return ctx.mpf(p) / q, 'R'
|
| 185 |
+
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5
|
| 186 |
+
intz = int(z.real)
|
| 187 |
+
else:
|
| 188 |
+
intz = int(z)
|
| 189 |
+
if z == intz:
|
| 190 |
+
return intz, 'Z'
|
| 191 |
+
return z, 'R'
|
| 192 |
+
|
| 193 |
+
def _is_real_type(ctx, z):
|
| 194 |
+
return isinstance(z, float) or isinstance(z, int_types)
|
| 195 |
+
|
| 196 |
+
def _is_complex_type(ctx, z):
|
| 197 |
+
return isinstance(z, complex)
|
| 198 |
+
|
| 199 |
+
def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs):
|
| 200 |
+
coeffs = list(coeffs)
|
| 201 |
+
num = range(p)
|
| 202 |
+
den = range(p,p+q)
|
| 203 |
+
tol = ctx.eps
|
| 204 |
+
s = t = 1.0
|
| 205 |
+
k = 0
|
| 206 |
+
while 1:
|
| 207 |
+
for i in num: t *= (coeffs[i]+k)
|
| 208 |
+
for i in den: t /= (coeffs[i]+k)
|
| 209 |
+
k += 1; t /= k; t *= z; s += t
|
| 210 |
+
if abs(t) < tol:
|
| 211 |
+
return s
|
| 212 |
+
if k > maxterms:
|
| 213 |
+
raise ctx.NoConvergence
|
| 214 |
+
|
| 215 |
+
def atan2(ctx, x, y):
|
| 216 |
+
return math.atan2(x, y)
|
| 217 |
+
|
| 218 |
+
def psi(ctx, m, z):
|
| 219 |
+
m = int(m)
|
| 220 |
+
if m == 0:
|
| 221 |
+
return ctx.digamma(z)
|
| 222 |
+
return (-1)**(m+1) * ctx.fac(m) * ctx.zeta(m+1, z)
|
| 223 |
+
|
| 224 |
+
digamma = staticmethod(math2.digamma)
|
| 225 |
+
|
| 226 |
+
def harmonic(ctx, x):
|
| 227 |
+
x = ctx.convert(x)
|
| 228 |
+
if x == 0 or x == 1:
|
| 229 |
+
return x
|
| 230 |
+
return ctx.digamma(x+1) + ctx.euler
|
| 231 |
+
|
| 232 |
+
nstr = str
|
| 233 |
+
|
| 234 |
+
def to_fixed(ctx, x, prec):
|
| 235 |
+
return int(math.ldexp(x, prec))
|
| 236 |
+
|
| 237 |
+
def rand(ctx):
|
| 238 |
+
import random
|
| 239 |
+
return random.random()
|
| 240 |
+
|
| 241 |
+
_erf = staticmethod(math2.erf)
|
| 242 |
+
_erfc = staticmethod(math2.erfc)
|
| 243 |
+
|
| 244 |
+
def sum_accurately(ctx, terms, check_step=1):
|
| 245 |
+
s = ctx.zero
|
| 246 |
+
k = 0
|
| 247 |
+
for term in terms():
|
| 248 |
+
s += term
|
| 249 |
+
if (not k % check_step) and term:
|
| 250 |
+
if abs(term) <= 1e-18*abs(s):
|
| 251 |
+
break
|
| 252 |
+
k += 1
|
| 253 |
+
return s
|
.venv/lib/python3.11/site-packages/mpmath/ctx_iv.py
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import operator
|
| 2 |
+
|
| 3 |
+
from . import libmp
|
| 4 |
+
|
| 5 |
+
from .libmp.backend import basestring
|
| 6 |
+
|
| 7 |
+
from .libmp import (
|
| 8 |
+
int_types, MPZ_ONE,
|
| 9 |
+
prec_to_dps, dps_to_prec, repr_dps,
|
| 10 |
+
round_floor, round_ceiling,
|
| 11 |
+
fzero, finf, fninf, fnan,
|
| 12 |
+
mpf_le, mpf_neg,
|
| 13 |
+
from_int, from_float, from_str, from_rational,
|
| 14 |
+
mpi_mid, mpi_delta, mpi_str,
|
| 15 |
+
mpi_abs, mpi_pos, mpi_neg, mpi_add, mpi_sub,
|
| 16 |
+
mpi_mul, mpi_div, mpi_pow_int, mpi_pow,
|
| 17 |
+
mpi_from_str,
|
| 18 |
+
mpci_pos, mpci_neg, mpci_add, mpci_sub, mpci_mul, mpci_div, mpci_pow,
|
| 19 |
+
mpci_abs, mpci_pow, mpci_exp, mpci_log,
|
| 20 |
+
ComplexResult,
|
| 21 |
+
mpf_hash, mpc_hash)
|
| 22 |
+
from .matrices.matrices import _matrix
|
| 23 |
+
|
| 24 |
+
mpi_zero = (fzero, fzero)
|
| 25 |
+
|
| 26 |
+
from .ctx_base import StandardBaseContext
|
| 27 |
+
|
| 28 |
+
new = object.__new__
|
| 29 |
+
|
| 30 |
+
def convert_mpf_(x, prec, rounding):
|
| 31 |
+
if hasattr(x, "_mpf_"): return x._mpf_
|
| 32 |
+
if isinstance(x, int_types): return from_int(x, prec, rounding)
|
| 33 |
+
if isinstance(x, float): return from_float(x, prec, rounding)
|
| 34 |
+
if isinstance(x, basestring): return from_str(x, prec, rounding)
|
| 35 |
+
raise NotImplementedError
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class ivmpf(object):
|
| 39 |
+
"""
|
| 40 |
+
Interval arithmetic class. Precision is controlled by iv.prec.
|
| 41 |
+
"""
|
| 42 |
+
|
| 43 |
+
def __new__(cls, x=0):
|
| 44 |
+
return cls.ctx.convert(x)
|
| 45 |
+
|
| 46 |
+
def cast(self, cls, f_convert):
|
| 47 |
+
a, b = self._mpi_
|
| 48 |
+
if a == b:
|
| 49 |
+
return cls(f_convert(a))
|
| 50 |
+
raise ValueError
|
| 51 |
+
|
| 52 |
+
def __int__(self):
|
| 53 |
+
return self.cast(int, libmp.to_int)
|
| 54 |
+
|
| 55 |
+
def __float__(self):
|
| 56 |
+
return self.cast(float, libmp.to_float)
|
| 57 |
+
|
| 58 |
+
def __complex__(self):
|
| 59 |
+
return self.cast(complex, libmp.to_float)
|
| 60 |
+
|
| 61 |
+
def __hash__(self):
|
| 62 |
+
a, b = self._mpi_
|
| 63 |
+
if a == b:
|
| 64 |
+
return mpf_hash(a)
|
| 65 |
+
else:
|
| 66 |
+
return hash(self._mpi_)
|
| 67 |
+
|
| 68 |
+
@property
|
| 69 |
+
def real(self): return self
|
| 70 |
+
|
| 71 |
+
@property
|
| 72 |
+
def imag(self): return self.ctx.zero
|
| 73 |
+
|
| 74 |
+
def conjugate(self): return self
|
| 75 |
+
|
| 76 |
+
@property
|
| 77 |
+
def a(self):
|
| 78 |
+
a, b = self._mpi_
|
| 79 |
+
return self.ctx.make_mpf((a, a))
|
| 80 |
+
|
| 81 |
+
@property
|
| 82 |
+
def b(self):
|
| 83 |
+
a, b = self._mpi_
|
| 84 |
+
return self.ctx.make_mpf((b, b))
|
| 85 |
+
|
| 86 |
+
@property
|
| 87 |
+
def mid(self):
|
| 88 |
+
ctx = self.ctx
|
| 89 |
+
v = mpi_mid(self._mpi_, ctx.prec)
|
| 90 |
+
return ctx.make_mpf((v, v))
|
| 91 |
+
|
| 92 |
+
@property
|
| 93 |
+
def delta(self):
|
| 94 |
+
ctx = self.ctx
|
| 95 |
+
v = mpi_delta(self._mpi_, ctx.prec)
|
| 96 |
+
return ctx.make_mpf((v,v))
|
| 97 |
+
|
| 98 |
+
@property
|
| 99 |
+
def _mpci_(self):
|
| 100 |
+
return self._mpi_, mpi_zero
|
| 101 |
+
|
| 102 |
+
def _compare(*args):
|
| 103 |
+
raise TypeError("no ordering relation is defined for intervals")
|
| 104 |
+
|
| 105 |
+
__gt__ = _compare
|
| 106 |
+
__le__ = _compare
|
| 107 |
+
__gt__ = _compare
|
| 108 |
+
__ge__ = _compare
|
| 109 |
+
|
| 110 |
+
def __contains__(self, t):
|
| 111 |
+
t = self.ctx.mpf(t)
|
| 112 |
+
return (self.a <= t.a) and (t.b <= self.b)
|
| 113 |
+
|
| 114 |
+
def __str__(self):
|
| 115 |
+
return mpi_str(self._mpi_, self.ctx.prec)
|
| 116 |
+
|
| 117 |
+
def __repr__(self):
|
| 118 |
+
if self.ctx.pretty:
|
| 119 |
+
return str(self)
|
| 120 |
+
a, b = self._mpi_
|
| 121 |
+
n = repr_dps(self.ctx.prec)
|
| 122 |
+
a = libmp.to_str(a, n)
|
| 123 |
+
b = libmp.to_str(b, n)
|
| 124 |
+
return "mpi(%r, %r)" % (a, b)
|
| 125 |
+
|
| 126 |
+
def _compare(s, t, cmpfun):
|
| 127 |
+
if not hasattr(t, "_mpi_"):
|
| 128 |
+
try:
|
| 129 |
+
t = s.ctx.convert(t)
|
| 130 |
+
except:
|
| 131 |
+
return NotImplemented
|
| 132 |
+
return cmpfun(s._mpi_, t._mpi_)
|
| 133 |
+
|
| 134 |
+
def __eq__(s, t): return s._compare(t, libmp.mpi_eq)
|
| 135 |
+
def __ne__(s, t): return s._compare(t, libmp.mpi_ne)
|
| 136 |
+
def __lt__(s, t): return s._compare(t, libmp.mpi_lt)
|
| 137 |
+
def __le__(s, t): return s._compare(t, libmp.mpi_le)
|
| 138 |
+
def __gt__(s, t): return s._compare(t, libmp.mpi_gt)
|
| 139 |
+
def __ge__(s, t): return s._compare(t, libmp.mpi_ge)
|
| 140 |
+
|
| 141 |
+
def __abs__(self):
|
| 142 |
+
return self.ctx.make_mpf(mpi_abs(self._mpi_, self.ctx.prec))
|
| 143 |
+
def __pos__(self):
|
| 144 |
+
return self.ctx.make_mpf(mpi_pos(self._mpi_, self.ctx.prec))
|
| 145 |
+
def __neg__(self):
|
| 146 |
+
return self.ctx.make_mpf(mpi_neg(self._mpi_, self.ctx.prec))
|
| 147 |
+
|
| 148 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 149 |
+
return s.ctx.almosteq(s, t, rel_eps, abs_eps)
|
| 150 |
+
|
| 151 |
+
class ivmpc(object):
|
| 152 |
+
|
| 153 |
+
def __new__(cls, re=0, im=0):
|
| 154 |
+
re = cls.ctx.convert(re)
|
| 155 |
+
im = cls.ctx.convert(im)
|
| 156 |
+
y = new(cls)
|
| 157 |
+
y._mpci_ = re._mpi_, im._mpi_
|
| 158 |
+
return y
|
| 159 |
+
|
| 160 |
+
def __hash__(self):
|
| 161 |
+
(a, b), (c,d) = self._mpci_
|
| 162 |
+
if a == b and c == d:
|
| 163 |
+
return mpc_hash((a, c))
|
| 164 |
+
else:
|
| 165 |
+
return hash(self._mpci_)
|
| 166 |
+
|
| 167 |
+
def __repr__(s):
|
| 168 |
+
if s.ctx.pretty:
|
| 169 |
+
return str(s)
|
| 170 |
+
return "iv.mpc(%s, %s)" % (repr(s.real), repr(s.imag))
|
| 171 |
+
|
| 172 |
+
def __str__(s):
|
| 173 |
+
return "(%s + %s*j)" % (str(s.real), str(s.imag))
|
| 174 |
+
|
| 175 |
+
@property
|
| 176 |
+
def a(self):
|
| 177 |
+
(a, b), (c,d) = self._mpci_
|
| 178 |
+
return self.ctx.make_mpf((a, a))
|
| 179 |
+
|
| 180 |
+
@property
|
| 181 |
+
def b(self):
|
| 182 |
+
(a, b), (c,d) = self._mpci_
|
| 183 |
+
return self.ctx.make_mpf((b, b))
|
| 184 |
+
|
| 185 |
+
@property
|
| 186 |
+
def c(self):
|
| 187 |
+
(a, b), (c,d) = self._mpci_
|
| 188 |
+
return self.ctx.make_mpf((c, c))
|
| 189 |
+
|
| 190 |
+
@property
|
| 191 |
+
def d(self):
|
| 192 |
+
(a, b), (c,d) = self._mpci_
|
| 193 |
+
return self.ctx.make_mpf((d, d))
|
| 194 |
+
|
| 195 |
+
@property
|
| 196 |
+
def real(s):
|
| 197 |
+
return s.ctx.make_mpf(s._mpci_[0])
|
| 198 |
+
|
| 199 |
+
@property
|
| 200 |
+
def imag(s):
|
| 201 |
+
return s.ctx.make_mpf(s._mpci_[1])
|
| 202 |
+
|
| 203 |
+
def conjugate(s):
|
| 204 |
+
a, b = s._mpci_
|
| 205 |
+
return s.ctx.make_mpc((a, mpf_neg(b)))
|
| 206 |
+
|
| 207 |
+
def overlap(s, t):
|
| 208 |
+
t = s.ctx.convert(t)
|
| 209 |
+
real_overlap = (s.a <= t.a <= s.b) or (s.a <= t.b <= s.b) or (t.a <= s.a <= t.b) or (t.a <= s.b <= t.b)
|
| 210 |
+
imag_overlap = (s.c <= t.c <= s.d) or (s.c <= t.d <= s.d) or (t.c <= s.c <= t.d) or (t.c <= s.d <= t.d)
|
| 211 |
+
return real_overlap and imag_overlap
|
| 212 |
+
|
| 213 |
+
def __contains__(s, t):
|
| 214 |
+
t = s.ctx.convert(t)
|
| 215 |
+
return t.real in s.real and t.imag in s.imag
|
| 216 |
+
|
| 217 |
+
def _compare(s, t, ne=False):
|
| 218 |
+
if not isinstance(t, s.ctx._types):
|
| 219 |
+
try:
|
| 220 |
+
t = s.ctx.convert(t)
|
| 221 |
+
except:
|
| 222 |
+
return NotImplemented
|
| 223 |
+
if hasattr(t, '_mpi_'):
|
| 224 |
+
tval = t._mpi_, mpi_zero
|
| 225 |
+
elif hasattr(t, '_mpci_'):
|
| 226 |
+
tval = t._mpci_
|
| 227 |
+
if ne:
|
| 228 |
+
return s._mpci_ != tval
|
| 229 |
+
return s._mpci_ == tval
|
| 230 |
+
|
| 231 |
+
def __eq__(s, t): return s._compare(t)
|
| 232 |
+
def __ne__(s, t): return s._compare(t, True)
|
| 233 |
+
|
| 234 |
+
def __lt__(s, t): raise TypeError("complex intervals cannot be ordered")
|
| 235 |
+
__le__ = __gt__ = __ge__ = __lt__
|
| 236 |
+
|
| 237 |
+
def __neg__(s): return s.ctx.make_mpc(mpci_neg(s._mpci_, s.ctx.prec))
|
| 238 |
+
def __pos__(s): return s.ctx.make_mpc(mpci_pos(s._mpci_, s.ctx.prec))
|
| 239 |
+
def __abs__(s): return s.ctx.make_mpf(mpci_abs(s._mpci_, s.ctx.prec))
|
| 240 |
+
|
| 241 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 242 |
+
return s.ctx.almosteq(s, t, rel_eps, abs_eps)
|
| 243 |
+
|
| 244 |
+
def _binary_op(f_real, f_complex):
|
| 245 |
+
def g_complex(ctx, sval, tval):
|
| 246 |
+
return ctx.make_mpc(f_complex(sval, tval, ctx.prec))
|
| 247 |
+
def g_real(ctx, sval, tval):
|
| 248 |
+
try:
|
| 249 |
+
return ctx.make_mpf(f_real(sval, tval, ctx.prec))
|
| 250 |
+
except ComplexResult:
|
| 251 |
+
sval = (sval, mpi_zero)
|
| 252 |
+
tval = (tval, mpi_zero)
|
| 253 |
+
return g_complex(ctx, sval, tval)
|
| 254 |
+
def lop_real(s, t):
|
| 255 |
+
if isinstance(t, _matrix): return NotImplemented
|
| 256 |
+
ctx = s.ctx
|
| 257 |
+
if not isinstance(t, ctx._types): t = ctx.convert(t)
|
| 258 |
+
if hasattr(t, "_mpi_"): return g_real(ctx, s._mpi_, t._mpi_)
|
| 259 |
+
if hasattr(t, "_mpci_"): return g_complex(ctx, (s._mpi_, mpi_zero), t._mpci_)
|
| 260 |
+
return NotImplemented
|
| 261 |
+
def rop_real(s, t):
|
| 262 |
+
ctx = s.ctx
|
| 263 |
+
if not isinstance(t, ctx._types): t = ctx.convert(t)
|
| 264 |
+
if hasattr(t, "_mpi_"): return g_real(ctx, t._mpi_, s._mpi_)
|
| 265 |
+
if hasattr(t, "_mpci_"): return g_complex(ctx, t._mpci_, (s._mpi_, mpi_zero))
|
| 266 |
+
return NotImplemented
|
| 267 |
+
def lop_complex(s, t):
|
| 268 |
+
if isinstance(t, _matrix): return NotImplemented
|
| 269 |
+
ctx = s.ctx
|
| 270 |
+
if not isinstance(t, s.ctx._types):
|
| 271 |
+
try:
|
| 272 |
+
t = s.ctx.convert(t)
|
| 273 |
+
except (ValueError, TypeError):
|
| 274 |
+
return NotImplemented
|
| 275 |
+
return g_complex(ctx, s._mpci_, t._mpci_)
|
| 276 |
+
def rop_complex(s, t):
|
| 277 |
+
ctx = s.ctx
|
| 278 |
+
if not isinstance(t, s.ctx._types):
|
| 279 |
+
t = s.ctx.convert(t)
|
| 280 |
+
return g_complex(ctx, t._mpci_, s._mpci_)
|
| 281 |
+
return lop_real, rop_real, lop_complex, rop_complex
|
| 282 |
+
|
| 283 |
+
ivmpf.__add__, ivmpf.__radd__, ivmpc.__add__, ivmpc.__radd__ = _binary_op(mpi_add, mpci_add)
|
| 284 |
+
ivmpf.__sub__, ivmpf.__rsub__, ivmpc.__sub__, ivmpc.__rsub__ = _binary_op(mpi_sub, mpci_sub)
|
| 285 |
+
ivmpf.__mul__, ivmpf.__rmul__, ivmpc.__mul__, ivmpc.__rmul__ = _binary_op(mpi_mul, mpci_mul)
|
| 286 |
+
ivmpf.__div__, ivmpf.__rdiv__, ivmpc.__div__, ivmpc.__rdiv__ = _binary_op(mpi_div, mpci_div)
|
| 287 |
+
ivmpf.__pow__, ivmpf.__rpow__, ivmpc.__pow__, ivmpc.__rpow__ = _binary_op(mpi_pow, mpci_pow)
|
| 288 |
+
|
| 289 |
+
ivmpf.__truediv__ = ivmpf.__div__; ivmpf.__rtruediv__ = ivmpf.__rdiv__
|
| 290 |
+
ivmpc.__truediv__ = ivmpc.__div__; ivmpc.__rtruediv__ = ivmpc.__rdiv__
|
| 291 |
+
|
| 292 |
+
class ivmpf_constant(ivmpf):
|
| 293 |
+
def __new__(cls, f):
|
| 294 |
+
self = new(cls)
|
| 295 |
+
self._f = f
|
| 296 |
+
return self
|
| 297 |
+
def _get_mpi_(self):
|
| 298 |
+
prec = self.ctx._prec[0]
|
| 299 |
+
a = self._f(prec, round_floor)
|
| 300 |
+
b = self._f(prec, round_ceiling)
|
| 301 |
+
return a, b
|
| 302 |
+
_mpi_ = property(_get_mpi_)
|
| 303 |
+
|
| 304 |
+
class MPIntervalContext(StandardBaseContext):
|
| 305 |
+
|
| 306 |
+
def __init__(ctx):
|
| 307 |
+
ctx.mpf = type('ivmpf', (ivmpf,), {})
|
| 308 |
+
ctx.mpc = type('ivmpc', (ivmpc,), {})
|
| 309 |
+
ctx._types = (ctx.mpf, ctx.mpc)
|
| 310 |
+
ctx._constant = type('ivmpf_constant', (ivmpf_constant,), {})
|
| 311 |
+
ctx._prec = [53]
|
| 312 |
+
ctx._set_prec(53)
|
| 313 |
+
ctx._constant._ctxdata = ctx.mpf._ctxdata = ctx.mpc._ctxdata = [ctx.mpf, new, ctx._prec]
|
| 314 |
+
ctx._constant.ctx = ctx.mpf.ctx = ctx.mpc.ctx = ctx
|
| 315 |
+
ctx.pretty = False
|
| 316 |
+
StandardBaseContext.__init__(ctx)
|
| 317 |
+
ctx._init_builtins()
|
| 318 |
+
|
| 319 |
+
def _mpi(ctx, a, b=None):
|
| 320 |
+
if b is None:
|
| 321 |
+
return ctx.mpf(a)
|
| 322 |
+
return ctx.mpf((a,b))
|
| 323 |
+
|
| 324 |
+
def _init_builtins(ctx):
|
| 325 |
+
ctx.one = ctx.mpf(1)
|
| 326 |
+
ctx.zero = ctx.mpf(0)
|
| 327 |
+
ctx.inf = ctx.mpf('inf')
|
| 328 |
+
ctx.ninf = -ctx.inf
|
| 329 |
+
ctx.nan = ctx.mpf('nan')
|
| 330 |
+
ctx.j = ctx.mpc(0,1)
|
| 331 |
+
ctx.exp = ctx._wrap_mpi_function(libmp.mpi_exp, libmp.mpci_exp)
|
| 332 |
+
ctx.sqrt = ctx._wrap_mpi_function(libmp.mpi_sqrt)
|
| 333 |
+
ctx.ln = ctx._wrap_mpi_function(libmp.mpi_log, libmp.mpci_log)
|
| 334 |
+
ctx.cos = ctx._wrap_mpi_function(libmp.mpi_cos, libmp.mpci_cos)
|
| 335 |
+
ctx.sin = ctx._wrap_mpi_function(libmp.mpi_sin, libmp.mpci_sin)
|
| 336 |
+
ctx.tan = ctx._wrap_mpi_function(libmp.mpi_tan)
|
| 337 |
+
ctx.gamma = ctx._wrap_mpi_function(libmp.mpi_gamma, libmp.mpci_gamma)
|
| 338 |
+
ctx.loggamma = ctx._wrap_mpi_function(libmp.mpi_loggamma, libmp.mpci_loggamma)
|
| 339 |
+
ctx.rgamma = ctx._wrap_mpi_function(libmp.mpi_rgamma, libmp.mpci_rgamma)
|
| 340 |
+
ctx.factorial = ctx._wrap_mpi_function(libmp.mpi_factorial, libmp.mpci_factorial)
|
| 341 |
+
ctx.fac = ctx.factorial
|
| 342 |
+
|
| 343 |
+
ctx.eps = ctx._constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1))
|
| 344 |
+
ctx.pi = ctx._constant(libmp.mpf_pi)
|
| 345 |
+
ctx.e = ctx._constant(libmp.mpf_e)
|
| 346 |
+
ctx.ln2 = ctx._constant(libmp.mpf_ln2)
|
| 347 |
+
ctx.ln10 = ctx._constant(libmp.mpf_ln10)
|
| 348 |
+
ctx.phi = ctx._constant(libmp.mpf_phi)
|
| 349 |
+
ctx.euler = ctx._constant(libmp.mpf_euler)
|
| 350 |
+
ctx.catalan = ctx._constant(libmp.mpf_catalan)
|
| 351 |
+
ctx.glaisher = ctx._constant(libmp.mpf_glaisher)
|
| 352 |
+
ctx.khinchin = ctx._constant(libmp.mpf_khinchin)
|
| 353 |
+
ctx.twinprime = ctx._constant(libmp.mpf_twinprime)
|
| 354 |
+
|
| 355 |
+
def _wrap_mpi_function(ctx, f_real, f_complex=None):
|
| 356 |
+
def g(x, **kwargs):
|
| 357 |
+
if kwargs:
|
| 358 |
+
prec = kwargs.get('prec', ctx._prec[0])
|
| 359 |
+
else:
|
| 360 |
+
prec = ctx._prec[0]
|
| 361 |
+
x = ctx.convert(x)
|
| 362 |
+
if hasattr(x, "_mpi_"):
|
| 363 |
+
return ctx.make_mpf(f_real(x._mpi_, prec))
|
| 364 |
+
if hasattr(x, "_mpci_"):
|
| 365 |
+
return ctx.make_mpc(f_complex(x._mpci_, prec))
|
| 366 |
+
raise ValueError
|
| 367 |
+
return g
|
| 368 |
+
|
| 369 |
+
@classmethod
|
| 370 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 371 |
+
if wrap:
|
| 372 |
+
def f_wrapped(ctx, *args, **kwargs):
|
| 373 |
+
convert = ctx.convert
|
| 374 |
+
args = [convert(a) for a in args]
|
| 375 |
+
prec = ctx.prec
|
| 376 |
+
try:
|
| 377 |
+
ctx.prec += 10
|
| 378 |
+
retval = f(ctx, *args, **kwargs)
|
| 379 |
+
finally:
|
| 380 |
+
ctx.prec = prec
|
| 381 |
+
return +retval
|
| 382 |
+
else:
|
| 383 |
+
f_wrapped = f
|
| 384 |
+
setattr(cls, name, f_wrapped)
|
| 385 |
+
|
| 386 |
+
def _set_prec(ctx, n):
|
| 387 |
+
ctx._prec[0] = max(1, int(n))
|
| 388 |
+
ctx._dps = prec_to_dps(n)
|
| 389 |
+
|
| 390 |
+
def _set_dps(ctx, n):
|
| 391 |
+
ctx._prec[0] = dps_to_prec(n)
|
| 392 |
+
ctx._dps = max(1, int(n))
|
| 393 |
+
|
| 394 |
+
prec = property(lambda ctx: ctx._prec[0], _set_prec)
|
| 395 |
+
dps = property(lambda ctx: ctx._dps, _set_dps)
|
| 396 |
+
|
| 397 |
+
def make_mpf(ctx, v):
|
| 398 |
+
a = new(ctx.mpf)
|
| 399 |
+
a._mpi_ = v
|
| 400 |
+
return a
|
| 401 |
+
|
| 402 |
+
def make_mpc(ctx, v):
|
| 403 |
+
a = new(ctx.mpc)
|
| 404 |
+
a._mpci_ = v
|
| 405 |
+
return a
|
| 406 |
+
|
| 407 |
+
def _mpq(ctx, pq):
|
| 408 |
+
p, q = pq
|
| 409 |
+
a = libmp.from_rational(p, q, ctx.prec, round_floor)
|
| 410 |
+
b = libmp.from_rational(p, q, ctx.prec, round_ceiling)
|
| 411 |
+
return ctx.make_mpf((a, b))
|
| 412 |
+
|
| 413 |
+
def convert(ctx, x):
|
| 414 |
+
if isinstance(x, (ctx.mpf, ctx.mpc)):
|
| 415 |
+
return x
|
| 416 |
+
if isinstance(x, ctx._constant):
|
| 417 |
+
return +x
|
| 418 |
+
if isinstance(x, complex) or hasattr(x, "_mpc_"):
|
| 419 |
+
re = ctx.convert(x.real)
|
| 420 |
+
im = ctx.convert(x.imag)
|
| 421 |
+
return ctx.mpc(re,im)
|
| 422 |
+
if isinstance(x, basestring):
|
| 423 |
+
v = mpi_from_str(x, ctx.prec)
|
| 424 |
+
return ctx.make_mpf(v)
|
| 425 |
+
if hasattr(x, "_mpi_"):
|
| 426 |
+
a, b = x._mpi_
|
| 427 |
+
else:
|
| 428 |
+
try:
|
| 429 |
+
a, b = x
|
| 430 |
+
except (TypeError, ValueError):
|
| 431 |
+
a = b = x
|
| 432 |
+
if hasattr(a, "_mpi_"):
|
| 433 |
+
a = a._mpi_[0]
|
| 434 |
+
else:
|
| 435 |
+
a = convert_mpf_(a, ctx.prec, round_floor)
|
| 436 |
+
if hasattr(b, "_mpi_"):
|
| 437 |
+
b = b._mpi_[1]
|
| 438 |
+
else:
|
| 439 |
+
b = convert_mpf_(b, ctx.prec, round_ceiling)
|
| 440 |
+
if a == fnan or b == fnan:
|
| 441 |
+
a = fninf
|
| 442 |
+
b = finf
|
| 443 |
+
assert mpf_le(a, b), "endpoints must be properly ordered"
|
| 444 |
+
return ctx.make_mpf((a, b))
|
| 445 |
+
|
| 446 |
+
def nstr(ctx, x, n=5, **kwargs):
|
| 447 |
+
x = ctx.convert(x)
|
| 448 |
+
if hasattr(x, "_mpi_"):
|
| 449 |
+
return libmp.mpi_to_str(x._mpi_, n, **kwargs)
|
| 450 |
+
if hasattr(x, "_mpci_"):
|
| 451 |
+
re = libmp.mpi_to_str(x._mpci_[0], n, **kwargs)
|
| 452 |
+
im = libmp.mpi_to_str(x._mpci_[1], n, **kwargs)
|
| 453 |
+
return "(%s + %s*j)" % (re, im)
|
| 454 |
+
|
| 455 |
+
def mag(ctx, x):
|
| 456 |
+
x = ctx.convert(x)
|
| 457 |
+
if isinstance(x, ctx.mpc):
|
| 458 |
+
return max(ctx.mag(x.real), ctx.mag(x.imag)) + 1
|
| 459 |
+
a, b = libmp.mpi_abs(x._mpi_)
|
| 460 |
+
sign, man, exp, bc = b
|
| 461 |
+
if man:
|
| 462 |
+
return exp+bc
|
| 463 |
+
if b == fzero:
|
| 464 |
+
return ctx.ninf
|
| 465 |
+
if b == fnan:
|
| 466 |
+
return ctx.nan
|
| 467 |
+
return ctx.inf
|
| 468 |
+
|
| 469 |
+
def isnan(ctx, x):
|
| 470 |
+
return False
|
| 471 |
+
|
| 472 |
+
def isinf(ctx, x):
|
| 473 |
+
return x == ctx.inf
|
| 474 |
+
|
| 475 |
+
def isint(ctx, x):
|
| 476 |
+
x = ctx.convert(x)
|
| 477 |
+
a, b = x._mpi_
|
| 478 |
+
if a == b:
|
| 479 |
+
sign, man, exp, bc = a
|
| 480 |
+
if man:
|
| 481 |
+
return exp >= 0
|
| 482 |
+
return a == fzero
|
| 483 |
+
return None
|
| 484 |
+
|
| 485 |
+
def ldexp(ctx, x, n):
|
| 486 |
+
a, b = ctx.convert(x)._mpi_
|
| 487 |
+
a = libmp.mpf_shift(a, n)
|
| 488 |
+
b = libmp.mpf_shift(b, n)
|
| 489 |
+
return ctx.make_mpf((a,b))
|
| 490 |
+
|
| 491 |
+
def absmin(ctx, x):
|
| 492 |
+
return abs(ctx.convert(x)).a
|
| 493 |
+
|
| 494 |
+
def absmax(ctx, x):
|
| 495 |
+
return abs(ctx.convert(x)).b
|
| 496 |
+
|
| 497 |
+
def atan2(ctx, y, x):
|
| 498 |
+
y = ctx.convert(y)._mpi_
|
| 499 |
+
x = ctx.convert(x)._mpi_
|
| 500 |
+
return ctx.make_mpf(libmp.mpi_atan2(y,x,ctx.prec))
|
| 501 |
+
|
| 502 |
+
def _convert_param(ctx, x):
|
| 503 |
+
if isinstance(x, libmp.int_types):
|
| 504 |
+
return x, 'Z'
|
| 505 |
+
if isinstance(x, tuple):
|
| 506 |
+
p, q = x
|
| 507 |
+
return (ctx.mpf(p) / ctx.mpf(q), 'R')
|
| 508 |
+
x = ctx.convert(x)
|
| 509 |
+
if isinstance(x, ctx.mpf):
|
| 510 |
+
return x, 'R'
|
| 511 |
+
if isinstance(x, ctx.mpc):
|
| 512 |
+
return x, 'C'
|
| 513 |
+
raise ValueError
|
| 514 |
+
|
| 515 |
+
def _is_real_type(ctx, z):
|
| 516 |
+
return isinstance(z, ctx.mpf) or isinstance(z, int_types)
|
| 517 |
+
|
| 518 |
+
def _is_complex_type(ctx, z):
|
| 519 |
+
return isinstance(z, ctx.mpc)
|
| 520 |
+
|
| 521 |
+
def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs):
|
| 522 |
+
coeffs = list(coeffs)
|
| 523 |
+
num = range(p)
|
| 524 |
+
den = range(p,p+q)
|
| 525 |
+
#tol = ctx.eps
|
| 526 |
+
s = t = ctx.one
|
| 527 |
+
k = 0
|
| 528 |
+
while 1:
|
| 529 |
+
for i in num: t *= (coeffs[i]+k)
|
| 530 |
+
for i in den: t /= (coeffs[i]+k)
|
| 531 |
+
k += 1; t /= k; t *= z; s += t
|
| 532 |
+
if t == 0:
|
| 533 |
+
return s
|
| 534 |
+
#if abs(t) < tol:
|
| 535 |
+
# return s
|
| 536 |
+
if k > maxterms:
|
| 537 |
+
raise ctx.NoConvergence
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
# Register with "numbers" ABC
|
| 541 |
+
# We do not subclass, hence we do not use the @abstractmethod checks. While
|
| 542 |
+
# this is less invasive it may turn out that we do not actually support
|
| 543 |
+
# parts of the expected interfaces. See
|
| 544 |
+
# http://docs.python.org/2/library/numbers.html for list of abstract
|
| 545 |
+
# methods.
|
| 546 |
+
try:
|
| 547 |
+
import numbers
|
| 548 |
+
numbers.Complex.register(ivmpc)
|
| 549 |
+
numbers.Real.register(ivmpf)
|
| 550 |
+
except ImportError:
|
| 551 |
+
pass
|
.venv/lib/python3.11/site-packages/mpmath/ctx_mp.py
ADDED
|
@@ -0,0 +1,1339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This module defines the mpf, mpc classes, and standard functions for
|
| 3 |
+
operating with them.
|
| 4 |
+
"""
|
| 5 |
+
__docformat__ = 'plaintext'
|
| 6 |
+
|
| 7 |
+
import functools
|
| 8 |
+
|
| 9 |
+
import re
|
| 10 |
+
|
| 11 |
+
from .ctx_base import StandardBaseContext
|
| 12 |
+
|
| 13 |
+
from .libmp.backend import basestring, BACKEND
|
| 14 |
+
|
| 15 |
+
from . import libmp
|
| 16 |
+
|
| 17 |
+
from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps,
|
| 18 |
+
round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps,
|
| 19 |
+
ComplexResult, to_pickable, from_pickable, normalize,
|
| 20 |
+
from_int, from_float, from_str, to_int, to_float, to_str,
|
| 21 |
+
from_rational, from_man_exp,
|
| 22 |
+
fone, fzero, finf, fninf, fnan,
|
| 23 |
+
mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int,
|
| 24 |
+
mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod,
|
| 25 |
+
mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge,
|
| 26 |
+
mpf_hash, mpf_rand,
|
| 27 |
+
mpf_sum,
|
| 28 |
+
bitcount, to_fixed,
|
| 29 |
+
mpc_to_str,
|
| 30 |
+
mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate,
|
| 31 |
+
mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf,
|
| 32 |
+
mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int,
|
| 33 |
+
mpc_mpf_div,
|
| 34 |
+
mpf_pow,
|
| 35 |
+
mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10,
|
| 36 |
+
mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin,
|
| 37 |
+
mpf_glaisher, mpf_twinprime, mpf_mertens,
|
| 38 |
+
int_types)
|
| 39 |
+
|
| 40 |
+
from . import function_docs
|
| 41 |
+
from . import rational
|
| 42 |
+
|
| 43 |
+
new = object.__new__
|
| 44 |
+
|
| 45 |
+
get_complex = re.compile(r'^\(?(?P<re>[\+\-]?\d*(\.\d*)?(e[\+\-]?\d+)?)??'
|
| 46 |
+
r'(?P<im>[\+\-]?\d*(\.\d*)?(e[\+\-]?\d+)?j)?\)?$')
|
| 47 |
+
|
| 48 |
+
if BACKEND == 'sage':
|
| 49 |
+
from sage.libs.mpmath.ext_main import Context as BaseMPContext
|
| 50 |
+
# pickle hack
|
| 51 |
+
import sage.libs.mpmath.ext_main as _mpf_module
|
| 52 |
+
else:
|
| 53 |
+
from .ctx_mp_python import PythonMPContext as BaseMPContext
|
| 54 |
+
from . import ctx_mp_python as _mpf_module
|
| 55 |
+
|
| 56 |
+
from .ctx_mp_python import _mpf, _mpc, mpnumeric
|
| 57 |
+
|
| 58 |
+
class MPContext(BaseMPContext, StandardBaseContext):
|
| 59 |
+
"""
|
| 60 |
+
Context for multiprecision arithmetic with a global precision.
|
| 61 |
+
"""
|
| 62 |
+
|
| 63 |
+
def __init__(ctx):
|
| 64 |
+
BaseMPContext.__init__(ctx)
|
| 65 |
+
ctx.trap_complex = False
|
| 66 |
+
ctx.pretty = False
|
| 67 |
+
ctx.types = [ctx.mpf, ctx.mpc, ctx.constant]
|
| 68 |
+
ctx._mpq = rational.mpq
|
| 69 |
+
ctx.default()
|
| 70 |
+
StandardBaseContext.__init__(ctx)
|
| 71 |
+
|
| 72 |
+
ctx.mpq = rational.mpq
|
| 73 |
+
ctx.init_builtins()
|
| 74 |
+
|
| 75 |
+
ctx.hyp_summators = {}
|
| 76 |
+
|
| 77 |
+
ctx._init_aliases()
|
| 78 |
+
|
| 79 |
+
# XXX: automate
|
| 80 |
+
try:
|
| 81 |
+
ctx.bernoulli.im_func.func_doc = function_docs.bernoulli
|
| 82 |
+
ctx.primepi.im_func.func_doc = function_docs.primepi
|
| 83 |
+
ctx.psi.im_func.func_doc = function_docs.psi
|
| 84 |
+
ctx.atan2.im_func.func_doc = function_docs.atan2
|
| 85 |
+
except AttributeError:
|
| 86 |
+
# python 3
|
| 87 |
+
ctx.bernoulli.__func__.func_doc = function_docs.bernoulli
|
| 88 |
+
ctx.primepi.__func__.func_doc = function_docs.primepi
|
| 89 |
+
ctx.psi.__func__.func_doc = function_docs.psi
|
| 90 |
+
ctx.atan2.__func__.func_doc = function_docs.atan2
|
| 91 |
+
|
| 92 |
+
ctx.digamma.func_doc = function_docs.digamma
|
| 93 |
+
ctx.cospi.func_doc = function_docs.cospi
|
| 94 |
+
ctx.sinpi.func_doc = function_docs.sinpi
|
| 95 |
+
|
| 96 |
+
def init_builtins(ctx):
|
| 97 |
+
|
| 98 |
+
mpf = ctx.mpf
|
| 99 |
+
mpc = ctx.mpc
|
| 100 |
+
|
| 101 |
+
# Exact constants
|
| 102 |
+
ctx.one = ctx.make_mpf(fone)
|
| 103 |
+
ctx.zero = ctx.make_mpf(fzero)
|
| 104 |
+
ctx.j = ctx.make_mpc((fzero,fone))
|
| 105 |
+
ctx.inf = ctx.make_mpf(finf)
|
| 106 |
+
ctx.ninf = ctx.make_mpf(fninf)
|
| 107 |
+
ctx.nan = ctx.make_mpf(fnan)
|
| 108 |
+
|
| 109 |
+
eps = ctx.constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1),
|
| 110 |
+
"epsilon of working precision", "eps")
|
| 111 |
+
ctx.eps = eps
|
| 112 |
+
|
| 113 |
+
# Approximate constants
|
| 114 |
+
ctx.pi = ctx.constant(mpf_pi, "pi", "pi")
|
| 115 |
+
ctx.ln2 = ctx.constant(mpf_ln2, "ln(2)", "ln2")
|
| 116 |
+
ctx.ln10 = ctx.constant(mpf_ln10, "ln(10)", "ln10")
|
| 117 |
+
ctx.phi = ctx.constant(mpf_phi, "Golden ratio phi", "phi")
|
| 118 |
+
ctx.e = ctx.constant(mpf_e, "e = exp(1)", "e")
|
| 119 |
+
ctx.euler = ctx.constant(mpf_euler, "Euler's constant", "euler")
|
| 120 |
+
ctx.catalan = ctx.constant(mpf_catalan, "Catalan's constant", "catalan")
|
| 121 |
+
ctx.khinchin = ctx.constant(mpf_khinchin, "Khinchin's constant", "khinchin")
|
| 122 |
+
ctx.glaisher = ctx.constant(mpf_glaisher, "Glaisher's constant", "glaisher")
|
| 123 |
+
ctx.apery = ctx.constant(mpf_apery, "Apery's constant", "apery")
|
| 124 |
+
ctx.degree = ctx.constant(mpf_degree, "1 deg = pi / 180", "degree")
|
| 125 |
+
ctx.twinprime = ctx.constant(mpf_twinprime, "Twin prime constant", "twinprime")
|
| 126 |
+
ctx.mertens = ctx.constant(mpf_mertens, "Mertens' constant", "mertens")
|
| 127 |
+
|
| 128 |
+
# Standard functions
|
| 129 |
+
ctx.sqrt = ctx._wrap_libmp_function(libmp.mpf_sqrt, libmp.mpc_sqrt)
|
| 130 |
+
ctx.cbrt = ctx._wrap_libmp_function(libmp.mpf_cbrt, libmp.mpc_cbrt)
|
| 131 |
+
ctx.ln = ctx._wrap_libmp_function(libmp.mpf_log, libmp.mpc_log)
|
| 132 |
+
ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan)
|
| 133 |
+
ctx.exp = ctx._wrap_libmp_function(libmp.mpf_exp, libmp.mpc_exp)
|
| 134 |
+
ctx.expj = ctx._wrap_libmp_function(libmp.mpf_expj, libmp.mpc_expj)
|
| 135 |
+
ctx.expjpi = ctx._wrap_libmp_function(libmp.mpf_expjpi, libmp.mpc_expjpi)
|
| 136 |
+
ctx.sin = ctx._wrap_libmp_function(libmp.mpf_sin, libmp.mpc_sin)
|
| 137 |
+
ctx.cos = ctx._wrap_libmp_function(libmp.mpf_cos, libmp.mpc_cos)
|
| 138 |
+
ctx.tan = ctx._wrap_libmp_function(libmp.mpf_tan, libmp.mpc_tan)
|
| 139 |
+
ctx.sinh = ctx._wrap_libmp_function(libmp.mpf_sinh, libmp.mpc_sinh)
|
| 140 |
+
ctx.cosh = ctx._wrap_libmp_function(libmp.mpf_cosh, libmp.mpc_cosh)
|
| 141 |
+
ctx.tanh = ctx._wrap_libmp_function(libmp.mpf_tanh, libmp.mpc_tanh)
|
| 142 |
+
ctx.asin = ctx._wrap_libmp_function(libmp.mpf_asin, libmp.mpc_asin)
|
| 143 |
+
ctx.acos = ctx._wrap_libmp_function(libmp.mpf_acos, libmp.mpc_acos)
|
| 144 |
+
ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan)
|
| 145 |
+
ctx.asinh = ctx._wrap_libmp_function(libmp.mpf_asinh, libmp.mpc_asinh)
|
| 146 |
+
ctx.acosh = ctx._wrap_libmp_function(libmp.mpf_acosh, libmp.mpc_acosh)
|
| 147 |
+
ctx.atanh = ctx._wrap_libmp_function(libmp.mpf_atanh, libmp.mpc_atanh)
|
| 148 |
+
ctx.sinpi = ctx._wrap_libmp_function(libmp.mpf_sin_pi, libmp.mpc_sin_pi)
|
| 149 |
+
ctx.cospi = ctx._wrap_libmp_function(libmp.mpf_cos_pi, libmp.mpc_cos_pi)
|
| 150 |
+
ctx.floor = ctx._wrap_libmp_function(libmp.mpf_floor, libmp.mpc_floor)
|
| 151 |
+
ctx.ceil = ctx._wrap_libmp_function(libmp.mpf_ceil, libmp.mpc_ceil)
|
| 152 |
+
ctx.nint = ctx._wrap_libmp_function(libmp.mpf_nint, libmp.mpc_nint)
|
| 153 |
+
ctx.frac = ctx._wrap_libmp_function(libmp.mpf_frac, libmp.mpc_frac)
|
| 154 |
+
ctx.fib = ctx.fibonacci = ctx._wrap_libmp_function(libmp.mpf_fibonacci, libmp.mpc_fibonacci)
|
| 155 |
+
|
| 156 |
+
ctx.gamma = ctx._wrap_libmp_function(libmp.mpf_gamma, libmp.mpc_gamma)
|
| 157 |
+
ctx.rgamma = ctx._wrap_libmp_function(libmp.mpf_rgamma, libmp.mpc_rgamma)
|
| 158 |
+
ctx.loggamma = ctx._wrap_libmp_function(libmp.mpf_loggamma, libmp.mpc_loggamma)
|
| 159 |
+
ctx.fac = ctx.factorial = ctx._wrap_libmp_function(libmp.mpf_factorial, libmp.mpc_factorial)
|
| 160 |
+
|
| 161 |
+
ctx.digamma = ctx._wrap_libmp_function(libmp.mpf_psi0, libmp.mpc_psi0)
|
| 162 |
+
ctx.harmonic = ctx._wrap_libmp_function(libmp.mpf_harmonic, libmp.mpc_harmonic)
|
| 163 |
+
ctx.ei = ctx._wrap_libmp_function(libmp.mpf_ei, libmp.mpc_ei)
|
| 164 |
+
ctx.e1 = ctx._wrap_libmp_function(libmp.mpf_e1, libmp.mpc_e1)
|
| 165 |
+
ctx._ci = ctx._wrap_libmp_function(libmp.mpf_ci, libmp.mpc_ci)
|
| 166 |
+
ctx._si = ctx._wrap_libmp_function(libmp.mpf_si, libmp.mpc_si)
|
| 167 |
+
ctx.ellipk = ctx._wrap_libmp_function(libmp.mpf_ellipk, libmp.mpc_ellipk)
|
| 168 |
+
ctx._ellipe = ctx._wrap_libmp_function(libmp.mpf_ellipe, libmp.mpc_ellipe)
|
| 169 |
+
ctx.agm1 = ctx._wrap_libmp_function(libmp.mpf_agm1, libmp.mpc_agm1)
|
| 170 |
+
ctx._erf = ctx._wrap_libmp_function(libmp.mpf_erf, None)
|
| 171 |
+
ctx._erfc = ctx._wrap_libmp_function(libmp.mpf_erfc, None)
|
| 172 |
+
ctx._zeta = ctx._wrap_libmp_function(libmp.mpf_zeta, libmp.mpc_zeta)
|
| 173 |
+
ctx._altzeta = ctx._wrap_libmp_function(libmp.mpf_altzeta, libmp.mpc_altzeta)
|
| 174 |
+
|
| 175 |
+
# Faster versions
|
| 176 |
+
ctx.sqrt = getattr(ctx, "_sage_sqrt", ctx.sqrt)
|
| 177 |
+
ctx.exp = getattr(ctx, "_sage_exp", ctx.exp)
|
| 178 |
+
ctx.ln = getattr(ctx, "_sage_ln", ctx.ln)
|
| 179 |
+
ctx.cos = getattr(ctx, "_sage_cos", ctx.cos)
|
| 180 |
+
ctx.sin = getattr(ctx, "_sage_sin", ctx.sin)
|
| 181 |
+
|
| 182 |
+
def to_fixed(ctx, x, prec):
|
| 183 |
+
return x.to_fixed(prec)
|
| 184 |
+
|
| 185 |
+
def hypot(ctx, x, y):
|
| 186 |
+
r"""
|
| 187 |
+
Computes the Euclidean norm of the vector `(x, y)`, equal
|
| 188 |
+
to `\sqrt{x^2 + y^2}`. Both `x` and `y` must be real."""
|
| 189 |
+
x = ctx.convert(x)
|
| 190 |
+
y = ctx.convert(y)
|
| 191 |
+
return ctx.make_mpf(libmp.mpf_hypot(x._mpf_, y._mpf_, *ctx._prec_rounding))
|
| 192 |
+
|
| 193 |
+
def _gamma_upper_int(ctx, n, z):
|
| 194 |
+
n = int(ctx._re(n))
|
| 195 |
+
if n == 0:
|
| 196 |
+
return ctx.e1(z)
|
| 197 |
+
if not hasattr(z, '_mpf_'):
|
| 198 |
+
raise NotImplementedError
|
| 199 |
+
prec, rounding = ctx._prec_rounding
|
| 200 |
+
real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding, gamma=True)
|
| 201 |
+
if imag is None:
|
| 202 |
+
return ctx.make_mpf(real)
|
| 203 |
+
else:
|
| 204 |
+
return ctx.make_mpc((real, imag))
|
| 205 |
+
|
| 206 |
+
def _expint_int(ctx, n, z):
|
| 207 |
+
n = int(n)
|
| 208 |
+
if n == 1:
|
| 209 |
+
return ctx.e1(z)
|
| 210 |
+
if not hasattr(z, '_mpf_'):
|
| 211 |
+
raise NotImplementedError
|
| 212 |
+
prec, rounding = ctx._prec_rounding
|
| 213 |
+
real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding)
|
| 214 |
+
if imag is None:
|
| 215 |
+
return ctx.make_mpf(real)
|
| 216 |
+
else:
|
| 217 |
+
return ctx.make_mpc((real, imag))
|
| 218 |
+
|
| 219 |
+
def _nthroot(ctx, x, n):
|
| 220 |
+
if hasattr(x, '_mpf_'):
|
| 221 |
+
try:
|
| 222 |
+
return ctx.make_mpf(libmp.mpf_nthroot(x._mpf_, n, *ctx._prec_rounding))
|
| 223 |
+
except ComplexResult:
|
| 224 |
+
if ctx.trap_complex:
|
| 225 |
+
raise
|
| 226 |
+
x = (x._mpf_, libmp.fzero)
|
| 227 |
+
else:
|
| 228 |
+
x = x._mpc_
|
| 229 |
+
return ctx.make_mpc(libmp.mpc_nthroot(x, n, *ctx._prec_rounding))
|
| 230 |
+
|
| 231 |
+
def _besselj(ctx, n, z):
|
| 232 |
+
prec, rounding = ctx._prec_rounding
|
| 233 |
+
if hasattr(z, '_mpf_'):
|
| 234 |
+
return ctx.make_mpf(libmp.mpf_besseljn(n, z._mpf_, prec, rounding))
|
| 235 |
+
elif hasattr(z, '_mpc_'):
|
| 236 |
+
return ctx.make_mpc(libmp.mpc_besseljn(n, z._mpc_, prec, rounding))
|
| 237 |
+
|
| 238 |
+
def _agm(ctx, a, b=1):
|
| 239 |
+
prec, rounding = ctx._prec_rounding
|
| 240 |
+
if hasattr(a, '_mpf_') and hasattr(b, '_mpf_'):
|
| 241 |
+
try:
|
| 242 |
+
v = libmp.mpf_agm(a._mpf_, b._mpf_, prec, rounding)
|
| 243 |
+
return ctx.make_mpf(v)
|
| 244 |
+
except ComplexResult:
|
| 245 |
+
pass
|
| 246 |
+
if hasattr(a, '_mpf_'): a = (a._mpf_, libmp.fzero)
|
| 247 |
+
else: a = a._mpc_
|
| 248 |
+
if hasattr(b, '_mpf_'): b = (b._mpf_, libmp.fzero)
|
| 249 |
+
else: b = b._mpc_
|
| 250 |
+
return ctx.make_mpc(libmp.mpc_agm(a, b, prec, rounding))
|
| 251 |
+
|
| 252 |
+
def bernoulli(ctx, n):
|
| 253 |
+
return ctx.make_mpf(libmp.mpf_bernoulli(int(n), *ctx._prec_rounding))
|
| 254 |
+
|
| 255 |
+
def _zeta_int(ctx, n):
|
| 256 |
+
return ctx.make_mpf(libmp.mpf_zeta_int(int(n), *ctx._prec_rounding))
|
| 257 |
+
|
| 258 |
+
def atan2(ctx, y, x):
|
| 259 |
+
x = ctx.convert(x)
|
| 260 |
+
y = ctx.convert(y)
|
| 261 |
+
return ctx.make_mpf(libmp.mpf_atan2(y._mpf_, x._mpf_, *ctx._prec_rounding))
|
| 262 |
+
|
| 263 |
+
def psi(ctx, m, z):
|
| 264 |
+
z = ctx.convert(z)
|
| 265 |
+
m = int(m)
|
| 266 |
+
if ctx._is_real_type(z):
|
| 267 |
+
return ctx.make_mpf(libmp.mpf_psi(m, z._mpf_, *ctx._prec_rounding))
|
| 268 |
+
else:
|
| 269 |
+
return ctx.make_mpc(libmp.mpc_psi(m, z._mpc_, *ctx._prec_rounding))
|
| 270 |
+
|
| 271 |
+
def cos_sin(ctx, x, **kwargs):
|
| 272 |
+
if type(x) not in ctx.types:
|
| 273 |
+
x = ctx.convert(x)
|
| 274 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 275 |
+
if hasattr(x, '_mpf_'):
|
| 276 |
+
c, s = libmp.mpf_cos_sin(x._mpf_, prec, rounding)
|
| 277 |
+
return ctx.make_mpf(c), ctx.make_mpf(s)
|
| 278 |
+
elif hasattr(x, '_mpc_'):
|
| 279 |
+
c, s = libmp.mpc_cos_sin(x._mpc_, prec, rounding)
|
| 280 |
+
return ctx.make_mpc(c), ctx.make_mpc(s)
|
| 281 |
+
else:
|
| 282 |
+
return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs)
|
| 283 |
+
|
| 284 |
+
def cospi_sinpi(ctx, x, **kwargs):
|
| 285 |
+
if type(x) not in ctx.types:
|
| 286 |
+
x = ctx.convert(x)
|
| 287 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 288 |
+
if hasattr(x, '_mpf_'):
|
| 289 |
+
c, s = libmp.mpf_cos_sin_pi(x._mpf_, prec, rounding)
|
| 290 |
+
return ctx.make_mpf(c), ctx.make_mpf(s)
|
| 291 |
+
elif hasattr(x, '_mpc_'):
|
| 292 |
+
c, s = libmp.mpc_cos_sin_pi(x._mpc_, prec, rounding)
|
| 293 |
+
return ctx.make_mpc(c), ctx.make_mpc(s)
|
| 294 |
+
else:
|
| 295 |
+
return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs)
|
| 296 |
+
|
| 297 |
+
def clone(ctx):
|
| 298 |
+
"""
|
| 299 |
+
Create a copy of the context, with the same working precision.
|
| 300 |
+
"""
|
| 301 |
+
a = ctx.__class__()
|
| 302 |
+
a.prec = ctx.prec
|
| 303 |
+
return a
|
| 304 |
+
|
| 305 |
+
# Several helper methods
|
| 306 |
+
# TODO: add more of these, make consistent, write docstrings, ...
|
| 307 |
+
|
| 308 |
+
def _is_real_type(ctx, x):
|
| 309 |
+
if hasattr(x, '_mpc_') or type(x) is complex:
|
| 310 |
+
return False
|
| 311 |
+
return True
|
| 312 |
+
|
| 313 |
+
def _is_complex_type(ctx, x):
|
| 314 |
+
if hasattr(x, '_mpc_') or type(x) is complex:
|
| 315 |
+
return True
|
| 316 |
+
return False
|
| 317 |
+
|
| 318 |
+
def isnan(ctx, x):
|
| 319 |
+
"""
|
| 320 |
+
Return *True* if *x* is a NaN (not-a-number), or for a complex
|
| 321 |
+
number, whether either the real or complex part is NaN;
|
| 322 |
+
otherwise return *False*::
|
| 323 |
+
|
| 324 |
+
>>> from mpmath import *
|
| 325 |
+
>>> isnan(3.14)
|
| 326 |
+
False
|
| 327 |
+
>>> isnan(nan)
|
| 328 |
+
True
|
| 329 |
+
>>> isnan(mpc(3.14,2.72))
|
| 330 |
+
False
|
| 331 |
+
>>> isnan(mpc(3.14,nan))
|
| 332 |
+
True
|
| 333 |
+
|
| 334 |
+
"""
|
| 335 |
+
if hasattr(x, "_mpf_"):
|
| 336 |
+
return x._mpf_ == fnan
|
| 337 |
+
if hasattr(x, "_mpc_"):
|
| 338 |
+
return fnan in x._mpc_
|
| 339 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 340 |
+
return False
|
| 341 |
+
x = ctx.convert(x)
|
| 342 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 343 |
+
return ctx.isnan(x)
|
| 344 |
+
raise TypeError("isnan() needs a number as input")
|
| 345 |
+
|
| 346 |
+
def isfinite(ctx, x):
|
| 347 |
+
"""
|
| 348 |
+
Return *True* if *x* is a finite number, i.e. neither
|
| 349 |
+
an infinity or a NaN.
|
| 350 |
+
|
| 351 |
+
>>> from mpmath import *
|
| 352 |
+
>>> isfinite(inf)
|
| 353 |
+
False
|
| 354 |
+
>>> isfinite(-inf)
|
| 355 |
+
False
|
| 356 |
+
>>> isfinite(3)
|
| 357 |
+
True
|
| 358 |
+
>>> isfinite(nan)
|
| 359 |
+
False
|
| 360 |
+
>>> isfinite(3+4j)
|
| 361 |
+
True
|
| 362 |
+
>>> isfinite(mpc(3,inf))
|
| 363 |
+
False
|
| 364 |
+
>>> isfinite(mpc(nan,3))
|
| 365 |
+
False
|
| 366 |
+
|
| 367 |
+
"""
|
| 368 |
+
if ctx.isinf(x) or ctx.isnan(x):
|
| 369 |
+
return False
|
| 370 |
+
return True
|
| 371 |
+
|
| 372 |
+
def isnpint(ctx, x):
|
| 373 |
+
"""
|
| 374 |
+
Determine if *x* is a nonpositive integer.
|
| 375 |
+
"""
|
| 376 |
+
if not x:
|
| 377 |
+
return True
|
| 378 |
+
if hasattr(x, '_mpf_'):
|
| 379 |
+
sign, man, exp, bc = x._mpf_
|
| 380 |
+
return sign and exp >= 0
|
| 381 |
+
if hasattr(x, '_mpc_'):
|
| 382 |
+
return not x.imag and ctx.isnpint(x.real)
|
| 383 |
+
if type(x) in int_types:
|
| 384 |
+
return x <= 0
|
| 385 |
+
if isinstance(x, ctx.mpq):
|
| 386 |
+
p, q = x._mpq_
|
| 387 |
+
if not p:
|
| 388 |
+
return True
|
| 389 |
+
return q == 1 and p <= 0
|
| 390 |
+
return ctx.isnpint(ctx.convert(x))
|
| 391 |
+
|
| 392 |
+
def __str__(ctx):
|
| 393 |
+
lines = ["Mpmath settings:",
|
| 394 |
+
(" mp.prec = %s" % ctx.prec).ljust(30) + "[default: 53]",
|
| 395 |
+
(" mp.dps = %s" % ctx.dps).ljust(30) + "[default: 15]",
|
| 396 |
+
(" mp.trap_complex = %s" % ctx.trap_complex).ljust(30) + "[default: False]",
|
| 397 |
+
]
|
| 398 |
+
return "\n".join(lines)
|
| 399 |
+
|
| 400 |
+
@property
|
| 401 |
+
def _repr_digits(ctx):
|
| 402 |
+
return repr_dps(ctx._prec)
|
| 403 |
+
|
| 404 |
+
@property
|
| 405 |
+
def _str_digits(ctx):
|
| 406 |
+
return ctx._dps
|
| 407 |
+
|
| 408 |
+
def extraprec(ctx, n, normalize_output=False):
|
| 409 |
+
"""
|
| 410 |
+
The block
|
| 411 |
+
|
| 412 |
+
with extraprec(n):
|
| 413 |
+
<code>
|
| 414 |
+
|
| 415 |
+
increases the precision n bits, executes <code>, and then
|
| 416 |
+
restores the precision.
|
| 417 |
+
|
| 418 |
+
extraprec(n)(f) returns a decorated version of the function f
|
| 419 |
+
that increases the working precision by n bits before execution,
|
| 420 |
+
and restores the parent precision afterwards. With
|
| 421 |
+
normalize_output=True, it rounds the return value to the parent
|
| 422 |
+
precision.
|
| 423 |
+
"""
|
| 424 |
+
return PrecisionManager(ctx, lambda p: p + n, None, normalize_output)
|
| 425 |
+
|
| 426 |
+
def extradps(ctx, n, normalize_output=False):
|
| 427 |
+
"""
|
| 428 |
+
This function is analogous to extraprec (see documentation)
|
| 429 |
+
but changes the decimal precision instead of the number of bits.
|
| 430 |
+
"""
|
| 431 |
+
return PrecisionManager(ctx, None, lambda d: d + n, normalize_output)
|
| 432 |
+
|
| 433 |
+
def workprec(ctx, n, normalize_output=False):
|
| 434 |
+
"""
|
| 435 |
+
The block
|
| 436 |
+
|
| 437 |
+
with workprec(n):
|
| 438 |
+
<code>
|
| 439 |
+
|
| 440 |
+
sets the precision to n bits, executes <code>, and then restores
|
| 441 |
+
the precision.
|
| 442 |
+
|
| 443 |
+
workprec(n)(f) returns a decorated version of the function f
|
| 444 |
+
that sets the precision to n bits before execution,
|
| 445 |
+
and restores the precision afterwards. With normalize_output=True,
|
| 446 |
+
it rounds the return value to the parent precision.
|
| 447 |
+
"""
|
| 448 |
+
return PrecisionManager(ctx, lambda p: n, None, normalize_output)
|
| 449 |
+
|
| 450 |
+
def workdps(ctx, n, normalize_output=False):
|
| 451 |
+
"""
|
| 452 |
+
This function is analogous to workprec (see documentation)
|
| 453 |
+
but changes the decimal precision instead of the number of bits.
|
| 454 |
+
"""
|
| 455 |
+
return PrecisionManager(ctx, None, lambda d: n, normalize_output)
|
| 456 |
+
|
| 457 |
+
def autoprec(ctx, f, maxprec=None, catch=(), verbose=False):
|
| 458 |
+
r"""
|
| 459 |
+
Return a wrapped copy of *f* that repeatedly evaluates *f*
|
| 460 |
+
with increasing precision until the result converges to the
|
| 461 |
+
full precision used at the point of the call.
|
| 462 |
+
|
| 463 |
+
This heuristically protects against rounding errors, at the cost of
|
| 464 |
+
roughly a 2x slowdown compared to manually setting the optimal
|
| 465 |
+
precision. This method can, however, easily be fooled if the results
|
| 466 |
+
from *f* depend "discontinuously" on the precision, for instance
|
| 467 |
+
if catastrophic cancellation can occur. Therefore, :func:`~mpmath.autoprec`
|
| 468 |
+
should be used judiciously.
|
| 469 |
+
|
| 470 |
+
**Examples**
|
| 471 |
+
|
| 472 |
+
Many functions are sensitive to perturbations of the input arguments.
|
| 473 |
+
If the arguments are decimal numbers, they may have to be converted
|
| 474 |
+
to binary at a much higher precision. If the amount of required
|
| 475 |
+
extra precision is unknown, :func:`~mpmath.autoprec` is convenient::
|
| 476 |
+
|
| 477 |
+
>>> from mpmath import *
|
| 478 |
+
>>> mp.dps = 15
|
| 479 |
+
>>> mp.pretty = True
|
| 480 |
+
>>> besselj(5, 125 * 10**28) # Exact input
|
| 481 |
+
-8.03284785591801e-17
|
| 482 |
+
>>> besselj(5, '1.25e30') # Bad
|
| 483 |
+
7.12954868316652e-16
|
| 484 |
+
>>> autoprec(besselj)(5, '1.25e30') # Good
|
| 485 |
+
-8.03284785591801e-17
|
| 486 |
+
|
| 487 |
+
The following fails to converge because `\sin(\pi) = 0` whereas all
|
| 488 |
+
finite-precision approximations of `\pi` give nonzero values::
|
| 489 |
+
|
| 490 |
+
>>> autoprec(sin)(pi) # doctest: +IGNORE_EXCEPTION_DETAIL
|
| 491 |
+
Traceback (most recent call last):
|
| 492 |
+
...
|
| 493 |
+
NoConvergence: autoprec: prec increased to 2910 without convergence
|
| 494 |
+
|
| 495 |
+
As the following example shows, :func:`~mpmath.autoprec` can protect against
|
| 496 |
+
cancellation, but is fooled by too severe cancellation::
|
| 497 |
+
|
| 498 |
+
>>> x = 1e-10
|
| 499 |
+
>>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
|
| 500 |
+
1.00000008274037e-10
|
| 501 |
+
1.00000000005e-10
|
| 502 |
+
1.00000000005e-10
|
| 503 |
+
>>> x = 1e-50
|
| 504 |
+
>>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
|
| 505 |
+
0.0
|
| 506 |
+
1.0e-50
|
| 507 |
+
0.0
|
| 508 |
+
|
| 509 |
+
With *catch*, an exception or list of exceptions to intercept
|
| 510 |
+
may be specified. The raised exception is interpreted
|
| 511 |
+
as signaling insufficient precision. This permits, for example,
|
| 512 |
+
evaluating a function where a too low precision results in a
|
| 513 |
+
division by zero::
|
| 514 |
+
|
| 515 |
+
>>> f = lambda x: 1/(exp(x)-1)
|
| 516 |
+
>>> f(1e-30)
|
| 517 |
+
Traceback (most recent call last):
|
| 518 |
+
...
|
| 519 |
+
ZeroDivisionError
|
| 520 |
+
>>> autoprec(f, catch=ZeroDivisionError)(1e-30)
|
| 521 |
+
1.0e+30
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
"""
|
| 525 |
+
def f_autoprec_wrapped(*args, **kwargs):
|
| 526 |
+
prec = ctx.prec
|
| 527 |
+
if maxprec is None:
|
| 528 |
+
maxprec2 = ctx._default_hyper_maxprec(prec)
|
| 529 |
+
else:
|
| 530 |
+
maxprec2 = maxprec
|
| 531 |
+
try:
|
| 532 |
+
ctx.prec = prec + 10
|
| 533 |
+
try:
|
| 534 |
+
v1 = f(*args, **kwargs)
|
| 535 |
+
except catch:
|
| 536 |
+
v1 = ctx.nan
|
| 537 |
+
prec2 = prec + 20
|
| 538 |
+
while 1:
|
| 539 |
+
ctx.prec = prec2
|
| 540 |
+
try:
|
| 541 |
+
v2 = f(*args, **kwargs)
|
| 542 |
+
except catch:
|
| 543 |
+
v2 = ctx.nan
|
| 544 |
+
if v1 == v2:
|
| 545 |
+
break
|
| 546 |
+
err = ctx.mag(v2-v1) - ctx.mag(v2)
|
| 547 |
+
if err < (-prec):
|
| 548 |
+
break
|
| 549 |
+
if verbose:
|
| 550 |
+
print("autoprec: target=%s, prec=%s, accuracy=%s" \
|
| 551 |
+
% (prec, prec2, -err))
|
| 552 |
+
v1 = v2
|
| 553 |
+
if prec2 >= maxprec2:
|
| 554 |
+
raise ctx.NoConvergence(\
|
| 555 |
+
"autoprec: prec increased to %i without convergence"\
|
| 556 |
+
% prec2)
|
| 557 |
+
prec2 += int(prec2*2)
|
| 558 |
+
prec2 = min(prec2, maxprec2)
|
| 559 |
+
finally:
|
| 560 |
+
ctx.prec = prec
|
| 561 |
+
return +v2
|
| 562 |
+
return f_autoprec_wrapped
|
| 563 |
+
|
| 564 |
+
def nstr(ctx, x, n=6, **kwargs):
|
| 565 |
+
"""
|
| 566 |
+
Convert an ``mpf`` or ``mpc`` to a decimal string literal with *n*
|
| 567 |
+
significant digits. The small default value for *n* is chosen to
|
| 568 |
+
make this function useful for printing collections of numbers
|
| 569 |
+
(lists, matrices, etc).
|
| 570 |
+
|
| 571 |
+
If *x* is a list or tuple, :func:`~mpmath.nstr` is applied recursively
|
| 572 |
+
to each element. For unrecognized classes, :func:`~mpmath.nstr`
|
| 573 |
+
simply returns ``str(x)``.
|
| 574 |
+
|
| 575 |
+
The companion function :func:`~mpmath.nprint` prints the result
|
| 576 |
+
instead of returning it.
|
| 577 |
+
|
| 578 |
+
The keyword arguments *strip_zeros*, *min_fixed*, *max_fixed*
|
| 579 |
+
and *show_zero_exponent* are forwarded to :func:`~mpmath.libmp.to_str`.
|
| 580 |
+
|
| 581 |
+
The number will be printed in fixed-point format if the position
|
| 582 |
+
of the leading digit is strictly between min_fixed
|
| 583 |
+
(default = min(-dps/3,-5)) and max_fixed (default = dps).
|
| 584 |
+
|
| 585 |
+
To force fixed-point format always, set min_fixed = -inf,
|
| 586 |
+
max_fixed = +inf. To force floating-point format, set
|
| 587 |
+
min_fixed >= max_fixed.
|
| 588 |
+
|
| 589 |
+
>>> from mpmath import *
|
| 590 |
+
>>> nstr([+pi, ldexp(1,-500)])
|
| 591 |
+
'[3.14159, 3.05494e-151]'
|
| 592 |
+
>>> nprint([+pi, ldexp(1,-500)])
|
| 593 |
+
[3.14159, 3.05494e-151]
|
| 594 |
+
>>> nstr(mpf("5e-10"), 5)
|
| 595 |
+
'5.0e-10'
|
| 596 |
+
>>> nstr(mpf("5e-10"), 5, strip_zeros=False)
|
| 597 |
+
'5.0000e-10'
|
| 598 |
+
>>> nstr(mpf("5e-10"), 5, strip_zeros=False, min_fixed=-11)
|
| 599 |
+
'0.00000000050000'
|
| 600 |
+
>>> nstr(mpf(0), 5, show_zero_exponent=True)
|
| 601 |
+
'0.0e+0'
|
| 602 |
+
|
| 603 |
+
"""
|
| 604 |
+
if isinstance(x, list):
|
| 605 |
+
return "[%s]" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x))
|
| 606 |
+
if isinstance(x, tuple):
|
| 607 |
+
return "(%s)" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x))
|
| 608 |
+
if hasattr(x, '_mpf_'):
|
| 609 |
+
return to_str(x._mpf_, n, **kwargs)
|
| 610 |
+
if hasattr(x, '_mpc_'):
|
| 611 |
+
return "(" + mpc_to_str(x._mpc_, n, **kwargs) + ")"
|
| 612 |
+
if isinstance(x, basestring):
|
| 613 |
+
return repr(x)
|
| 614 |
+
if isinstance(x, ctx.matrix):
|
| 615 |
+
return x.__nstr__(n, **kwargs)
|
| 616 |
+
return str(x)
|
| 617 |
+
|
| 618 |
+
def _convert_fallback(ctx, x, strings):
|
| 619 |
+
if strings and isinstance(x, basestring):
|
| 620 |
+
if 'j' in x.lower():
|
| 621 |
+
x = x.lower().replace(' ', '')
|
| 622 |
+
match = get_complex.match(x)
|
| 623 |
+
re = match.group('re')
|
| 624 |
+
if not re:
|
| 625 |
+
re = 0
|
| 626 |
+
im = match.group('im').rstrip('j')
|
| 627 |
+
return ctx.mpc(ctx.convert(re), ctx.convert(im))
|
| 628 |
+
if hasattr(x, "_mpi_"):
|
| 629 |
+
a, b = x._mpi_
|
| 630 |
+
if a == b:
|
| 631 |
+
return ctx.make_mpf(a)
|
| 632 |
+
else:
|
| 633 |
+
raise ValueError("can only create mpf from zero-width interval")
|
| 634 |
+
raise TypeError("cannot create mpf from " + repr(x))
|
| 635 |
+
|
| 636 |
+
def mpmathify(ctx, *args, **kwargs):
|
| 637 |
+
return ctx.convert(*args, **kwargs)
|
| 638 |
+
|
| 639 |
+
def _parse_prec(ctx, kwargs):
|
| 640 |
+
if kwargs:
|
| 641 |
+
if kwargs.get('exact'):
|
| 642 |
+
return 0, 'f'
|
| 643 |
+
prec, rounding = ctx._prec_rounding
|
| 644 |
+
if 'rounding' in kwargs:
|
| 645 |
+
rounding = kwargs['rounding']
|
| 646 |
+
if 'prec' in kwargs:
|
| 647 |
+
prec = kwargs['prec']
|
| 648 |
+
if prec == ctx.inf:
|
| 649 |
+
return 0, 'f'
|
| 650 |
+
else:
|
| 651 |
+
prec = int(prec)
|
| 652 |
+
elif 'dps' in kwargs:
|
| 653 |
+
dps = kwargs['dps']
|
| 654 |
+
if dps == ctx.inf:
|
| 655 |
+
return 0, 'f'
|
| 656 |
+
prec = dps_to_prec(dps)
|
| 657 |
+
return prec, rounding
|
| 658 |
+
return ctx._prec_rounding
|
| 659 |
+
|
| 660 |
+
_exact_overflow_msg = "the exact result does not fit in memory"
|
| 661 |
+
|
| 662 |
+
_hypsum_msg = """hypsum() failed to converge to the requested %i bits of accuracy
|
| 663 |
+
using a working precision of %i bits. Try with a higher maxprec,
|
| 664 |
+
maxterms, or set zeroprec."""
|
| 665 |
+
|
| 666 |
+
def hypsum(ctx, p, q, flags, coeffs, z, accurate_small=True, **kwargs):
|
| 667 |
+
if hasattr(z, "_mpf_"):
|
| 668 |
+
key = p, q, flags, 'R'
|
| 669 |
+
v = z._mpf_
|
| 670 |
+
elif hasattr(z, "_mpc_"):
|
| 671 |
+
key = p, q, flags, 'C'
|
| 672 |
+
v = z._mpc_
|
| 673 |
+
if key not in ctx.hyp_summators:
|
| 674 |
+
ctx.hyp_summators[key] = libmp.make_hyp_summator(key)[1]
|
| 675 |
+
summator = ctx.hyp_summators[key]
|
| 676 |
+
prec = ctx.prec
|
| 677 |
+
maxprec = kwargs.get('maxprec', ctx._default_hyper_maxprec(prec))
|
| 678 |
+
extraprec = 50
|
| 679 |
+
epsshift = 25
|
| 680 |
+
# Jumps in magnitude occur when parameters are close to negative
|
| 681 |
+
# integers. We must ensure that these terms are included in
|
| 682 |
+
# the sum and added accurately
|
| 683 |
+
magnitude_check = {}
|
| 684 |
+
max_total_jump = 0
|
| 685 |
+
for i, c in enumerate(coeffs):
|
| 686 |
+
if flags[i] == 'Z':
|
| 687 |
+
if i >= p and c <= 0:
|
| 688 |
+
ok = False
|
| 689 |
+
for ii, cc in enumerate(coeffs[:p]):
|
| 690 |
+
# Note: c <= cc or c < cc, depending on convention
|
| 691 |
+
if flags[ii] == 'Z' and cc <= 0 and c <= cc:
|
| 692 |
+
ok = True
|
| 693 |
+
if not ok:
|
| 694 |
+
raise ZeroDivisionError("pole in hypergeometric series")
|
| 695 |
+
continue
|
| 696 |
+
n, d = ctx.nint_distance(c)
|
| 697 |
+
n = -int(n)
|
| 698 |
+
d = -d
|
| 699 |
+
if i >= p and n >= 0 and d > 4:
|
| 700 |
+
if n in magnitude_check:
|
| 701 |
+
magnitude_check[n] += d
|
| 702 |
+
else:
|
| 703 |
+
magnitude_check[n] = d
|
| 704 |
+
extraprec = max(extraprec, d - prec + 60)
|
| 705 |
+
max_total_jump += abs(d)
|
| 706 |
+
while 1:
|
| 707 |
+
if extraprec > maxprec:
|
| 708 |
+
raise ValueError(ctx._hypsum_msg % (prec, prec+extraprec))
|
| 709 |
+
wp = prec + extraprec
|
| 710 |
+
if magnitude_check:
|
| 711 |
+
mag_dict = dict((n,None) for n in magnitude_check)
|
| 712 |
+
else:
|
| 713 |
+
mag_dict = {}
|
| 714 |
+
zv, have_complex, magnitude = summator(coeffs, v, prec, wp, \
|
| 715 |
+
epsshift, mag_dict, **kwargs)
|
| 716 |
+
cancel = -magnitude
|
| 717 |
+
jumps_resolved = True
|
| 718 |
+
if extraprec < max_total_jump:
|
| 719 |
+
for n in mag_dict.values():
|
| 720 |
+
if (n is None) or (n < prec):
|
| 721 |
+
jumps_resolved = False
|
| 722 |
+
break
|
| 723 |
+
accurate = (cancel < extraprec-25-5 or not accurate_small)
|
| 724 |
+
if jumps_resolved:
|
| 725 |
+
if accurate:
|
| 726 |
+
break
|
| 727 |
+
# zero?
|
| 728 |
+
zeroprec = kwargs.get('zeroprec')
|
| 729 |
+
if zeroprec is not None:
|
| 730 |
+
if cancel > zeroprec:
|
| 731 |
+
if have_complex:
|
| 732 |
+
return ctx.mpc(0)
|
| 733 |
+
else:
|
| 734 |
+
return ctx.zero
|
| 735 |
+
|
| 736 |
+
# Some near-singularities were not included, so increase
|
| 737 |
+
# precision and repeat until they are
|
| 738 |
+
extraprec *= 2
|
| 739 |
+
# Possible workaround for bad roundoff in fixed-point arithmetic
|
| 740 |
+
epsshift += 5
|
| 741 |
+
extraprec += 5
|
| 742 |
+
|
| 743 |
+
if type(zv) is tuple:
|
| 744 |
+
if have_complex:
|
| 745 |
+
return ctx.make_mpc(zv)
|
| 746 |
+
else:
|
| 747 |
+
return ctx.make_mpf(zv)
|
| 748 |
+
else:
|
| 749 |
+
return zv
|
| 750 |
+
|
| 751 |
+
def ldexp(ctx, x, n):
|
| 752 |
+
r"""
|
| 753 |
+
Computes `x 2^n` efficiently. No rounding is performed.
|
| 754 |
+
The argument `x` must be a real floating-point number (or
|
| 755 |
+
possible to convert into one) and `n` must be a Python ``int``.
|
| 756 |
+
|
| 757 |
+
>>> from mpmath import *
|
| 758 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 759 |
+
>>> ldexp(1, 10)
|
| 760 |
+
mpf('1024.0')
|
| 761 |
+
>>> ldexp(1, -3)
|
| 762 |
+
mpf('0.125')
|
| 763 |
+
|
| 764 |
+
"""
|
| 765 |
+
x = ctx.convert(x)
|
| 766 |
+
return ctx.make_mpf(libmp.mpf_shift(x._mpf_, n))
|
| 767 |
+
|
| 768 |
+
def frexp(ctx, x):
|
| 769 |
+
r"""
|
| 770 |
+
Given a real number `x`, returns `(y, n)` with `y \in [0.5, 1)`,
|
| 771 |
+
`n` a Python integer, and such that `x = y 2^n`. No rounding is
|
| 772 |
+
performed.
|
| 773 |
+
|
| 774 |
+
>>> from mpmath import *
|
| 775 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 776 |
+
>>> frexp(7.5)
|
| 777 |
+
(mpf('0.9375'), 3)
|
| 778 |
+
|
| 779 |
+
"""
|
| 780 |
+
x = ctx.convert(x)
|
| 781 |
+
y, n = libmp.mpf_frexp(x._mpf_)
|
| 782 |
+
return ctx.make_mpf(y), n
|
| 783 |
+
|
| 784 |
+
def fneg(ctx, x, **kwargs):
|
| 785 |
+
"""
|
| 786 |
+
Negates the number *x*, giving a floating-point result, optionally
|
| 787 |
+
using a custom precision and rounding mode.
|
| 788 |
+
|
| 789 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 790 |
+
of how to specify precision and rounding.
|
| 791 |
+
|
| 792 |
+
**Examples**
|
| 793 |
+
|
| 794 |
+
An mpmath number is returned::
|
| 795 |
+
|
| 796 |
+
>>> from mpmath import *
|
| 797 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 798 |
+
>>> fneg(2.5)
|
| 799 |
+
mpf('-2.5')
|
| 800 |
+
>>> fneg(-5+2j)
|
| 801 |
+
mpc(real='5.0', imag='-2.0')
|
| 802 |
+
|
| 803 |
+
Precise control over rounding is possible::
|
| 804 |
+
|
| 805 |
+
>>> x = fadd(2, 1e-100, exact=True)
|
| 806 |
+
>>> fneg(x)
|
| 807 |
+
mpf('-2.0')
|
| 808 |
+
>>> fneg(x, rounding='f')
|
| 809 |
+
mpf('-2.0000000000000004')
|
| 810 |
+
|
| 811 |
+
Negating with and without roundoff::
|
| 812 |
+
|
| 813 |
+
>>> n = 200000000000000000000001
|
| 814 |
+
>>> print(int(-mpf(n)))
|
| 815 |
+
-200000000000000016777216
|
| 816 |
+
>>> print(int(fneg(n)))
|
| 817 |
+
-200000000000000016777216
|
| 818 |
+
>>> print(int(fneg(n, prec=log(n,2)+1)))
|
| 819 |
+
-200000000000000000000001
|
| 820 |
+
>>> print(int(fneg(n, dps=log(n,10)+1)))
|
| 821 |
+
-200000000000000000000001
|
| 822 |
+
>>> print(int(fneg(n, prec=inf)))
|
| 823 |
+
-200000000000000000000001
|
| 824 |
+
>>> print(int(fneg(n, dps=inf)))
|
| 825 |
+
-200000000000000000000001
|
| 826 |
+
>>> print(int(fneg(n, exact=True)))
|
| 827 |
+
-200000000000000000000001
|
| 828 |
+
|
| 829 |
+
"""
|
| 830 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 831 |
+
x = ctx.convert(x)
|
| 832 |
+
if hasattr(x, '_mpf_'):
|
| 833 |
+
return ctx.make_mpf(mpf_neg(x._mpf_, prec, rounding))
|
| 834 |
+
if hasattr(x, '_mpc_'):
|
| 835 |
+
return ctx.make_mpc(mpc_neg(x._mpc_, prec, rounding))
|
| 836 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 837 |
+
|
| 838 |
+
def fadd(ctx, x, y, **kwargs):
|
| 839 |
+
"""
|
| 840 |
+
Adds the numbers *x* and *y*, giving a floating-point result,
|
| 841 |
+
optionally using a custom precision and rounding mode.
|
| 842 |
+
|
| 843 |
+
The default precision is the working precision of the context.
|
| 844 |
+
You can specify a custom precision in bits by passing the *prec* keyword
|
| 845 |
+
argument, or by providing an equivalent decimal precision with the *dps*
|
| 846 |
+
keyword argument. If the precision is set to ``+inf``, or if the flag
|
| 847 |
+
*exact=True* is passed, an exact addition with no rounding is performed.
|
| 848 |
+
|
| 849 |
+
When the precision is finite, the optional *rounding* keyword argument
|
| 850 |
+
specifies the direction of rounding. Valid options are ``'n'`` for
|
| 851 |
+
nearest (default), ``'f'`` for floor, ``'c'`` for ceiling, ``'d'``
|
| 852 |
+
for down, ``'u'`` for up.
|
| 853 |
+
|
| 854 |
+
**Examples**
|
| 855 |
+
|
| 856 |
+
Using :func:`~mpmath.fadd` with precision and rounding control::
|
| 857 |
+
|
| 858 |
+
>>> from mpmath import *
|
| 859 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 860 |
+
>>> fadd(2, 1e-20)
|
| 861 |
+
mpf('2.0')
|
| 862 |
+
>>> fadd(2, 1e-20, rounding='u')
|
| 863 |
+
mpf('2.0000000000000004')
|
| 864 |
+
>>> nprint(fadd(2, 1e-20, prec=100), 25)
|
| 865 |
+
2.00000000000000000001
|
| 866 |
+
>>> nprint(fadd(2, 1e-20, dps=15), 25)
|
| 867 |
+
2.0
|
| 868 |
+
>>> nprint(fadd(2, 1e-20, dps=25), 25)
|
| 869 |
+
2.00000000000000000001
|
| 870 |
+
>>> nprint(fadd(2, 1e-20, exact=True), 25)
|
| 871 |
+
2.00000000000000000001
|
| 872 |
+
|
| 873 |
+
Exact addition avoids cancellation errors, enforcing familiar laws
|
| 874 |
+
of numbers such as `x+y-x = y`, which don't hold in floating-point
|
| 875 |
+
arithmetic with finite precision::
|
| 876 |
+
|
| 877 |
+
>>> x, y = mpf(2), mpf('1e-1000')
|
| 878 |
+
>>> print(x + y - x)
|
| 879 |
+
0.0
|
| 880 |
+
>>> print(fadd(x, y, prec=inf) - x)
|
| 881 |
+
1.0e-1000
|
| 882 |
+
>>> print(fadd(x, y, exact=True) - x)
|
| 883 |
+
1.0e-1000
|
| 884 |
+
|
| 885 |
+
Exact addition can be inefficient and may be impossible to perform
|
| 886 |
+
with large magnitude differences::
|
| 887 |
+
|
| 888 |
+
>>> fadd(1, '1e-100000000000000000000', prec=inf)
|
| 889 |
+
Traceback (most recent call last):
|
| 890 |
+
...
|
| 891 |
+
OverflowError: the exact result does not fit in memory
|
| 892 |
+
|
| 893 |
+
"""
|
| 894 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 895 |
+
x = ctx.convert(x)
|
| 896 |
+
y = ctx.convert(y)
|
| 897 |
+
try:
|
| 898 |
+
if hasattr(x, '_mpf_'):
|
| 899 |
+
if hasattr(y, '_mpf_'):
|
| 900 |
+
return ctx.make_mpf(mpf_add(x._mpf_, y._mpf_, prec, rounding))
|
| 901 |
+
if hasattr(y, '_mpc_'):
|
| 902 |
+
return ctx.make_mpc(mpc_add_mpf(y._mpc_, x._mpf_, prec, rounding))
|
| 903 |
+
if hasattr(x, '_mpc_'):
|
| 904 |
+
if hasattr(y, '_mpf_'):
|
| 905 |
+
return ctx.make_mpc(mpc_add_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 906 |
+
if hasattr(y, '_mpc_'):
|
| 907 |
+
return ctx.make_mpc(mpc_add(x._mpc_, y._mpc_, prec, rounding))
|
| 908 |
+
except (ValueError, OverflowError):
|
| 909 |
+
raise OverflowError(ctx._exact_overflow_msg)
|
| 910 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 911 |
+
|
| 912 |
+
def fsub(ctx, x, y, **kwargs):
|
| 913 |
+
"""
|
| 914 |
+
Subtracts the numbers *x* and *y*, giving a floating-point result,
|
| 915 |
+
optionally using a custom precision and rounding mode.
|
| 916 |
+
|
| 917 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 918 |
+
of how to specify precision and rounding.
|
| 919 |
+
|
| 920 |
+
**Examples**
|
| 921 |
+
|
| 922 |
+
Using :func:`~mpmath.fsub` with precision and rounding control::
|
| 923 |
+
|
| 924 |
+
>>> from mpmath import *
|
| 925 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 926 |
+
>>> fsub(2, 1e-20)
|
| 927 |
+
mpf('2.0')
|
| 928 |
+
>>> fsub(2, 1e-20, rounding='d')
|
| 929 |
+
mpf('1.9999999999999998')
|
| 930 |
+
>>> nprint(fsub(2, 1e-20, prec=100), 25)
|
| 931 |
+
1.99999999999999999999
|
| 932 |
+
>>> nprint(fsub(2, 1e-20, dps=15), 25)
|
| 933 |
+
2.0
|
| 934 |
+
>>> nprint(fsub(2, 1e-20, dps=25), 25)
|
| 935 |
+
1.99999999999999999999
|
| 936 |
+
>>> nprint(fsub(2, 1e-20, exact=True), 25)
|
| 937 |
+
1.99999999999999999999
|
| 938 |
+
|
| 939 |
+
Exact subtraction avoids cancellation errors, enforcing familiar laws
|
| 940 |
+
of numbers such as `x-y+y = x`, which don't hold in floating-point
|
| 941 |
+
arithmetic with finite precision::
|
| 942 |
+
|
| 943 |
+
>>> x, y = mpf(2), mpf('1e1000')
|
| 944 |
+
>>> print(x - y + y)
|
| 945 |
+
0.0
|
| 946 |
+
>>> print(fsub(x, y, prec=inf) + y)
|
| 947 |
+
2.0
|
| 948 |
+
>>> print(fsub(x, y, exact=True) + y)
|
| 949 |
+
2.0
|
| 950 |
+
|
| 951 |
+
Exact addition can be inefficient and may be impossible to perform
|
| 952 |
+
with large magnitude differences::
|
| 953 |
+
|
| 954 |
+
>>> fsub(1, '1e-100000000000000000000', prec=inf)
|
| 955 |
+
Traceback (most recent call last):
|
| 956 |
+
...
|
| 957 |
+
OverflowError: the exact result does not fit in memory
|
| 958 |
+
|
| 959 |
+
"""
|
| 960 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 961 |
+
x = ctx.convert(x)
|
| 962 |
+
y = ctx.convert(y)
|
| 963 |
+
try:
|
| 964 |
+
if hasattr(x, '_mpf_'):
|
| 965 |
+
if hasattr(y, '_mpf_'):
|
| 966 |
+
return ctx.make_mpf(mpf_sub(x._mpf_, y._mpf_, prec, rounding))
|
| 967 |
+
if hasattr(y, '_mpc_'):
|
| 968 |
+
return ctx.make_mpc(mpc_sub((x._mpf_, fzero), y._mpc_, prec, rounding))
|
| 969 |
+
if hasattr(x, '_mpc_'):
|
| 970 |
+
if hasattr(y, '_mpf_'):
|
| 971 |
+
return ctx.make_mpc(mpc_sub_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 972 |
+
if hasattr(y, '_mpc_'):
|
| 973 |
+
return ctx.make_mpc(mpc_sub(x._mpc_, y._mpc_, prec, rounding))
|
| 974 |
+
except (ValueError, OverflowError):
|
| 975 |
+
raise OverflowError(ctx._exact_overflow_msg)
|
| 976 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 977 |
+
|
| 978 |
+
def fmul(ctx, x, y, **kwargs):
|
| 979 |
+
"""
|
| 980 |
+
Multiplies the numbers *x* and *y*, giving a floating-point result,
|
| 981 |
+
optionally using a custom precision and rounding mode.
|
| 982 |
+
|
| 983 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 984 |
+
of how to specify precision and rounding.
|
| 985 |
+
|
| 986 |
+
**Examples**
|
| 987 |
+
|
| 988 |
+
The result is an mpmath number::
|
| 989 |
+
|
| 990 |
+
>>> from mpmath import *
|
| 991 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 992 |
+
>>> fmul(2, 5.0)
|
| 993 |
+
mpf('10.0')
|
| 994 |
+
>>> fmul(0.5j, 0.5)
|
| 995 |
+
mpc(real='0.0', imag='0.25')
|
| 996 |
+
|
| 997 |
+
Avoiding roundoff::
|
| 998 |
+
|
| 999 |
+
>>> x, y = 10**10+1, 10**15+1
|
| 1000 |
+
>>> print(x*y)
|
| 1001 |
+
10000000001000010000000001
|
| 1002 |
+
>>> print(mpf(x) * mpf(y))
|
| 1003 |
+
1.0000000001e+25
|
| 1004 |
+
>>> print(int(mpf(x) * mpf(y)))
|
| 1005 |
+
10000000001000011026399232
|
| 1006 |
+
>>> print(int(fmul(x, y)))
|
| 1007 |
+
10000000001000011026399232
|
| 1008 |
+
>>> print(int(fmul(x, y, dps=25)))
|
| 1009 |
+
10000000001000010000000001
|
| 1010 |
+
>>> print(int(fmul(x, y, exact=True)))
|
| 1011 |
+
10000000001000010000000001
|
| 1012 |
+
|
| 1013 |
+
Exact multiplication with complex numbers can be inefficient and may
|
| 1014 |
+
be impossible to perform with large magnitude differences between
|
| 1015 |
+
real and imaginary parts::
|
| 1016 |
+
|
| 1017 |
+
>>> x = 1+2j
|
| 1018 |
+
>>> y = mpc(2, '1e-100000000000000000000')
|
| 1019 |
+
>>> fmul(x, y)
|
| 1020 |
+
mpc(real='2.0', imag='4.0')
|
| 1021 |
+
>>> fmul(x, y, rounding='u')
|
| 1022 |
+
mpc(real='2.0', imag='4.0000000000000009')
|
| 1023 |
+
>>> fmul(x, y, exact=True)
|
| 1024 |
+
Traceback (most recent call last):
|
| 1025 |
+
...
|
| 1026 |
+
OverflowError: the exact result does not fit in memory
|
| 1027 |
+
|
| 1028 |
+
"""
|
| 1029 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 1030 |
+
x = ctx.convert(x)
|
| 1031 |
+
y = ctx.convert(y)
|
| 1032 |
+
try:
|
| 1033 |
+
if hasattr(x, '_mpf_'):
|
| 1034 |
+
if hasattr(y, '_mpf_'):
|
| 1035 |
+
return ctx.make_mpf(mpf_mul(x._mpf_, y._mpf_, prec, rounding))
|
| 1036 |
+
if hasattr(y, '_mpc_'):
|
| 1037 |
+
return ctx.make_mpc(mpc_mul_mpf(y._mpc_, x._mpf_, prec, rounding))
|
| 1038 |
+
if hasattr(x, '_mpc_'):
|
| 1039 |
+
if hasattr(y, '_mpf_'):
|
| 1040 |
+
return ctx.make_mpc(mpc_mul_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 1041 |
+
if hasattr(y, '_mpc_'):
|
| 1042 |
+
return ctx.make_mpc(mpc_mul(x._mpc_, y._mpc_, prec, rounding))
|
| 1043 |
+
except (ValueError, OverflowError):
|
| 1044 |
+
raise OverflowError(ctx._exact_overflow_msg)
|
| 1045 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 1046 |
+
|
| 1047 |
+
def fdiv(ctx, x, y, **kwargs):
|
| 1048 |
+
"""
|
| 1049 |
+
Divides the numbers *x* and *y*, giving a floating-point result,
|
| 1050 |
+
optionally using a custom precision and rounding mode.
|
| 1051 |
+
|
| 1052 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 1053 |
+
of how to specify precision and rounding.
|
| 1054 |
+
|
| 1055 |
+
**Examples**
|
| 1056 |
+
|
| 1057 |
+
The result is an mpmath number::
|
| 1058 |
+
|
| 1059 |
+
>>> from mpmath import *
|
| 1060 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 1061 |
+
>>> fdiv(3, 2)
|
| 1062 |
+
mpf('1.5')
|
| 1063 |
+
>>> fdiv(2, 3)
|
| 1064 |
+
mpf('0.66666666666666663')
|
| 1065 |
+
>>> fdiv(2+4j, 0.5)
|
| 1066 |
+
mpc(real='4.0', imag='8.0')
|
| 1067 |
+
|
| 1068 |
+
The rounding direction and precision can be controlled::
|
| 1069 |
+
|
| 1070 |
+
>>> fdiv(2, 3, dps=3) # Should be accurate to at least 3 digits
|
| 1071 |
+
mpf('0.6666259765625')
|
| 1072 |
+
>>> fdiv(2, 3, rounding='d')
|
| 1073 |
+
mpf('0.66666666666666663')
|
| 1074 |
+
>>> fdiv(2, 3, prec=60)
|
| 1075 |
+
mpf('0.66666666666666667')
|
| 1076 |
+
>>> fdiv(2, 3, rounding='u')
|
| 1077 |
+
mpf('0.66666666666666674')
|
| 1078 |
+
|
| 1079 |
+
Checking the error of a division by performing it at higher precision::
|
| 1080 |
+
|
| 1081 |
+
>>> fdiv(2, 3) - fdiv(2, 3, prec=100)
|
| 1082 |
+
mpf('-3.7007434154172148e-17')
|
| 1083 |
+
|
| 1084 |
+
Unlike :func:`~mpmath.fadd`, :func:`~mpmath.fmul`, etc., exact division is not
|
| 1085 |
+
allowed since the quotient of two floating-point numbers generally
|
| 1086 |
+
does not have an exact floating-point representation. (In the
|
| 1087 |
+
future this might be changed to allow the case where the division
|
| 1088 |
+
is actually exact.)
|
| 1089 |
+
|
| 1090 |
+
>>> fdiv(2, 3, exact=True)
|
| 1091 |
+
Traceback (most recent call last):
|
| 1092 |
+
...
|
| 1093 |
+
ValueError: division is not an exact operation
|
| 1094 |
+
|
| 1095 |
+
"""
|
| 1096 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 1097 |
+
if not prec:
|
| 1098 |
+
raise ValueError("division is not an exact operation")
|
| 1099 |
+
x = ctx.convert(x)
|
| 1100 |
+
y = ctx.convert(y)
|
| 1101 |
+
if hasattr(x, '_mpf_'):
|
| 1102 |
+
if hasattr(y, '_mpf_'):
|
| 1103 |
+
return ctx.make_mpf(mpf_div(x._mpf_, y._mpf_, prec, rounding))
|
| 1104 |
+
if hasattr(y, '_mpc_'):
|
| 1105 |
+
return ctx.make_mpc(mpc_div((x._mpf_, fzero), y._mpc_, prec, rounding))
|
| 1106 |
+
if hasattr(x, '_mpc_'):
|
| 1107 |
+
if hasattr(y, '_mpf_'):
|
| 1108 |
+
return ctx.make_mpc(mpc_div_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 1109 |
+
if hasattr(y, '_mpc_'):
|
| 1110 |
+
return ctx.make_mpc(mpc_div(x._mpc_, y._mpc_, prec, rounding))
|
| 1111 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 1112 |
+
|
| 1113 |
+
def nint_distance(ctx, x):
|
| 1114 |
+
r"""
|
| 1115 |
+
Return `(n,d)` where `n` is the nearest integer to `x` and `d` is
|
| 1116 |
+
an estimate of `\log_2(|x-n|)`. If `d < 0`, `-d` gives the precision
|
| 1117 |
+
(measured in bits) lost to cancellation when computing `x-n`.
|
| 1118 |
+
|
| 1119 |
+
>>> from mpmath import *
|
| 1120 |
+
>>> n, d = nint_distance(5)
|
| 1121 |
+
>>> print(n); print(d)
|
| 1122 |
+
5
|
| 1123 |
+
-inf
|
| 1124 |
+
>>> n, d = nint_distance(mpf(5))
|
| 1125 |
+
>>> print(n); print(d)
|
| 1126 |
+
5
|
| 1127 |
+
-inf
|
| 1128 |
+
>>> n, d = nint_distance(mpf(5.00000001))
|
| 1129 |
+
>>> print(n); print(d)
|
| 1130 |
+
5
|
| 1131 |
+
-26
|
| 1132 |
+
>>> n, d = nint_distance(mpf(4.99999999))
|
| 1133 |
+
>>> print(n); print(d)
|
| 1134 |
+
5
|
| 1135 |
+
-26
|
| 1136 |
+
>>> n, d = nint_distance(mpc(5,10))
|
| 1137 |
+
>>> print(n); print(d)
|
| 1138 |
+
5
|
| 1139 |
+
4
|
| 1140 |
+
>>> n, d = nint_distance(mpc(5,0.000001))
|
| 1141 |
+
>>> print(n); print(d)
|
| 1142 |
+
5
|
| 1143 |
+
-19
|
| 1144 |
+
|
| 1145 |
+
"""
|
| 1146 |
+
typx = type(x)
|
| 1147 |
+
if typx in int_types:
|
| 1148 |
+
return int(x), ctx.ninf
|
| 1149 |
+
elif typx is rational.mpq:
|
| 1150 |
+
p, q = x._mpq_
|
| 1151 |
+
n, r = divmod(p, q)
|
| 1152 |
+
if 2*r >= q:
|
| 1153 |
+
n += 1
|
| 1154 |
+
elif not r:
|
| 1155 |
+
return n, ctx.ninf
|
| 1156 |
+
# log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q)
|
| 1157 |
+
d = bitcount(abs(p-n*q)) - bitcount(q)
|
| 1158 |
+
return n, d
|
| 1159 |
+
if hasattr(x, "_mpf_"):
|
| 1160 |
+
re = x._mpf_
|
| 1161 |
+
im_dist = ctx.ninf
|
| 1162 |
+
elif hasattr(x, "_mpc_"):
|
| 1163 |
+
re, im = x._mpc_
|
| 1164 |
+
isign, iman, iexp, ibc = im
|
| 1165 |
+
if iman:
|
| 1166 |
+
im_dist = iexp + ibc
|
| 1167 |
+
elif im == fzero:
|
| 1168 |
+
im_dist = ctx.ninf
|
| 1169 |
+
else:
|
| 1170 |
+
raise ValueError("requires a finite number")
|
| 1171 |
+
else:
|
| 1172 |
+
x = ctx.convert(x)
|
| 1173 |
+
if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"):
|
| 1174 |
+
return ctx.nint_distance(x)
|
| 1175 |
+
else:
|
| 1176 |
+
raise TypeError("requires an mpf/mpc")
|
| 1177 |
+
sign, man, exp, bc = re
|
| 1178 |
+
mag = exp+bc
|
| 1179 |
+
# |x| < 0.5
|
| 1180 |
+
if mag < 0:
|
| 1181 |
+
n = 0
|
| 1182 |
+
re_dist = mag
|
| 1183 |
+
elif man:
|
| 1184 |
+
# exact integer
|
| 1185 |
+
if exp >= 0:
|
| 1186 |
+
n = man << exp
|
| 1187 |
+
re_dist = ctx.ninf
|
| 1188 |
+
# exact half-integer
|
| 1189 |
+
elif exp == -1:
|
| 1190 |
+
n = (man>>1)+1
|
| 1191 |
+
re_dist = 0
|
| 1192 |
+
else:
|
| 1193 |
+
d = (-exp-1)
|
| 1194 |
+
t = man >> d
|
| 1195 |
+
if t & 1:
|
| 1196 |
+
t += 1
|
| 1197 |
+
man = (t<<d) - man
|
| 1198 |
+
else:
|
| 1199 |
+
man -= (t<<d)
|
| 1200 |
+
n = t>>1 # int(t)>>1
|
| 1201 |
+
re_dist = exp+bitcount(man)
|
| 1202 |
+
if sign:
|
| 1203 |
+
n = -n
|
| 1204 |
+
elif re == fzero:
|
| 1205 |
+
re_dist = ctx.ninf
|
| 1206 |
+
n = 0
|
| 1207 |
+
else:
|
| 1208 |
+
raise ValueError("requires a finite number")
|
| 1209 |
+
return n, max(re_dist, im_dist)
|
| 1210 |
+
|
| 1211 |
+
def fprod(ctx, factors):
|
| 1212 |
+
r"""
|
| 1213 |
+
Calculates a product containing a finite number of factors (for
|
| 1214 |
+
infinite products, see :func:`~mpmath.nprod`). The factors will be
|
| 1215 |
+
converted to mpmath numbers.
|
| 1216 |
+
|
| 1217 |
+
>>> from mpmath import *
|
| 1218 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 1219 |
+
>>> fprod([1, 2, 0.5, 7])
|
| 1220 |
+
mpf('7.0')
|
| 1221 |
+
|
| 1222 |
+
"""
|
| 1223 |
+
orig = ctx.prec
|
| 1224 |
+
try:
|
| 1225 |
+
v = ctx.one
|
| 1226 |
+
for p in factors:
|
| 1227 |
+
v *= p
|
| 1228 |
+
finally:
|
| 1229 |
+
ctx.prec = orig
|
| 1230 |
+
return +v
|
| 1231 |
+
|
| 1232 |
+
def rand(ctx):
|
| 1233 |
+
"""
|
| 1234 |
+
Returns an ``mpf`` with value chosen randomly from `[0, 1)`.
|
| 1235 |
+
The number of randomly generated bits in the mantissa is equal
|
| 1236 |
+
to the working precision.
|
| 1237 |
+
"""
|
| 1238 |
+
return ctx.make_mpf(mpf_rand(ctx._prec))
|
| 1239 |
+
|
| 1240 |
+
def fraction(ctx, p, q):
|
| 1241 |
+
"""
|
| 1242 |
+
Given Python integers `(p, q)`, returns a lazy ``mpf`` representing
|
| 1243 |
+
the fraction `p/q`. The value is updated with the precision.
|
| 1244 |
+
|
| 1245 |
+
>>> from mpmath import *
|
| 1246 |
+
>>> mp.dps = 15
|
| 1247 |
+
>>> a = fraction(1,100)
|
| 1248 |
+
>>> b = mpf(1)/100
|
| 1249 |
+
>>> print(a); print(b)
|
| 1250 |
+
0.01
|
| 1251 |
+
0.01
|
| 1252 |
+
>>> mp.dps = 30
|
| 1253 |
+
>>> print(a); print(b) # a will be accurate
|
| 1254 |
+
0.01
|
| 1255 |
+
0.0100000000000000002081668171172
|
| 1256 |
+
>>> mp.dps = 15
|
| 1257 |
+
"""
|
| 1258 |
+
return ctx.constant(lambda prec, rnd: from_rational(p, q, prec, rnd),
|
| 1259 |
+
'%s/%s' % (p, q))
|
| 1260 |
+
|
| 1261 |
+
def absmin(ctx, x):
|
| 1262 |
+
return abs(ctx.convert(x))
|
| 1263 |
+
|
| 1264 |
+
def absmax(ctx, x):
|
| 1265 |
+
return abs(ctx.convert(x))
|
| 1266 |
+
|
| 1267 |
+
def _as_points(ctx, x):
|
| 1268 |
+
# XXX: remove this?
|
| 1269 |
+
if hasattr(x, '_mpi_'):
|
| 1270 |
+
a, b = x._mpi_
|
| 1271 |
+
return [ctx.make_mpf(a), ctx.make_mpf(b)]
|
| 1272 |
+
return x
|
| 1273 |
+
|
| 1274 |
+
'''
|
| 1275 |
+
def _zetasum(ctx, s, a, b):
|
| 1276 |
+
"""
|
| 1277 |
+
Computes sum of k^(-s) for k = a, a+1, ..., b with a, b both small
|
| 1278 |
+
integers.
|
| 1279 |
+
"""
|
| 1280 |
+
a = int(a)
|
| 1281 |
+
b = int(b)
|
| 1282 |
+
s = ctx.convert(s)
|
| 1283 |
+
prec, rounding = ctx._prec_rounding
|
| 1284 |
+
if hasattr(s, '_mpf_'):
|
| 1285 |
+
v = ctx.make_mpf(libmp.mpf_zetasum(s._mpf_, a, b, prec))
|
| 1286 |
+
elif hasattr(s, '_mpc_'):
|
| 1287 |
+
v = ctx.make_mpc(libmp.mpc_zetasum(s._mpc_, a, b, prec))
|
| 1288 |
+
return v
|
| 1289 |
+
'''
|
| 1290 |
+
|
| 1291 |
+
def _zetasum_fast(ctx, s, a, n, derivatives=[0], reflect=False):
|
| 1292 |
+
if not (ctx.isint(a) and hasattr(s, "_mpc_")):
|
| 1293 |
+
raise NotImplementedError
|
| 1294 |
+
a = int(a)
|
| 1295 |
+
prec = ctx._prec
|
| 1296 |
+
xs, ys = libmp.mpc_zetasum(s._mpc_, a, n, derivatives, reflect, prec)
|
| 1297 |
+
xs = [ctx.make_mpc(x) for x in xs]
|
| 1298 |
+
ys = [ctx.make_mpc(y) for y in ys]
|
| 1299 |
+
return xs, ys
|
| 1300 |
+
|
| 1301 |
+
class PrecisionManager:
|
| 1302 |
+
def __init__(self, ctx, precfun, dpsfun, normalize_output=False):
|
| 1303 |
+
self.ctx = ctx
|
| 1304 |
+
self.precfun = precfun
|
| 1305 |
+
self.dpsfun = dpsfun
|
| 1306 |
+
self.normalize_output = normalize_output
|
| 1307 |
+
def __call__(self, f):
|
| 1308 |
+
@functools.wraps(f)
|
| 1309 |
+
def g(*args, **kwargs):
|
| 1310 |
+
orig = self.ctx.prec
|
| 1311 |
+
try:
|
| 1312 |
+
if self.precfun:
|
| 1313 |
+
self.ctx.prec = self.precfun(self.ctx.prec)
|
| 1314 |
+
else:
|
| 1315 |
+
self.ctx.dps = self.dpsfun(self.ctx.dps)
|
| 1316 |
+
if self.normalize_output:
|
| 1317 |
+
v = f(*args, **kwargs)
|
| 1318 |
+
if type(v) is tuple:
|
| 1319 |
+
return tuple([+a for a in v])
|
| 1320 |
+
return +v
|
| 1321 |
+
else:
|
| 1322 |
+
return f(*args, **kwargs)
|
| 1323 |
+
finally:
|
| 1324 |
+
self.ctx.prec = orig
|
| 1325 |
+
return g
|
| 1326 |
+
def __enter__(self):
|
| 1327 |
+
self.origp = self.ctx.prec
|
| 1328 |
+
if self.precfun:
|
| 1329 |
+
self.ctx.prec = self.precfun(self.ctx.prec)
|
| 1330 |
+
else:
|
| 1331 |
+
self.ctx.dps = self.dpsfun(self.ctx.dps)
|
| 1332 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 1333 |
+
self.ctx.prec = self.origp
|
| 1334 |
+
return False
|
| 1335 |
+
|
| 1336 |
+
|
| 1337 |
+
if __name__ == '__main__':
|
| 1338 |
+
import doctest
|
| 1339 |
+
doctest.testmod()
|
.venv/lib/python3.11/site-packages/mpmath/ctx_mp_python.py
ADDED
|
@@ -0,0 +1,1149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#from ctx_base import StandardBaseContext
|
| 2 |
+
|
| 3 |
+
from .libmp.backend import basestring, exec_
|
| 4 |
+
|
| 5 |
+
from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps,
|
| 6 |
+
round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps,
|
| 7 |
+
ComplexResult, to_pickable, from_pickable, normalize,
|
| 8 |
+
from_int, from_float, from_npfloat, from_Decimal, from_str, to_int, to_float, to_str,
|
| 9 |
+
from_rational, from_man_exp,
|
| 10 |
+
fone, fzero, finf, fninf, fnan,
|
| 11 |
+
mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int,
|
| 12 |
+
mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod,
|
| 13 |
+
mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge,
|
| 14 |
+
mpf_hash, mpf_rand,
|
| 15 |
+
mpf_sum,
|
| 16 |
+
bitcount, to_fixed,
|
| 17 |
+
mpc_to_str,
|
| 18 |
+
mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate,
|
| 19 |
+
mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf,
|
| 20 |
+
mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int,
|
| 21 |
+
mpc_mpf_div,
|
| 22 |
+
mpf_pow,
|
| 23 |
+
mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10,
|
| 24 |
+
mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin,
|
| 25 |
+
mpf_glaisher, mpf_twinprime, mpf_mertens,
|
| 26 |
+
int_types)
|
| 27 |
+
|
| 28 |
+
from . import rational
|
| 29 |
+
from . import function_docs
|
| 30 |
+
|
| 31 |
+
new = object.__new__
|
| 32 |
+
|
| 33 |
+
class mpnumeric(object):
|
| 34 |
+
"""Base class for mpf and mpc."""
|
| 35 |
+
__slots__ = []
|
| 36 |
+
def __new__(cls, val):
|
| 37 |
+
raise NotImplementedError
|
| 38 |
+
|
| 39 |
+
class _mpf(mpnumeric):
|
| 40 |
+
"""
|
| 41 |
+
An mpf instance holds a real-valued floating-point number. mpf:s
|
| 42 |
+
work analogously to Python floats, but support arbitrary-precision
|
| 43 |
+
arithmetic.
|
| 44 |
+
"""
|
| 45 |
+
__slots__ = ['_mpf_']
|
| 46 |
+
|
| 47 |
+
def __new__(cls, val=fzero, **kwargs):
|
| 48 |
+
"""A new mpf can be created from a Python float, an int, a
|
| 49 |
+
or a decimal string representing a number in floating-point
|
| 50 |
+
format."""
|
| 51 |
+
prec, rounding = cls.context._prec_rounding
|
| 52 |
+
if kwargs:
|
| 53 |
+
prec = kwargs.get('prec', prec)
|
| 54 |
+
if 'dps' in kwargs:
|
| 55 |
+
prec = dps_to_prec(kwargs['dps'])
|
| 56 |
+
rounding = kwargs.get('rounding', rounding)
|
| 57 |
+
if type(val) is cls:
|
| 58 |
+
sign, man, exp, bc = val._mpf_
|
| 59 |
+
if (not man) and exp:
|
| 60 |
+
return val
|
| 61 |
+
v = new(cls)
|
| 62 |
+
v._mpf_ = normalize(sign, man, exp, bc, prec, rounding)
|
| 63 |
+
return v
|
| 64 |
+
elif type(val) is tuple:
|
| 65 |
+
if len(val) == 2:
|
| 66 |
+
v = new(cls)
|
| 67 |
+
v._mpf_ = from_man_exp(val[0], val[1], prec, rounding)
|
| 68 |
+
return v
|
| 69 |
+
if len(val) == 4:
|
| 70 |
+
if val not in (finf, fninf, fnan):
|
| 71 |
+
sign, man, exp, bc = val
|
| 72 |
+
val = normalize(sign, MPZ(man), exp, bc, prec, rounding)
|
| 73 |
+
v = new(cls)
|
| 74 |
+
v._mpf_ = val
|
| 75 |
+
return v
|
| 76 |
+
raise ValueError
|
| 77 |
+
else:
|
| 78 |
+
v = new(cls)
|
| 79 |
+
v._mpf_ = mpf_pos(cls.mpf_convert_arg(val, prec, rounding), prec, rounding)
|
| 80 |
+
return v
|
| 81 |
+
|
| 82 |
+
@classmethod
|
| 83 |
+
def mpf_convert_arg(cls, x, prec, rounding):
|
| 84 |
+
if isinstance(x, int_types): return from_int(x)
|
| 85 |
+
if isinstance(x, float): return from_float(x)
|
| 86 |
+
if isinstance(x, basestring): return from_str(x, prec, rounding)
|
| 87 |
+
if isinstance(x, cls.context.constant): return x.func(prec, rounding)
|
| 88 |
+
if hasattr(x, '_mpf_'): return x._mpf_
|
| 89 |
+
if hasattr(x, '_mpmath_'):
|
| 90 |
+
t = cls.context.convert(x._mpmath_(prec, rounding))
|
| 91 |
+
if hasattr(t, '_mpf_'):
|
| 92 |
+
return t._mpf_
|
| 93 |
+
if hasattr(x, '_mpi_'):
|
| 94 |
+
a, b = x._mpi_
|
| 95 |
+
if a == b:
|
| 96 |
+
return a
|
| 97 |
+
raise ValueError("can only create mpf from zero-width interval")
|
| 98 |
+
raise TypeError("cannot create mpf from " + repr(x))
|
| 99 |
+
|
| 100 |
+
@classmethod
|
| 101 |
+
def mpf_convert_rhs(cls, x):
|
| 102 |
+
if isinstance(x, int_types): return from_int(x)
|
| 103 |
+
if isinstance(x, float): return from_float(x)
|
| 104 |
+
if isinstance(x, complex_types): return cls.context.mpc(x)
|
| 105 |
+
if isinstance(x, rational.mpq):
|
| 106 |
+
p, q = x._mpq_
|
| 107 |
+
return from_rational(p, q, cls.context.prec)
|
| 108 |
+
if hasattr(x, '_mpf_'): return x._mpf_
|
| 109 |
+
if hasattr(x, '_mpmath_'):
|
| 110 |
+
t = cls.context.convert(x._mpmath_(*cls.context._prec_rounding))
|
| 111 |
+
if hasattr(t, '_mpf_'):
|
| 112 |
+
return t._mpf_
|
| 113 |
+
return t
|
| 114 |
+
return NotImplemented
|
| 115 |
+
|
| 116 |
+
@classmethod
|
| 117 |
+
def mpf_convert_lhs(cls, x):
|
| 118 |
+
x = cls.mpf_convert_rhs(x)
|
| 119 |
+
if type(x) is tuple:
|
| 120 |
+
return cls.context.make_mpf(x)
|
| 121 |
+
return x
|
| 122 |
+
|
| 123 |
+
man_exp = property(lambda self: self._mpf_[1:3])
|
| 124 |
+
man = property(lambda self: self._mpf_[1])
|
| 125 |
+
exp = property(lambda self: self._mpf_[2])
|
| 126 |
+
bc = property(lambda self: self._mpf_[3])
|
| 127 |
+
|
| 128 |
+
real = property(lambda self: self)
|
| 129 |
+
imag = property(lambda self: self.context.zero)
|
| 130 |
+
|
| 131 |
+
conjugate = lambda self: self
|
| 132 |
+
|
| 133 |
+
def __getstate__(self): return to_pickable(self._mpf_)
|
| 134 |
+
def __setstate__(self, val): self._mpf_ = from_pickable(val)
|
| 135 |
+
|
| 136 |
+
def __repr__(s):
|
| 137 |
+
if s.context.pretty:
|
| 138 |
+
return str(s)
|
| 139 |
+
return "mpf('%s')" % to_str(s._mpf_, s.context._repr_digits)
|
| 140 |
+
|
| 141 |
+
def __str__(s): return to_str(s._mpf_, s.context._str_digits)
|
| 142 |
+
def __hash__(s): return mpf_hash(s._mpf_)
|
| 143 |
+
def __int__(s): return int(to_int(s._mpf_))
|
| 144 |
+
def __long__(s): return long(to_int(s._mpf_))
|
| 145 |
+
def __float__(s): return to_float(s._mpf_, rnd=s.context._prec_rounding[1])
|
| 146 |
+
def __complex__(s): return complex(float(s))
|
| 147 |
+
def __nonzero__(s): return s._mpf_ != fzero
|
| 148 |
+
|
| 149 |
+
__bool__ = __nonzero__
|
| 150 |
+
|
| 151 |
+
def __abs__(s):
|
| 152 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 153 |
+
v = new(cls)
|
| 154 |
+
v._mpf_ = mpf_abs(s._mpf_, prec, rounding)
|
| 155 |
+
return v
|
| 156 |
+
|
| 157 |
+
def __pos__(s):
|
| 158 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 159 |
+
v = new(cls)
|
| 160 |
+
v._mpf_ = mpf_pos(s._mpf_, prec, rounding)
|
| 161 |
+
return v
|
| 162 |
+
|
| 163 |
+
def __neg__(s):
|
| 164 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 165 |
+
v = new(cls)
|
| 166 |
+
v._mpf_ = mpf_neg(s._mpf_, prec, rounding)
|
| 167 |
+
return v
|
| 168 |
+
|
| 169 |
+
def _cmp(s, t, func):
|
| 170 |
+
if hasattr(t, '_mpf_'):
|
| 171 |
+
t = t._mpf_
|
| 172 |
+
else:
|
| 173 |
+
t = s.mpf_convert_rhs(t)
|
| 174 |
+
if t is NotImplemented:
|
| 175 |
+
return t
|
| 176 |
+
return func(s._mpf_, t)
|
| 177 |
+
|
| 178 |
+
def __cmp__(s, t): return s._cmp(t, mpf_cmp)
|
| 179 |
+
def __lt__(s, t): return s._cmp(t, mpf_lt)
|
| 180 |
+
def __gt__(s, t): return s._cmp(t, mpf_gt)
|
| 181 |
+
def __le__(s, t): return s._cmp(t, mpf_le)
|
| 182 |
+
def __ge__(s, t): return s._cmp(t, mpf_ge)
|
| 183 |
+
|
| 184 |
+
def __ne__(s, t):
|
| 185 |
+
v = s.__eq__(t)
|
| 186 |
+
if v is NotImplemented:
|
| 187 |
+
return v
|
| 188 |
+
return not v
|
| 189 |
+
|
| 190 |
+
def __rsub__(s, t):
|
| 191 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 192 |
+
if type(t) in int_types:
|
| 193 |
+
v = new(cls)
|
| 194 |
+
v._mpf_ = mpf_sub(from_int(t), s._mpf_, prec, rounding)
|
| 195 |
+
return v
|
| 196 |
+
t = s.mpf_convert_lhs(t)
|
| 197 |
+
if t is NotImplemented:
|
| 198 |
+
return t
|
| 199 |
+
return t - s
|
| 200 |
+
|
| 201 |
+
def __rdiv__(s, t):
|
| 202 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 203 |
+
if isinstance(t, int_types):
|
| 204 |
+
v = new(cls)
|
| 205 |
+
v._mpf_ = mpf_rdiv_int(t, s._mpf_, prec, rounding)
|
| 206 |
+
return v
|
| 207 |
+
t = s.mpf_convert_lhs(t)
|
| 208 |
+
if t is NotImplemented:
|
| 209 |
+
return t
|
| 210 |
+
return t / s
|
| 211 |
+
|
| 212 |
+
def __rpow__(s, t):
|
| 213 |
+
t = s.mpf_convert_lhs(t)
|
| 214 |
+
if t is NotImplemented:
|
| 215 |
+
return t
|
| 216 |
+
return t ** s
|
| 217 |
+
|
| 218 |
+
def __rmod__(s, t):
|
| 219 |
+
t = s.mpf_convert_lhs(t)
|
| 220 |
+
if t is NotImplemented:
|
| 221 |
+
return t
|
| 222 |
+
return t % s
|
| 223 |
+
|
| 224 |
+
def sqrt(s):
|
| 225 |
+
return s.context.sqrt(s)
|
| 226 |
+
|
| 227 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 228 |
+
return s.context.almosteq(s, t, rel_eps, abs_eps)
|
| 229 |
+
|
| 230 |
+
def to_fixed(self, prec):
|
| 231 |
+
return to_fixed(self._mpf_, prec)
|
| 232 |
+
|
| 233 |
+
def __round__(self, *args):
|
| 234 |
+
return round(float(self), *args)
|
| 235 |
+
|
| 236 |
+
mpf_binary_op = """
|
| 237 |
+
def %NAME%(self, other):
|
| 238 |
+
mpf, new, (prec, rounding) = self._ctxdata
|
| 239 |
+
sval = self._mpf_
|
| 240 |
+
if hasattr(other, '_mpf_'):
|
| 241 |
+
tval = other._mpf_
|
| 242 |
+
%WITH_MPF%
|
| 243 |
+
ttype = type(other)
|
| 244 |
+
if ttype in int_types:
|
| 245 |
+
%WITH_INT%
|
| 246 |
+
elif ttype is float:
|
| 247 |
+
tval = from_float(other)
|
| 248 |
+
%WITH_MPF%
|
| 249 |
+
elif hasattr(other, '_mpc_'):
|
| 250 |
+
tval = other._mpc_
|
| 251 |
+
mpc = type(other)
|
| 252 |
+
%WITH_MPC%
|
| 253 |
+
elif ttype is complex:
|
| 254 |
+
tval = from_float(other.real), from_float(other.imag)
|
| 255 |
+
mpc = self.context.mpc
|
| 256 |
+
%WITH_MPC%
|
| 257 |
+
if isinstance(other, mpnumeric):
|
| 258 |
+
return NotImplemented
|
| 259 |
+
try:
|
| 260 |
+
other = mpf.context.convert(other, strings=False)
|
| 261 |
+
except TypeError:
|
| 262 |
+
return NotImplemented
|
| 263 |
+
return self.%NAME%(other)
|
| 264 |
+
"""
|
| 265 |
+
|
| 266 |
+
return_mpf = "; obj = new(mpf); obj._mpf_ = val; return obj"
|
| 267 |
+
return_mpc = "; obj = new(mpc); obj._mpc_ = val; return obj"
|
| 268 |
+
|
| 269 |
+
mpf_pow_same = """
|
| 270 |
+
try:
|
| 271 |
+
val = mpf_pow(sval, tval, prec, rounding) %s
|
| 272 |
+
except ComplexResult:
|
| 273 |
+
if mpf.context.trap_complex:
|
| 274 |
+
raise
|
| 275 |
+
mpc = mpf.context.mpc
|
| 276 |
+
val = mpc_pow((sval, fzero), (tval, fzero), prec, rounding) %s
|
| 277 |
+
""" % (return_mpf, return_mpc)
|
| 278 |
+
|
| 279 |
+
def binary_op(name, with_mpf='', with_int='', with_mpc=''):
|
| 280 |
+
code = mpf_binary_op
|
| 281 |
+
code = code.replace("%WITH_INT%", with_int)
|
| 282 |
+
code = code.replace("%WITH_MPC%", with_mpc)
|
| 283 |
+
code = code.replace("%WITH_MPF%", with_mpf)
|
| 284 |
+
code = code.replace("%NAME%", name)
|
| 285 |
+
np = {}
|
| 286 |
+
exec_(code, globals(), np)
|
| 287 |
+
return np[name]
|
| 288 |
+
|
| 289 |
+
_mpf.__eq__ = binary_op('__eq__',
|
| 290 |
+
'return mpf_eq(sval, tval)',
|
| 291 |
+
'return mpf_eq(sval, from_int(other))',
|
| 292 |
+
'return (tval[1] == fzero) and mpf_eq(tval[0], sval)')
|
| 293 |
+
|
| 294 |
+
_mpf.__add__ = binary_op('__add__',
|
| 295 |
+
'val = mpf_add(sval, tval, prec, rounding)' + return_mpf,
|
| 296 |
+
'val = mpf_add(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 297 |
+
'val = mpc_add_mpf(tval, sval, prec, rounding)' + return_mpc)
|
| 298 |
+
|
| 299 |
+
_mpf.__sub__ = binary_op('__sub__',
|
| 300 |
+
'val = mpf_sub(sval, tval, prec, rounding)' + return_mpf,
|
| 301 |
+
'val = mpf_sub(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 302 |
+
'val = mpc_sub((sval, fzero), tval, prec, rounding)' + return_mpc)
|
| 303 |
+
|
| 304 |
+
_mpf.__mul__ = binary_op('__mul__',
|
| 305 |
+
'val = mpf_mul(sval, tval, prec, rounding)' + return_mpf,
|
| 306 |
+
'val = mpf_mul_int(sval, other, prec, rounding)' + return_mpf,
|
| 307 |
+
'val = mpc_mul_mpf(tval, sval, prec, rounding)' + return_mpc)
|
| 308 |
+
|
| 309 |
+
_mpf.__div__ = binary_op('__div__',
|
| 310 |
+
'val = mpf_div(sval, tval, prec, rounding)' + return_mpf,
|
| 311 |
+
'val = mpf_div(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 312 |
+
'val = mpc_mpf_div(sval, tval, prec, rounding)' + return_mpc)
|
| 313 |
+
|
| 314 |
+
_mpf.__mod__ = binary_op('__mod__',
|
| 315 |
+
'val = mpf_mod(sval, tval, prec, rounding)' + return_mpf,
|
| 316 |
+
'val = mpf_mod(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 317 |
+
'raise NotImplementedError("complex modulo")')
|
| 318 |
+
|
| 319 |
+
_mpf.__pow__ = binary_op('__pow__',
|
| 320 |
+
mpf_pow_same,
|
| 321 |
+
'val = mpf_pow_int(sval, other, prec, rounding)' + return_mpf,
|
| 322 |
+
'val = mpc_pow((sval, fzero), tval, prec, rounding)' + return_mpc)
|
| 323 |
+
|
| 324 |
+
_mpf.__radd__ = _mpf.__add__
|
| 325 |
+
_mpf.__rmul__ = _mpf.__mul__
|
| 326 |
+
_mpf.__truediv__ = _mpf.__div__
|
| 327 |
+
_mpf.__rtruediv__ = _mpf.__rdiv__
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
class _constant(_mpf):
|
| 331 |
+
"""Represents a mathematical constant with dynamic precision.
|
| 332 |
+
When printed or used in an arithmetic operation, a constant
|
| 333 |
+
is converted to a regular mpf at the working precision. A
|
| 334 |
+
regular mpf can also be obtained using the operation +x."""
|
| 335 |
+
|
| 336 |
+
def __new__(cls, func, name, docname=''):
|
| 337 |
+
a = object.__new__(cls)
|
| 338 |
+
a.name = name
|
| 339 |
+
a.func = func
|
| 340 |
+
a.__doc__ = getattr(function_docs, docname, '')
|
| 341 |
+
return a
|
| 342 |
+
|
| 343 |
+
def __call__(self, prec=None, dps=None, rounding=None):
|
| 344 |
+
prec2, rounding2 = self.context._prec_rounding
|
| 345 |
+
if not prec: prec = prec2
|
| 346 |
+
if not rounding: rounding = rounding2
|
| 347 |
+
if dps: prec = dps_to_prec(dps)
|
| 348 |
+
return self.context.make_mpf(self.func(prec, rounding))
|
| 349 |
+
|
| 350 |
+
@property
|
| 351 |
+
def _mpf_(self):
|
| 352 |
+
prec, rounding = self.context._prec_rounding
|
| 353 |
+
return self.func(prec, rounding)
|
| 354 |
+
|
| 355 |
+
def __repr__(self):
|
| 356 |
+
return "<%s: %s~>" % (self.name, self.context.nstr(self(dps=15)))
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
class _mpc(mpnumeric):
|
| 360 |
+
"""
|
| 361 |
+
An mpc represents a complex number using a pair of mpf:s (one
|
| 362 |
+
for the real part and another for the imaginary part.) The mpc
|
| 363 |
+
class behaves fairly similarly to Python's complex type.
|
| 364 |
+
"""
|
| 365 |
+
|
| 366 |
+
__slots__ = ['_mpc_']
|
| 367 |
+
|
| 368 |
+
def __new__(cls, real=0, imag=0):
|
| 369 |
+
s = object.__new__(cls)
|
| 370 |
+
if isinstance(real, complex_types):
|
| 371 |
+
real, imag = real.real, real.imag
|
| 372 |
+
elif hasattr(real, '_mpc_'):
|
| 373 |
+
s._mpc_ = real._mpc_
|
| 374 |
+
return s
|
| 375 |
+
real = cls.context.mpf(real)
|
| 376 |
+
imag = cls.context.mpf(imag)
|
| 377 |
+
s._mpc_ = (real._mpf_, imag._mpf_)
|
| 378 |
+
return s
|
| 379 |
+
|
| 380 |
+
real = property(lambda self: self.context.make_mpf(self._mpc_[0]))
|
| 381 |
+
imag = property(lambda self: self.context.make_mpf(self._mpc_[1]))
|
| 382 |
+
|
| 383 |
+
def __getstate__(self):
|
| 384 |
+
return to_pickable(self._mpc_[0]), to_pickable(self._mpc_[1])
|
| 385 |
+
|
| 386 |
+
def __setstate__(self, val):
|
| 387 |
+
self._mpc_ = from_pickable(val[0]), from_pickable(val[1])
|
| 388 |
+
|
| 389 |
+
def __repr__(s):
|
| 390 |
+
if s.context.pretty:
|
| 391 |
+
return str(s)
|
| 392 |
+
r = repr(s.real)[4:-1]
|
| 393 |
+
i = repr(s.imag)[4:-1]
|
| 394 |
+
return "%s(real=%s, imag=%s)" % (type(s).__name__, r, i)
|
| 395 |
+
|
| 396 |
+
def __str__(s):
|
| 397 |
+
return "(%s)" % mpc_to_str(s._mpc_, s.context._str_digits)
|
| 398 |
+
|
| 399 |
+
def __complex__(s):
|
| 400 |
+
return mpc_to_complex(s._mpc_, rnd=s.context._prec_rounding[1])
|
| 401 |
+
|
| 402 |
+
def __pos__(s):
|
| 403 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 404 |
+
v = new(cls)
|
| 405 |
+
v._mpc_ = mpc_pos(s._mpc_, prec, rounding)
|
| 406 |
+
return v
|
| 407 |
+
|
| 408 |
+
def __abs__(s):
|
| 409 |
+
prec, rounding = s.context._prec_rounding
|
| 410 |
+
v = new(s.context.mpf)
|
| 411 |
+
v._mpf_ = mpc_abs(s._mpc_, prec, rounding)
|
| 412 |
+
return v
|
| 413 |
+
|
| 414 |
+
def __neg__(s):
|
| 415 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 416 |
+
v = new(cls)
|
| 417 |
+
v._mpc_ = mpc_neg(s._mpc_, prec, rounding)
|
| 418 |
+
return v
|
| 419 |
+
|
| 420 |
+
def conjugate(s):
|
| 421 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 422 |
+
v = new(cls)
|
| 423 |
+
v._mpc_ = mpc_conjugate(s._mpc_, prec, rounding)
|
| 424 |
+
return v
|
| 425 |
+
|
| 426 |
+
def __nonzero__(s):
|
| 427 |
+
return mpc_is_nonzero(s._mpc_)
|
| 428 |
+
|
| 429 |
+
__bool__ = __nonzero__
|
| 430 |
+
|
| 431 |
+
def __hash__(s):
|
| 432 |
+
return mpc_hash(s._mpc_)
|
| 433 |
+
|
| 434 |
+
@classmethod
|
| 435 |
+
def mpc_convert_lhs(cls, x):
|
| 436 |
+
try:
|
| 437 |
+
y = cls.context.convert(x)
|
| 438 |
+
return y
|
| 439 |
+
except TypeError:
|
| 440 |
+
return NotImplemented
|
| 441 |
+
|
| 442 |
+
def __eq__(s, t):
|
| 443 |
+
if not hasattr(t, '_mpc_'):
|
| 444 |
+
if isinstance(t, str):
|
| 445 |
+
return False
|
| 446 |
+
t = s.mpc_convert_lhs(t)
|
| 447 |
+
if t is NotImplemented:
|
| 448 |
+
return t
|
| 449 |
+
return s.real == t.real and s.imag == t.imag
|
| 450 |
+
|
| 451 |
+
def __ne__(s, t):
|
| 452 |
+
b = s.__eq__(t)
|
| 453 |
+
if b is NotImplemented:
|
| 454 |
+
return b
|
| 455 |
+
return not b
|
| 456 |
+
|
| 457 |
+
def _compare(*args):
|
| 458 |
+
raise TypeError("no ordering relation is defined for complex numbers")
|
| 459 |
+
|
| 460 |
+
__gt__ = _compare
|
| 461 |
+
__le__ = _compare
|
| 462 |
+
__gt__ = _compare
|
| 463 |
+
__ge__ = _compare
|
| 464 |
+
|
| 465 |
+
def __add__(s, t):
|
| 466 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 467 |
+
if not hasattr(t, '_mpc_'):
|
| 468 |
+
t = s.mpc_convert_lhs(t)
|
| 469 |
+
if t is NotImplemented:
|
| 470 |
+
return t
|
| 471 |
+
if hasattr(t, '_mpf_'):
|
| 472 |
+
v = new(cls)
|
| 473 |
+
v._mpc_ = mpc_add_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 474 |
+
return v
|
| 475 |
+
v = new(cls)
|
| 476 |
+
v._mpc_ = mpc_add(s._mpc_, t._mpc_, prec, rounding)
|
| 477 |
+
return v
|
| 478 |
+
|
| 479 |
+
def __sub__(s, t):
|
| 480 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 481 |
+
if not hasattr(t, '_mpc_'):
|
| 482 |
+
t = s.mpc_convert_lhs(t)
|
| 483 |
+
if t is NotImplemented:
|
| 484 |
+
return t
|
| 485 |
+
if hasattr(t, '_mpf_'):
|
| 486 |
+
v = new(cls)
|
| 487 |
+
v._mpc_ = mpc_sub_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 488 |
+
return v
|
| 489 |
+
v = new(cls)
|
| 490 |
+
v._mpc_ = mpc_sub(s._mpc_, t._mpc_, prec, rounding)
|
| 491 |
+
return v
|
| 492 |
+
|
| 493 |
+
def __mul__(s, t):
|
| 494 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 495 |
+
if not hasattr(t, '_mpc_'):
|
| 496 |
+
if isinstance(t, int_types):
|
| 497 |
+
v = new(cls)
|
| 498 |
+
v._mpc_ = mpc_mul_int(s._mpc_, t, prec, rounding)
|
| 499 |
+
return v
|
| 500 |
+
t = s.mpc_convert_lhs(t)
|
| 501 |
+
if t is NotImplemented:
|
| 502 |
+
return t
|
| 503 |
+
if hasattr(t, '_mpf_'):
|
| 504 |
+
v = new(cls)
|
| 505 |
+
v._mpc_ = mpc_mul_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 506 |
+
return v
|
| 507 |
+
t = s.mpc_convert_lhs(t)
|
| 508 |
+
v = new(cls)
|
| 509 |
+
v._mpc_ = mpc_mul(s._mpc_, t._mpc_, prec, rounding)
|
| 510 |
+
return v
|
| 511 |
+
|
| 512 |
+
def __div__(s, t):
|
| 513 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 514 |
+
if not hasattr(t, '_mpc_'):
|
| 515 |
+
t = s.mpc_convert_lhs(t)
|
| 516 |
+
if t is NotImplemented:
|
| 517 |
+
return t
|
| 518 |
+
if hasattr(t, '_mpf_'):
|
| 519 |
+
v = new(cls)
|
| 520 |
+
v._mpc_ = mpc_div_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 521 |
+
return v
|
| 522 |
+
v = new(cls)
|
| 523 |
+
v._mpc_ = mpc_div(s._mpc_, t._mpc_, prec, rounding)
|
| 524 |
+
return v
|
| 525 |
+
|
| 526 |
+
def __pow__(s, t):
|
| 527 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 528 |
+
if isinstance(t, int_types):
|
| 529 |
+
v = new(cls)
|
| 530 |
+
v._mpc_ = mpc_pow_int(s._mpc_, t, prec, rounding)
|
| 531 |
+
return v
|
| 532 |
+
t = s.mpc_convert_lhs(t)
|
| 533 |
+
if t is NotImplemented:
|
| 534 |
+
return t
|
| 535 |
+
v = new(cls)
|
| 536 |
+
if hasattr(t, '_mpf_'):
|
| 537 |
+
v._mpc_ = mpc_pow_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 538 |
+
else:
|
| 539 |
+
v._mpc_ = mpc_pow(s._mpc_, t._mpc_, prec, rounding)
|
| 540 |
+
return v
|
| 541 |
+
|
| 542 |
+
__radd__ = __add__
|
| 543 |
+
|
| 544 |
+
def __rsub__(s, t):
|
| 545 |
+
t = s.mpc_convert_lhs(t)
|
| 546 |
+
if t is NotImplemented:
|
| 547 |
+
return t
|
| 548 |
+
return t - s
|
| 549 |
+
|
| 550 |
+
def __rmul__(s, t):
|
| 551 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 552 |
+
if isinstance(t, int_types):
|
| 553 |
+
v = new(cls)
|
| 554 |
+
v._mpc_ = mpc_mul_int(s._mpc_, t, prec, rounding)
|
| 555 |
+
return v
|
| 556 |
+
t = s.mpc_convert_lhs(t)
|
| 557 |
+
if t is NotImplemented:
|
| 558 |
+
return t
|
| 559 |
+
return t * s
|
| 560 |
+
|
| 561 |
+
def __rdiv__(s, t):
|
| 562 |
+
t = s.mpc_convert_lhs(t)
|
| 563 |
+
if t is NotImplemented:
|
| 564 |
+
return t
|
| 565 |
+
return t / s
|
| 566 |
+
|
| 567 |
+
def __rpow__(s, t):
|
| 568 |
+
t = s.mpc_convert_lhs(t)
|
| 569 |
+
if t is NotImplemented:
|
| 570 |
+
return t
|
| 571 |
+
return t ** s
|
| 572 |
+
|
| 573 |
+
__truediv__ = __div__
|
| 574 |
+
__rtruediv__ = __rdiv__
|
| 575 |
+
|
| 576 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 577 |
+
return s.context.almosteq(s, t, rel_eps, abs_eps)
|
| 578 |
+
|
| 579 |
+
|
| 580 |
+
complex_types = (complex, _mpc)
|
| 581 |
+
|
| 582 |
+
|
| 583 |
+
class PythonMPContext(object):
|
| 584 |
+
|
| 585 |
+
def __init__(ctx):
|
| 586 |
+
ctx._prec_rounding = [53, round_nearest]
|
| 587 |
+
ctx.mpf = type('mpf', (_mpf,), {})
|
| 588 |
+
ctx.mpc = type('mpc', (_mpc,), {})
|
| 589 |
+
ctx.mpf._ctxdata = [ctx.mpf, new, ctx._prec_rounding]
|
| 590 |
+
ctx.mpc._ctxdata = [ctx.mpc, new, ctx._prec_rounding]
|
| 591 |
+
ctx.mpf.context = ctx
|
| 592 |
+
ctx.mpc.context = ctx
|
| 593 |
+
ctx.constant = type('constant', (_constant,), {})
|
| 594 |
+
ctx.constant._ctxdata = [ctx.mpf, new, ctx._prec_rounding]
|
| 595 |
+
ctx.constant.context = ctx
|
| 596 |
+
|
| 597 |
+
def make_mpf(ctx, v):
|
| 598 |
+
a = new(ctx.mpf)
|
| 599 |
+
a._mpf_ = v
|
| 600 |
+
return a
|
| 601 |
+
|
| 602 |
+
def make_mpc(ctx, v):
|
| 603 |
+
a = new(ctx.mpc)
|
| 604 |
+
a._mpc_ = v
|
| 605 |
+
return a
|
| 606 |
+
|
| 607 |
+
def default(ctx):
|
| 608 |
+
ctx._prec = ctx._prec_rounding[0] = 53
|
| 609 |
+
ctx._dps = 15
|
| 610 |
+
ctx.trap_complex = False
|
| 611 |
+
|
| 612 |
+
def _set_prec(ctx, n):
|
| 613 |
+
ctx._prec = ctx._prec_rounding[0] = max(1, int(n))
|
| 614 |
+
ctx._dps = prec_to_dps(n)
|
| 615 |
+
|
| 616 |
+
def _set_dps(ctx, n):
|
| 617 |
+
ctx._prec = ctx._prec_rounding[0] = dps_to_prec(n)
|
| 618 |
+
ctx._dps = max(1, int(n))
|
| 619 |
+
|
| 620 |
+
prec = property(lambda ctx: ctx._prec, _set_prec)
|
| 621 |
+
dps = property(lambda ctx: ctx._dps, _set_dps)
|
| 622 |
+
|
| 623 |
+
def convert(ctx, x, strings=True):
|
| 624 |
+
"""
|
| 625 |
+
Converts *x* to an ``mpf`` or ``mpc``. If *x* is of type ``mpf``,
|
| 626 |
+
``mpc``, ``int``, ``float``, ``complex``, the conversion
|
| 627 |
+
will be performed losslessly.
|
| 628 |
+
|
| 629 |
+
If *x* is a string, the result will be rounded to the present
|
| 630 |
+
working precision. Strings representing fractions or complex
|
| 631 |
+
numbers are permitted.
|
| 632 |
+
|
| 633 |
+
>>> from mpmath import *
|
| 634 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 635 |
+
>>> mpmathify(3.5)
|
| 636 |
+
mpf('3.5')
|
| 637 |
+
>>> mpmathify('2.1')
|
| 638 |
+
mpf('2.1000000000000001')
|
| 639 |
+
>>> mpmathify('3/4')
|
| 640 |
+
mpf('0.75')
|
| 641 |
+
>>> mpmathify('2+3j')
|
| 642 |
+
mpc(real='2.0', imag='3.0')
|
| 643 |
+
|
| 644 |
+
"""
|
| 645 |
+
if type(x) in ctx.types: return x
|
| 646 |
+
if isinstance(x, int_types): return ctx.make_mpf(from_int(x))
|
| 647 |
+
if isinstance(x, float): return ctx.make_mpf(from_float(x))
|
| 648 |
+
if isinstance(x, complex):
|
| 649 |
+
return ctx.make_mpc((from_float(x.real), from_float(x.imag)))
|
| 650 |
+
if type(x).__module__ == 'numpy': return ctx.npconvert(x)
|
| 651 |
+
if isinstance(x, numbers.Rational): # e.g. Fraction
|
| 652 |
+
try: x = rational.mpq(int(x.numerator), int(x.denominator))
|
| 653 |
+
except: pass
|
| 654 |
+
prec, rounding = ctx._prec_rounding
|
| 655 |
+
if isinstance(x, rational.mpq):
|
| 656 |
+
p, q = x._mpq_
|
| 657 |
+
return ctx.make_mpf(from_rational(p, q, prec))
|
| 658 |
+
if strings and isinstance(x, basestring):
|
| 659 |
+
try:
|
| 660 |
+
_mpf_ = from_str(x, prec, rounding)
|
| 661 |
+
return ctx.make_mpf(_mpf_)
|
| 662 |
+
except ValueError:
|
| 663 |
+
pass
|
| 664 |
+
if hasattr(x, '_mpf_'): return ctx.make_mpf(x._mpf_)
|
| 665 |
+
if hasattr(x, '_mpc_'): return ctx.make_mpc(x._mpc_)
|
| 666 |
+
if hasattr(x, '_mpmath_'):
|
| 667 |
+
return ctx.convert(x._mpmath_(prec, rounding))
|
| 668 |
+
if type(x).__module__ == 'decimal':
|
| 669 |
+
try: return ctx.make_mpf(from_Decimal(x, prec, rounding))
|
| 670 |
+
except: pass
|
| 671 |
+
return ctx._convert_fallback(x, strings)
|
| 672 |
+
|
| 673 |
+
def npconvert(ctx, x):
|
| 674 |
+
"""
|
| 675 |
+
Converts *x* to an ``mpf`` or ``mpc``. *x* should be a numpy
|
| 676 |
+
scalar.
|
| 677 |
+
"""
|
| 678 |
+
import numpy as np
|
| 679 |
+
if isinstance(x, np.integer): return ctx.make_mpf(from_int(int(x)))
|
| 680 |
+
if isinstance(x, np.floating): return ctx.make_mpf(from_npfloat(x))
|
| 681 |
+
if isinstance(x, np.complexfloating):
|
| 682 |
+
return ctx.make_mpc((from_npfloat(x.real), from_npfloat(x.imag)))
|
| 683 |
+
raise TypeError("cannot create mpf from " + repr(x))
|
| 684 |
+
|
| 685 |
+
def isnan(ctx, x):
|
| 686 |
+
"""
|
| 687 |
+
Return *True* if *x* is a NaN (not-a-number), or for a complex
|
| 688 |
+
number, whether either the real or complex part is NaN;
|
| 689 |
+
otherwise return *False*::
|
| 690 |
+
|
| 691 |
+
>>> from mpmath import *
|
| 692 |
+
>>> isnan(3.14)
|
| 693 |
+
False
|
| 694 |
+
>>> isnan(nan)
|
| 695 |
+
True
|
| 696 |
+
>>> isnan(mpc(3.14,2.72))
|
| 697 |
+
False
|
| 698 |
+
>>> isnan(mpc(3.14,nan))
|
| 699 |
+
True
|
| 700 |
+
|
| 701 |
+
"""
|
| 702 |
+
if hasattr(x, "_mpf_"):
|
| 703 |
+
return x._mpf_ == fnan
|
| 704 |
+
if hasattr(x, "_mpc_"):
|
| 705 |
+
return fnan in x._mpc_
|
| 706 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 707 |
+
return False
|
| 708 |
+
x = ctx.convert(x)
|
| 709 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 710 |
+
return ctx.isnan(x)
|
| 711 |
+
raise TypeError("isnan() needs a number as input")
|
| 712 |
+
|
| 713 |
+
def isinf(ctx, x):
|
| 714 |
+
"""
|
| 715 |
+
Return *True* if the absolute value of *x* is infinite;
|
| 716 |
+
otherwise return *False*::
|
| 717 |
+
|
| 718 |
+
>>> from mpmath import *
|
| 719 |
+
>>> isinf(inf)
|
| 720 |
+
True
|
| 721 |
+
>>> isinf(-inf)
|
| 722 |
+
True
|
| 723 |
+
>>> isinf(3)
|
| 724 |
+
False
|
| 725 |
+
>>> isinf(3+4j)
|
| 726 |
+
False
|
| 727 |
+
>>> isinf(mpc(3,inf))
|
| 728 |
+
True
|
| 729 |
+
>>> isinf(mpc(inf,3))
|
| 730 |
+
True
|
| 731 |
+
|
| 732 |
+
"""
|
| 733 |
+
if hasattr(x, "_mpf_"):
|
| 734 |
+
return x._mpf_ in (finf, fninf)
|
| 735 |
+
if hasattr(x, "_mpc_"):
|
| 736 |
+
re, im = x._mpc_
|
| 737 |
+
return re in (finf, fninf) or im in (finf, fninf)
|
| 738 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 739 |
+
return False
|
| 740 |
+
x = ctx.convert(x)
|
| 741 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 742 |
+
return ctx.isinf(x)
|
| 743 |
+
raise TypeError("isinf() needs a number as input")
|
| 744 |
+
|
| 745 |
+
def isnormal(ctx, x):
|
| 746 |
+
"""
|
| 747 |
+
Determine whether *x* is "normal" in the sense of floating-point
|
| 748 |
+
representation; that is, return *False* if *x* is zero, an
|
| 749 |
+
infinity or NaN; otherwise return *True*. By extension, a
|
| 750 |
+
complex number *x* is considered "normal" if its magnitude is
|
| 751 |
+
normal::
|
| 752 |
+
|
| 753 |
+
>>> from mpmath import *
|
| 754 |
+
>>> isnormal(3)
|
| 755 |
+
True
|
| 756 |
+
>>> isnormal(0)
|
| 757 |
+
False
|
| 758 |
+
>>> isnormal(inf); isnormal(-inf); isnormal(nan)
|
| 759 |
+
False
|
| 760 |
+
False
|
| 761 |
+
False
|
| 762 |
+
>>> isnormal(0+0j)
|
| 763 |
+
False
|
| 764 |
+
>>> isnormal(0+3j)
|
| 765 |
+
True
|
| 766 |
+
>>> isnormal(mpc(2,nan))
|
| 767 |
+
False
|
| 768 |
+
"""
|
| 769 |
+
if hasattr(x, "_mpf_"):
|
| 770 |
+
return bool(x._mpf_[1])
|
| 771 |
+
if hasattr(x, "_mpc_"):
|
| 772 |
+
re, im = x._mpc_
|
| 773 |
+
re_normal = bool(re[1])
|
| 774 |
+
im_normal = bool(im[1])
|
| 775 |
+
if re == fzero: return im_normal
|
| 776 |
+
if im == fzero: return re_normal
|
| 777 |
+
return re_normal and im_normal
|
| 778 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 779 |
+
return bool(x)
|
| 780 |
+
x = ctx.convert(x)
|
| 781 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 782 |
+
return ctx.isnormal(x)
|
| 783 |
+
raise TypeError("isnormal() needs a number as input")
|
| 784 |
+
|
| 785 |
+
def isint(ctx, x, gaussian=False):
|
| 786 |
+
"""
|
| 787 |
+
Return *True* if *x* is integer-valued; otherwise return
|
| 788 |
+
*False*::
|
| 789 |
+
|
| 790 |
+
>>> from mpmath import *
|
| 791 |
+
>>> isint(3)
|
| 792 |
+
True
|
| 793 |
+
>>> isint(mpf(3))
|
| 794 |
+
True
|
| 795 |
+
>>> isint(3.2)
|
| 796 |
+
False
|
| 797 |
+
>>> isint(inf)
|
| 798 |
+
False
|
| 799 |
+
|
| 800 |
+
Optionally, Gaussian integers can be checked for::
|
| 801 |
+
|
| 802 |
+
>>> isint(3+0j)
|
| 803 |
+
True
|
| 804 |
+
>>> isint(3+2j)
|
| 805 |
+
False
|
| 806 |
+
>>> isint(3+2j, gaussian=True)
|
| 807 |
+
True
|
| 808 |
+
|
| 809 |
+
"""
|
| 810 |
+
if isinstance(x, int_types):
|
| 811 |
+
return True
|
| 812 |
+
if hasattr(x, "_mpf_"):
|
| 813 |
+
sign, man, exp, bc = xval = x._mpf_
|
| 814 |
+
return bool((man and exp >= 0) or xval == fzero)
|
| 815 |
+
if hasattr(x, "_mpc_"):
|
| 816 |
+
re, im = x._mpc_
|
| 817 |
+
rsign, rman, rexp, rbc = re
|
| 818 |
+
isign, iman, iexp, ibc = im
|
| 819 |
+
re_isint = (rman and rexp >= 0) or re == fzero
|
| 820 |
+
if gaussian:
|
| 821 |
+
im_isint = (iman and iexp >= 0) or im == fzero
|
| 822 |
+
return re_isint and im_isint
|
| 823 |
+
return re_isint and im == fzero
|
| 824 |
+
if isinstance(x, rational.mpq):
|
| 825 |
+
p, q = x._mpq_
|
| 826 |
+
return p % q == 0
|
| 827 |
+
x = ctx.convert(x)
|
| 828 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 829 |
+
return ctx.isint(x, gaussian)
|
| 830 |
+
raise TypeError("isint() needs a number as input")
|
| 831 |
+
|
| 832 |
+
def fsum(ctx, terms, absolute=False, squared=False):
|
| 833 |
+
"""
|
| 834 |
+
Calculates a sum containing a finite number of terms (for infinite
|
| 835 |
+
series, see :func:`~mpmath.nsum`). The terms will be converted to
|
| 836 |
+
mpmath numbers. For len(terms) > 2, this function is generally
|
| 837 |
+
faster and produces more accurate results than the builtin
|
| 838 |
+
Python function :func:`sum`.
|
| 839 |
+
|
| 840 |
+
>>> from mpmath import *
|
| 841 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 842 |
+
>>> fsum([1, 2, 0.5, 7])
|
| 843 |
+
mpf('10.5')
|
| 844 |
+
|
| 845 |
+
With squared=True each term is squared, and with absolute=True
|
| 846 |
+
the absolute value of each term is used.
|
| 847 |
+
"""
|
| 848 |
+
prec, rnd = ctx._prec_rounding
|
| 849 |
+
real = []
|
| 850 |
+
imag = []
|
| 851 |
+
for term in terms:
|
| 852 |
+
reval = imval = 0
|
| 853 |
+
if hasattr(term, "_mpf_"):
|
| 854 |
+
reval = term._mpf_
|
| 855 |
+
elif hasattr(term, "_mpc_"):
|
| 856 |
+
reval, imval = term._mpc_
|
| 857 |
+
else:
|
| 858 |
+
term = ctx.convert(term)
|
| 859 |
+
if hasattr(term, "_mpf_"):
|
| 860 |
+
reval = term._mpf_
|
| 861 |
+
elif hasattr(term, "_mpc_"):
|
| 862 |
+
reval, imval = term._mpc_
|
| 863 |
+
else:
|
| 864 |
+
raise NotImplementedError
|
| 865 |
+
if imval:
|
| 866 |
+
if squared:
|
| 867 |
+
if absolute:
|
| 868 |
+
real.append(mpf_mul(reval,reval))
|
| 869 |
+
real.append(mpf_mul(imval,imval))
|
| 870 |
+
else:
|
| 871 |
+
reval, imval = mpc_pow_int((reval,imval),2,prec+10)
|
| 872 |
+
real.append(reval)
|
| 873 |
+
imag.append(imval)
|
| 874 |
+
elif absolute:
|
| 875 |
+
real.append(mpc_abs((reval,imval), prec))
|
| 876 |
+
else:
|
| 877 |
+
real.append(reval)
|
| 878 |
+
imag.append(imval)
|
| 879 |
+
else:
|
| 880 |
+
if squared:
|
| 881 |
+
reval = mpf_mul(reval, reval)
|
| 882 |
+
elif absolute:
|
| 883 |
+
reval = mpf_abs(reval)
|
| 884 |
+
real.append(reval)
|
| 885 |
+
s = mpf_sum(real, prec, rnd, absolute)
|
| 886 |
+
if imag:
|
| 887 |
+
s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd)))
|
| 888 |
+
else:
|
| 889 |
+
s = ctx.make_mpf(s)
|
| 890 |
+
return s
|
| 891 |
+
|
| 892 |
+
def fdot(ctx, A, B=None, conjugate=False):
|
| 893 |
+
r"""
|
| 894 |
+
Computes the dot product of the iterables `A` and `B`,
|
| 895 |
+
|
| 896 |
+
.. math ::
|
| 897 |
+
|
| 898 |
+
\sum_{k=0} A_k B_k.
|
| 899 |
+
|
| 900 |
+
Alternatively, :func:`~mpmath.fdot` accepts a single iterable of pairs.
|
| 901 |
+
In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent.
|
| 902 |
+
The elements are automatically converted to mpmath numbers.
|
| 903 |
+
|
| 904 |
+
With ``conjugate=True``, the elements in the second vector
|
| 905 |
+
will be conjugated:
|
| 906 |
+
|
| 907 |
+
.. math ::
|
| 908 |
+
|
| 909 |
+
\sum_{k=0} A_k \overline{B_k}
|
| 910 |
+
|
| 911 |
+
**Examples**
|
| 912 |
+
|
| 913 |
+
>>> from mpmath import *
|
| 914 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 915 |
+
>>> A = [2, 1.5, 3]
|
| 916 |
+
>>> B = [1, -1, 2]
|
| 917 |
+
>>> fdot(A, B)
|
| 918 |
+
mpf('6.5')
|
| 919 |
+
>>> list(zip(A, B))
|
| 920 |
+
[(2, 1), (1.5, -1), (3, 2)]
|
| 921 |
+
>>> fdot(_)
|
| 922 |
+
mpf('6.5')
|
| 923 |
+
>>> A = [2, 1.5, 3j]
|
| 924 |
+
>>> B = [1+j, 3, -1-j]
|
| 925 |
+
>>> fdot(A, B)
|
| 926 |
+
mpc(real='9.5', imag='-1.0')
|
| 927 |
+
>>> fdot(A, B, conjugate=True)
|
| 928 |
+
mpc(real='3.5', imag='-5.0')
|
| 929 |
+
|
| 930 |
+
"""
|
| 931 |
+
if B is not None:
|
| 932 |
+
A = zip(A, B)
|
| 933 |
+
prec, rnd = ctx._prec_rounding
|
| 934 |
+
real = []
|
| 935 |
+
imag = []
|
| 936 |
+
hasattr_ = hasattr
|
| 937 |
+
types = (ctx.mpf, ctx.mpc)
|
| 938 |
+
for a, b in A:
|
| 939 |
+
if type(a) not in types: a = ctx.convert(a)
|
| 940 |
+
if type(b) not in types: b = ctx.convert(b)
|
| 941 |
+
a_real = hasattr_(a, "_mpf_")
|
| 942 |
+
b_real = hasattr_(b, "_mpf_")
|
| 943 |
+
if a_real and b_real:
|
| 944 |
+
real.append(mpf_mul(a._mpf_, b._mpf_))
|
| 945 |
+
continue
|
| 946 |
+
a_complex = hasattr_(a, "_mpc_")
|
| 947 |
+
b_complex = hasattr_(b, "_mpc_")
|
| 948 |
+
if a_real and b_complex:
|
| 949 |
+
aval = a._mpf_
|
| 950 |
+
bre, bim = b._mpc_
|
| 951 |
+
if conjugate:
|
| 952 |
+
bim = mpf_neg(bim)
|
| 953 |
+
real.append(mpf_mul(aval, bre))
|
| 954 |
+
imag.append(mpf_mul(aval, bim))
|
| 955 |
+
elif b_real and a_complex:
|
| 956 |
+
are, aim = a._mpc_
|
| 957 |
+
bval = b._mpf_
|
| 958 |
+
real.append(mpf_mul(are, bval))
|
| 959 |
+
imag.append(mpf_mul(aim, bval))
|
| 960 |
+
elif a_complex and b_complex:
|
| 961 |
+
#re, im = mpc_mul(a._mpc_, b._mpc_, prec+20)
|
| 962 |
+
are, aim = a._mpc_
|
| 963 |
+
bre, bim = b._mpc_
|
| 964 |
+
if conjugate:
|
| 965 |
+
bim = mpf_neg(bim)
|
| 966 |
+
real.append(mpf_mul(are, bre))
|
| 967 |
+
real.append(mpf_neg(mpf_mul(aim, bim)))
|
| 968 |
+
imag.append(mpf_mul(are, bim))
|
| 969 |
+
imag.append(mpf_mul(aim, bre))
|
| 970 |
+
else:
|
| 971 |
+
raise NotImplementedError
|
| 972 |
+
s = mpf_sum(real, prec, rnd)
|
| 973 |
+
if imag:
|
| 974 |
+
s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd)))
|
| 975 |
+
else:
|
| 976 |
+
s = ctx.make_mpf(s)
|
| 977 |
+
return s
|
| 978 |
+
|
| 979 |
+
def _wrap_libmp_function(ctx, mpf_f, mpc_f=None, mpi_f=None, doc="<no doc>"):
|
| 980 |
+
"""
|
| 981 |
+
Given a low-level mpf_ function, and optionally similar functions
|
| 982 |
+
for mpc_ and mpi_, defines the function as a context method.
|
| 983 |
+
|
| 984 |
+
It is assumed that the return type is the same as that of
|
| 985 |
+
the input; the exception is that propagation from mpf to mpc is possible
|
| 986 |
+
by raising ComplexResult.
|
| 987 |
+
|
| 988 |
+
"""
|
| 989 |
+
def f(x, **kwargs):
|
| 990 |
+
if type(x) not in ctx.types:
|
| 991 |
+
x = ctx.convert(x)
|
| 992 |
+
prec, rounding = ctx._prec_rounding
|
| 993 |
+
if kwargs:
|
| 994 |
+
prec = kwargs.get('prec', prec)
|
| 995 |
+
if 'dps' in kwargs:
|
| 996 |
+
prec = dps_to_prec(kwargs['dps'])
|
| 997 |
+
rounding = kwargs.get('rounding', rounding)
|
| 998 |
+
if hasattr(x, '_mpf_'):
|
| 999 |
+
try:
|
| 1000 |
+
return ctx.make_mpf(mpf_f(x._mpf_, prec, rounding))
|
| 1001 |
+
except ComplexResult:
|
| 1002 |
+
# Handle propagation to complex
|
| 1003 |
+
if ctx.trap_complex:
|
| 1004 |
+
raise
|
| 1005 |
+
return ctx.make_mpc(mpc_f((x._mpf_, fzero), prec, rounding))
|
| 1006 |
+
elif hasattr(x, '_mpc_'):
|
| 1007 |
+
return ctx.make_mpc(mpc_f(x._mpc_, prec, rounding))
|
| 1008 |
+
raise NotImplementedError("%s of a %s" % (name, type(x)))
|
| 1009 |
+
name = mpf_f.__name__[4:]
|
| 1010 |
+
f.__doc__ = function_docs.__dict__.get(name, "Computes the %s of x" % doc)
|
| 1011 |
+
return f
|
| 1012 |
+
|
| 1013 |
+
# Called by SpecialFunctions.__init__()
|
| 1014 |
+
@classmethod
|
| 1015 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 1016 |
+
if wrap:
|
| 1017 |
+
def f_wrapped(ctx, *args, **kwargs):
|
| 1018 |
+
convert = ctx.convert
|
| 1019 |
+
args = [convert(a) for a in args]
|
| 1020 |
+
prec = ctx.prec
|
| 1021 |
+
try:
|
| 1022 |
+
ctx.prec += 10
|
| 1023 |
+
retval = f(ctx, *args, **kwargs)
|
| 1024 |
+
finally:
|
| 1025 |
+
ctx.prec = prec
|
| 1026 |
+
return +retval
|
| 1027 |
+
else:
|
| 1028 |
+
f_wrapped = f
|
| 1029 |
+
f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__)
|
| 1030 |
+
setattr(cls, name, f_wrapped)
|
| 1031 |
+
|
| 1032 |
+
def _convert_param(ctx, x):
|
| 1033 |
+
if hasattr(x, "_mpc_"):
|
| 1034 |
+
v, im = x._mpc_
|
| 1035 |
+
if im != fzero:
|
| 1036 |
+
return x, 'C'
|
| 1037 |
+
elif hasattr(x, "_mpf_"):
|
| 1038 |
+
v = x._mpf_
|
| 1039 |
+
else:
|
| 1040 |
+
if type(x) in int_types:
|
| 1041 |
+
return int(x), 'Z'
|
| 1042 |
+
p = None
|
| 1043 |
+
if isinstance(x, tuple):
|
| 1044 |
+
p, q = x
|
| 1045 |
+
elif hasattr(x, '_mpq_'):
|
| 1046 |
+
p, q = x._mpq_
|
| 1047 |
+
elif isinstance(x, basestring) and '/' in x:
|
| 1048 |
+
p, q = x.split('/')
|
| 1049 |
+
p = int(p)
|
| 1050 |
+
q = int(q)
|
| 1051 |
+
if p is not None:
|
| 1052 |
+
if not p % q:
|
| 1053 |
+
return p // q, 'Z'
|
| 1054 |
+
return ctx.mpq(p,q), 'Q'
|
| 1055 |
+
x = ctx.convert(x)
|
| 1056 |
+
if hasattr(x, "_mpc_"):
|
| 1057 |
+
v, im = x._mpc_
|
| 1058 |
+
if im != fzero:
|
| 1059 |
+
return x, 'C'
|
| 1060 |
+
elif hasattr(x, "_mpf_"):
|
| 1061 |
+
v = x._mpf_
|
| 1062 |
+
else:
|
| 1063 |
+
return x, 'U'
|
| 1064 |
+
sign, man, exp, bc = v
|
| 1065 |
+
if man:
|
| 1066 |
+
if exp >= -4:
|
| 1067 |
+
if sign:
|
| 1068 |
+
man = -man
|
| 1069 |
+
if exp >= 0:
|
| 1070 |
+
return int(man) << exp, 'Z'
|
| 1071 |
+
if exp >= -4:
|
| 1072 |
+
p, q = int(man), (1<<(-exp))
|
| 1073 |
+
return ctx.mpq(p,q), 'Q'
|
| 1074 |
+
x = ctx.make_mpf(v)
|
| 1075 |
+
return x, 'R'
|
| 1076 |
+
elif not exp:
|
| 1077 |
+
return 0, 'Z'
|
| 1078 |
+
else:
|
| 1079 |
+
return x, 'U'
|
| 1080 |
+
|
| 1081 |
+
def _mpf_mag(ctx, x):
|
| 1082 |
+
sign, man, exp, bc = x
|
| 1083 |
+
if man:
|
| 1084 |
+
return exp+bc
|
| 1085 |
+
if x == fzero:
|
| 1086 |
+
return ctx.ninf
|
| 1087 |
+
if x == finf or x == fninf:
|
| 1088 |
+
return ctx.inf
|
| 1089 |
+
return ctx.nan
|
| 1090 |
+
|
| 1091 |
+
def mag(ctx, x):
|
| 1092 |
+
"""
|
| 1093 |
+
Quick logarithmic magnitude estimate of a number. Returns an
|
| 1094 |
+
integer or infinity `m` such that `|x| <= 2^m`. It is not
|
| 1095 |
+
guaranteed that `m` is an optimal bound, but it will never
|
| 1096 |
+
be too large by more than 2 (and probably not more than 1).
|
| 1097 |
+
|
| 1098 |
+
**Examples**
|
| 1099 |
+
|
| 1100 |
+
>>> from mpmath import *
|
| 1101 |
+
>>> mp.pretty = True
|
| 1102 |
+
>>> mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2)))
|
| 1103 |
+
(4, 4, 4, 4)
|
| 1104 |
+
>>> mag(10j), mag(10+10j)
|
| 1105 |
+
(4, 5)
|
| 1106 |
+
>>> mag(0.01), int(ceil(log(0.01,2)))
|
| 1107 |
+
(-6, -6)
|
| 1108 |
+
>>> mag(0), mag(inf), mag(-inf), mag(nan)
|
| 1109 |
+
(-inf, +inf, +inf, nan)
|
| 1110 |
+
|
| 1111 |
+
"""
|
| 1112 |
+
if hasattr(x, "_mpf_"):
|
| 1113 |
+
return ctx._mpf_mag(x._mpf_)
|
| 1114 |
+
elif hasattr(x, "_mpc_"):
|
| 1115 |
+
r, i = x._mpc_
|
| 1116 |
+
if r == fzero:
|
| 1117 |
+
return ctx._mpf_mag(i)
|
| 1118 |
+
if i == fzero:
|
| 1119 |
+
return ctx._mpf_mag(r)
|
| 1120 |
+
return 1+max(ctx._mpf_mag(r), ctx._mpf_mag(i))
|
| 1121 |
+
elif isinstance(x, int_types):
|
| 1122 |
+
if x:
|
| 1123 |
+
return bitcount(abs(x))
|
| 1124 |
+
return ctx.ninf
|
| 1125 |
+
elif isinstance(x, rational.mpq):
|
| 1126 |
+
p, q = x._mpq_
|
| 1127 |
+
if p:
|
| 1128 |
+
return 1 + bitcount(abs(p)) - bitcount(q)
|
| 1129 |
+
return ctx.ninf
|
| 1130 |
+
else:
|
| 1131 |
+
x = ctx.convert(x)
|
| 1132 |
+
if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"):
|
| 1133 |
+
return ctx.mag(x)
|
| 1134 |
+
else:
|
| 1135 |
+
raise TypeError("requires an mpf/mpc")
|
| 1136 |
+
|
| 1137 |
+
|
| 1138 |
+
# Register with "numbers" ABC
|
| 1139 |
+
# We do not subclass, hence we do not use the @abstractmethod checks. While
|
| 1140 |
+
# this is less invasive it may turn out that we do not actually support
|
| 1141 |
+
# parts of the expected interfaces. See
|
| 1142 |
+
# http://docs.python.org/2/library/numbers.html for list of abstract
|
| 1143 |
+
# methods.
|
| 1144 |
+
try:
|
| 1145 |
+
import numbers
|
| 1146 |
+
numbers.Complex.register(_mpc)
|
| 1147 |
+
numbers.Real.register(_mpf)
|
| 1148 |
+
except ImportError:
|
| 1149 |
+
pass
|
.venv/lib/python3.11/site-packages/mpmath/function_docs.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
.venv/lib/python3.11/site-packages/mpmath/functions/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from . import functions
|
| 2 |
+
# Hack to update methods
|
| 3 |
+
from . import factorials
|
| 4 |
+
from . import hypergeometric
|
| 5 |
+
from . import expintegrals
|
| 6 |
+
from . import bessel
|
| 7 |
+
from . import orthogonal
|
| 8 |
+
from . import theta
|
| 9 |
+
from . import elliptic
|
| 10 |
+
from . import signals
|
| 11 |
+
from . import zeta
|
| 12 |
+
from . import rszeta
|
| 13 |
+
from . import zetazeros
|
| 14 |
+
from . import qfunctions
|
.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/orthogonal.cpython-311.pyc
ADDED
|
Binary file (25.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/qfunctions.cpython-311.pyc
ADDED
|
Binary file (10.2 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/signals.cpython-311.pyc
ADDED
|
Binary file (1.83 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/theta.cpython-311.pyc
ADDED
|
Binary file (53.5 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/functions/bessel.py
ADDED
|
@@ -0,0 +1,1108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .functions import defun, defun_wrapped
|
| 2 |
+
|
| 3 |
+
@defun
|
| 4 |
+
def j0(ctx, x):
|
| 5 |
+
"""Computes the Bessel function `J_0(x)`. See :func:`~mpmath.besselj`."""
|
| 6 |
+
return ctx.besselj(0, x)
|
| 7 |
+
|
| 8 |
+
@defun
|
| 9 |
+
def j1(ctx, x):
|
| 10 |
+
"""Computes the Bessel function `J_1(x)`. See :func:`~mpmath.besselj`."""
|
| 11 |
+
return ctx.besselj(1, x)
|
| 12 |
+
|
| 13 |
+
@defun
|
| 14 |
+
def besselj(ctx, n, z, derivative=0, **kwargs):
|
| 15 |
+
if type(n) is int:
|
| 16 |
+
n_isint = True
|
| 17 |
+
else:
|
| 18 |
+
n = ctx.convert(n)
|
| 19 |
+
n_isint = ctx.isint(n)
|
| 20 |
+
if n_isint:
|
| 21 |
+
n = int(ctx._re(n))
|
| 22 |
+
if n_isint and n < 0:
|
| 23 |
+
return (-1)**n * ctx.besselj(-n, z, derivative, **kwargs)
|
| 24 |
+
z = ctx.convert(z)
|
| 25 |
+
M = ctx.mag(z)
|
| 26 |
+
if derivative:
|
| 27 |
+
d = ctx.convert(derivative)
|
| 28 |
+
# TODO: the integer special-casing shouldn't be necessary.
|
| 29 |
+
# However, the hypergeometric series gets inaccurate for large d
|
| 30 |
+
# because of inaccurate pole cancellation at a pole far from
|
| 31 |
+
# zero (needs to be fixed in hypercomb or hypsum)
|
| 32 |
+
if ctx.isint(d) and d >= 0:
|
| 33 |
+
d = int(d)
|
| 34 |
+
orig = ctx.prec
|
| 35 |
+
try:
|
| 36 |
+
ctx.prec += 15
|
| 37 |
+
v = ctx.fsum((-1)**k * ctx.binomial(d,k) * ctx.besselj(2*k+n-d,z)
|
| 38 |
+
for k in range(d+1))
|
| 39 |
+
finally:
|
| 40 |
+
ctx.prec = orig
|
| 41 |
+
v *= ctx.mpf(2)**(-d)
|
| 42 |
+
else:
|
| 43 |
+
def h(n,d):
|
| 44 |
+
r = ctx.fmul(ctx.fmul(z, z, prec=ctx.prec+M), -0.25, exact=True)
|
| 45 |
+
B = [0.5*(n-d+1), 0.5*(n-d+2)]
|
| 46 |
+
T = [([2,ctx.pi,z],[d-2*n,0.5,n-d],[],B,[(n+1)*0.5,(n+2)*0.5],B+[n+1],r)]
|
| 47 |
+
return T
|
| 48 |
+
v = ctx.hypercomb(h, [n,d], **kwargs)
|
| 49 |
+
else:
|
| 50 |
+
# Fast case: J_n(x), n int, appropriate magnitude for fixed-point calculation
|
| 51 |
+
if (not derivative) and n_isint and abs(M) < 10 and abs(n) < 20:
|
| 52 |
+
try:
|
| 53 |
+
return ctx._besselj(n, z)
|
| 54 |
+
except NotImplementedError:
|
| 55 |
+
pass
|
| 56 |
+
if not z:
|
| 57 |
+
if not n:
|
| 58 |
+
v = ctx.one + n+z
|
| 59 |
+
elif ctx.re(n) > 0:
|
| 60 |
+
v = n*z
|
| 61 |
+
else:
|
| 62 |
+
v = ctx.inf + z + n
|
| 63 |
+
else:
|
| 64 |
+
#v = 0
|
| 65 |
+
orig = ctx.prec
|
| 66 |
+
try:
|
| 67 |
+
# XXX: workaround for accuracy in low level hypergeometric series
|
| 68 |
+
# when alternating, large arguments
|
| 69 |
+
ctx.prec += min(3*abs(M), ctx.prec)
|
| 70 |
+
w = ctx.fmul(z, 0.5, exact=True)
|
| 71 |
+
def h(n):
|
| 72 |
+
r = ctx.fneg(ctx.fmul(w, w, prec=max(0,ctx.prec+M)), exact=True)
|
| 73 |
+
return [([w], [n], [], [n+1], [], [n+1], r)]
|
| 74 |
+
v = ctx.hypercomb(h, [n], **kwargs)
|
| 75 |
+
finally:
|
| 76 |
+
ctx.prec = orig
|
| 77 |
+
v = +v
|
| 78 |
+
return v
|
| 79 |
+
|
| 80 |
+
@defun
|
| 81 |
+
def besseli(ctx, n, z, derivative=0, **kwargs):
|
| 82 |
+
n = ctx.convert(n)
|
| 83 |
+
z = ctx.convert(z)
|
| 84 |
+
if not z:
|
| 85 |
+
if derivative:
|
| 86 |
+
raise ValueError
|
| 87 |
+
if not n:
|
| 88 |
+
# I(0,0) = 1
|
| 89 |
+
return 1+n+z
|
| 90 |
+
if ctx.isint(n):
|
| 91 |
+
return 0*(n+z)
|
| 92 |
+
r = ctx.re(n)
|
| 93 |
+
if r == 0:
|
| 94 |
+
return ctx.nan*(n+z)
|
| 95 |
+
elif r > 0:
|
| 96 |
+
return 0*(n+z)
|
| 97 |
+
else:
|
| 98 |
+
return ctx.inf+(n+z)
|
| 99 |
+
M = ctx.mag(z)
|
| 100 |
+
if derivative:
|
| 101 |
+
d = ctx.convert(derivative)
|
| 102 |
+
def h(n,d):
|
| 103 |
+
r = ctx.fmul(ctx.fmul(z, z, prec=ctx.prec+M), 0.25, exact=True)
|
| 104 |
+
B = [0.5*(n-d+1), 0.5*(n-d+2), n+1]
|
| 105 |
+
T = [([2,ctx.pi,z],[d-2*n,0.5,n-d],[n+1],B,[(n+1)*0.5,(n+2)*0.5],B,r)]
|
| 106 |
+
return T
|
| 107 |
+
v = ctx.hypercomb(h, [n,d], **kwargs)
|
| 108 |
+
else:
|
| 109 |
+
def h(n):
|
| 110 |
+
w = ctx.fmul(z, 0.5, exact=True)
|
| 111 |
+
r = ctx.fmul(w, w, prec=max(0,ctx.prec+M))
|
| 112 |
+
return [([w], [n], [], [n+1], [], [n+1], r)]
|
| 113 |
+
v = ctx.hypercomb(h, [n], **kwargs)
|
| 114 |
+
return v
|
| 115 |
+
|
| 116 |
+
@defun_wrapped
|
| 117 |
+
def bessely(ctx, n, z, derivative=0, **kwargs):
|
| 118 |
+
if not z:
|
| 119 |
+
if derivative:
|
| 120 |
+
# Not implemented
|
| 121 |
+
raise ValueError
|
| 122 |
+
if not n:
|
| 123 |
+
# ~ log(z/2)
|
| 124 |
+
return -ctx.inf + (n+z)
|
| 125 |
+
if ctx.im(n):
|
| 126 |
+
return ctx.nan * (n+z)
|
| 127 |
+
r = ctx.re(n)
|
| 128 |
+
q = n+0.5
|
| 129 |
+
if ctx.isint(q):
|
| 130 |
+
if n > 0:
|
| 131 |
+
return -ctx.inf + (n+z)
|
| 132 |
+
else:
|
| 133 |
+
return 0 * (n+z)
|
| 134 |
+
if r < 0 and int(ctx.floor(q)) % 2:
|
| 135 |
+
return ctx.inf + (n+z)
|
| 136 |
+
else:
|
| 137 |
+
return ctx.ninf + (n+z)
|
| 138 |
+
# XXX: use hypercomb
|
| 139 |
+
ctx.prec += 10
|
| 140 |
+
m, d = ctx.nint_distance(n)
|
| 141 |
+
if d < -ctx.prec:
|
| 142 |
+
h = +ctx.eps
|
| 143 |
+
ctx.prec *= 2
|
| 144 |
+
n += h
|
| 145 |
+
elif d < 0:
|
| 146 |
+
ctx.prec -= d
|
| 147 |
+
# TODO: avoid cancellation for imaginary arguments
|
| 148 |
+
cos, sin = ctx.cospi_sinpi(n)
|
| 149 |
+
return (ctx.besselj(n,z,derivative,**kwargs)*cos - \
|
| 150 |
+
ctx.besselj(-n,z,derivative,**kwargs))/sin
|
| 151 |
+
|
| 152 |
+
@defun_wrapped
|
| 153 |
+
def besselk(ctx, n, z, **kwargs):
|
| 154 |
+
if not z:
|
| 155 |
+
return ctx.inf
|
| 156 |
+
M = ctx.mag(z)
|
| 157 |
+
if M < 1:
|
| 158 |
+
# Represent as limit definition
|
| 159 |
+
def h(n):
|
| 160 |
+
r = (z/2)**2
|
| 161 |
+
T1 = [z, 2], [-n, n-1], [n], [], [], [1-n], r
|
| 162 |
+
T2 = [z, 2], [n, -n-1], [-n], [], [], [1+n], r
|
| 163 |
+
return T1, T2
|
| 164 |
+
# We could use the limit definition always, but it leads
|
| 165 |
+
# to very bad cancellation (of exponentially large terms)
|
| 166 |
+
# for large real z
|
| 167 |
+
# Instead represent in terms of 2F0
|
| 168 |
+
else:
|
| 169 |
+
ctx.prec += M
|
| 170 |
+
def h(n):
|
| 171 |
+
return [([ctx.pi/2, z, ctx.exp(-z)], [0.5,-0.5,1], [], [], \
|
| 172 |
+
[n+0.5, 0.5-n], [], -1/(2*z))]
|
| 173 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 174 |
+
|
| 175 |
+
@defun_wrapped
|
| 176 |
+
def hankel1(ctx,n,x,**kwargs):
|
| 177 |
+
return ctx.besselj(n,x,**kwargs) + ctx.j*ctx.bessely(n,x,**kwargs)
|
| 178 |
+
|
| 179 |
+
@defun_wrapped
|
| 180 |
+
def hankel2(ctx,n,x,**kwargs):
|
| 181 |
+
return ctx.besselj(n,x,**kwargs) - ctx.j*ctx.bessely(n,x,**kwargs)
|
| 182 |
+
|
| 183 |
+
@defun_wrapped
|
| 184 |
+
def whitm(ctx,k,m,z,**kwargs):
|
| 185 |
+
if z == 0:
|
| 186 |
+
# M(k,m,z) = 0^(1/2+m)
|
| 187 |
+
if ctx.re(m) > -0.5:
|
| 188 |
+
return z
|
| 189 |
+
elif ctx.re(m) < -0.5:
|
| 190 |
+
return ctx.inf + z
|
| 191 |
+
else:
|
| 192 |
+
return ctx.nan * z
|
| 193 |
+
x = ctx.fmul(-0.5, z, exact=True)
|
| 194 |
+
y = 0.5+m
|
| 195 |
+
return ctx.exp(x) * z**y * ctx.hyp1f1(y-k, 1+2*m, z, **kwargs)
|
| 196 |
+
|
| 197 |
+
@defun_wrapped
|
| 198 |
+
def whitw(ctx,k,m,z,**kwargs):
|
| 199 |
+
if z == 0:
|
| 200 |
+
g = abs(ctx.re(m))
|
| 201 |
+
if g < 0.5:
|
| 202 |
+
return z
|
| 203 |
+
elif g > 0.5:
|
| 204 |
+
return ctx.inf + z
|
| 205 |
+
else:
|
| 206 |
+
return ctx.nan * z
|
| 207 |
+
x = ctx.fmul(-0.5, z, exact=True)
|
| 208 |
+
y = 0.5+m
|
| 209 |
+
return ctx.exp(x) * z**y * ctx.hyperu(y-k, 1+2*m, z, **kwargs)
|
| 210 |
+
|
| 211 |
+
@defun
|
| 212 |
+
def hyperu(ctx, a, b, z, **kwargs):
|
| 213 |
+
a, atype = ctx._convert_param(a)
|
| 214 |
+
b, btype = ctx._convert_param(b)
|
| 215 |
+
z = ctx.convert(z)
|
| 216 |
+
if not z:
|
| 217 |
+
if ctx.re(b) <= 1:
|
| 218 |
+
return ctx.gammaprod([1-b],[a-b+1])
|
| 219 |
+
else:
|
| 220 |
+
return ctx.inf + z
|
| 221 |
+
bb = 1+a-b
|
| 222 |
+
bb, bbtype = ctx._convert_param(bb)
|
| 223 |
+
try:
|
| 224 |
+
orig = ctx.prec
|
| 225 |
+
try:
|
| 226 |
+
ctx.prec += 10
|
| 227 |
+
v = ctx.hypsum(2, 0, (atype, bbtype), [a, bb], -1/z, maxterms=ctx.prec)
|
| 228 |
+
return v / z**a
|
| 229 |
+
finally:
|
| 230 |
+
ctx.prec = orig
|
| 231 |
+
except ctx.NoConvergence:
|
| 232 |
+
pass
|
| 233 |
+
def h(a,b):
|
| 234 |
+
w = ctx.sinpi(b)
|
| 235 |
+
T1 = ([ctx.pi,w],[1,-1],[],[a-b+1,b],[a],[b],z)
|
| 236 |
+
T2 = ([-ctx.pi,w,z],[1,-1,1-b],[],[a,2-b],[a-b+1],[2-b],z)
|
| 237 |
+
return T1, T2
|
| 238 |
+
return ctx.hypercomb(h, [a,b], **kwargs)
|
| 239 |
+
|
| 240 |
+
@defun
|
| 241 |
+
def struveh(ctx,n,z, **kwargs):
|
| 242 |
+
n = ctx.convert(n)
|
| 243 |
+
z = ctx.convert(z)
|
| 244 |
+
# http://functions.wolfram.com/Bessel-TypeFunctions/StruveH/26/01/02/
|
| 245 |
+
def h(n):
|
| 246 |
+
return [([z/2, 0.5*ctx.sqrt(ctx.pi)], [n+1, -1], [], [n+1.5], [1], [1.5, n+1.5], -(z/2)**2)]
|
| 247 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 248 |
+
|
| 249 |
+
@defun
|
| 250 |
+
def struvel(ctx,n,z, **kwargs):
|
| 251 |
+
n = ctx.convert(n)
|
| 252 |
+
z = ctx.convert(z)
|
| 253 |
+
# http://functions.wolfram.com/Bessel-TypeFunctions/StruveL/26/01/02/
|
| 254 |
+
def h(n):
|
| 255 |
+
return [([z/2, 0.5*ctx.sqrt(ctx.pi)], [n+1, -1], [], [n+1.5], [1], [1.5, n+1.5], (z/2)**2)]
|
| 256 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 257 |
+
|
| 258 |
+
def _anger(ctx,which,v,z,**kwargs):
|
| 259 |
+
v = ctx._convert_param(v)[0]
|
| 260 |
+
z = ctx.convert(z)
|
| 261 |
+
def h(v):
|
| 262 |
+
b = ctx.mpq_1_2
|
| 263 |
+
u = v*b
|
| 264 |
+
m = b*3
|
| 265 |
+
a1,a2,b1,b2 = m-u, m+u, 1-u, 1+u
|
| 266 |
+
c, s = ctx.cospi_sinpi(u)
|
| 267 |
+
if which == 0:
|
| 268 |
+
A, B = [b*z, s], [c]
|
| 269 |
+
if which == 1:
|
| 270 |
+
A, B = [b*z, -c], [s]
|
| 271 |
+
w = ctx.square_exp_arg(z, mult=-0.25)
|
| 272 |
+
T1 = A, [1, 1], [], [a1,a2], [1], [a1,a2], w
|
| 273 |
+
T2 = B, [1], [], [b1,b2], [1], [b1,b2], w
|
| 274 |
+
return T1, T2
|
| 275 |
+
return ctx.hypercomb(h, [v], **kwargs)
|
| 276 |
+
|
| 277 |
+
@defun
|
| 278 |
+
def angerj(ctx, v, z, **kwargs):
|
| 279 |
+
return _anger(ctx, 0, v, z, **kwargs)
|
| 280 |
+
|
| 281 |
+
@defun
|
| 282 |
+
def webere(ctx, v, z, **kwargs):
|
| 283 |
+
return _anger(ctx, 1, v, z, **kwargs)
|
| 284 |
+
|
| 285 |
+
@defun
|
| 286 |
+
def lommels1(ctx, u, v, z, **kwargs):
|
| 287 |
+
u = ctx._convert_param(u)[0]
|
| 288 |
+
v = ctx._convert_param(v)[0]
|
| 289 |
+
z = ctx.convert(z)
|
| 290 |
+
def h(u,v):
|
| 291 |
+
b = ctx.mpq_1_2
|
| 292 |
+
w = ctx.square_exp_arg(z, mult=-0.25)
|
| 293 |
+
return ([u-v+1, u+v+1, z], [-1, -1, u+1], [], [], [1], \
|
| 294 |
+
[b*(u-v+3),b*(u+v+3)], w),
|
| 295 |
+
return ctx.hypercomb(h, [u,v], **kwargs)
|
| 296 |
+
|
| 297 |
+
@defun
|
| 298 |
+
def lommels2(ctx, u, v, z, **kwargs):
|
| 299 |
+
u = ctx._convert_param(u)[0]
|
| 300 |
+
v = ctx._convert_param(v)[0]
|
| 301 |
+
z = ctx.convert(z)
|
| 302 |
+
# Asymptotic expansion (GR p. 947) -- need to be careful
|
| 303 |
+
# not to use for small arguments
|
| 304 |
+
# def h(u,v):
|
| 305 |
+
# b = ctx.mpq_1_2
|
| 306 |
+
# w = -(z/2)**(-2)
|
| 307 |
+
# return ([z], [u-1], [], [], [b*(1-u+v)], [b*(1-u-v)], w),
|
| 308 |
+
def h(u,v):
|
| 309 |
+
b = ctx.mpq_1_2
|
| 310 |
+
w = ctx.square_exp_arg(z, mult=-0.25)
|
| 311 |
+
T1 = [u-v+1, u+v+1, z], [-1, -1, u+1], [], [], [1], [b*(u-v+3),b*(u+v+3)], w
|
| 312 |
+
T2 = [2, z], [u+v-1, -v], [v, b*(u+v+1)], [b*(v-u+1)], [], [1-v], w
|
| 313 |
+
T3 = [2, z], [u-v-1, v], [-v, b*(u-v+1)], [b*(1-u-v)], [], [1+v], w
|
| 314 |
+
#c1 = ctx.cospi((u-v)*b)
|
| 315 |
+
#c2 = ctx.cospi((u+v)*b)
|
| 316 |
+
#s = ctx.sinpi(v)
|
| 317 |
+
#r1 = (u-v+1)*b
|
| 318 |
+
#r2 = (u+v+1)*b
|
| 319 |
+
#T2 = [c1, s, z, 2], [1, -1, -v, v], [], [-v+1], [], [-v+1], w
|
| 320 |
+
#T3 = [-c2, s, z, 2], [1, -1, v, -v], [], [v+1], [], [v+1], w
|
| 321 |
+
#T2 = [c1, s, z, 2], [1, -1, -v, v+u-1], [r1, r2], [-v+1], [], [-v+1], w
|
| 322 |
+
#T3 = [-c2, s, z, 2], [1, -1, v, -v+u-1], [r1, r2], [v+1], [], [v+1], w
|
| 323 |
+
return T1, T2, T3
|
| 324 |
+
return ctx.hypercomb(h, [u,v], **kwargs)
|
| 325 |
+
|
| 326 |
+
@defun
|
| 327 |
+
def ber(ctx, n, z, **kwargs):
|
| 328 |
+
n = ctx.convert(n)
|
| 329 |
+
z = ctx.convert(z)
|
| 330 |
+
# http://functions.wolfram.com/Bessel-TypeFunctions/KelvinBer2/26/01/02/0001/
|
| 331 |
+
def h(n):
|
| 332 |
+
r = -(z/4)**4
|
| 333 |
+
cos, sin = ctx.cospi_sinpi(-0.75*n)
|
| 334 |
+
T1 = [cos, z/2], [1, n], [], [n+1], [], [0.5, 0.5*(n+1), 0.5*n+1], r
|
| 335 |
+
T2 = [sin, z/2], [1, n+2], [], [n+2], [], [1.5, 0.5*(n+3), 0.5*n+1], r
|
| 336 |
+
return T1, T2
|
| 337 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 338 |
+
|
| 339 |
+
@defun
|
| 340 |
+
def bei(ctx, n, z, **kwargs):
|
| 341 |
+
n = ctx.convert(n)
|
| 342 |
+
z = ctx.convert(z)
|
| 343 |
+
# http://functions.wolfram.com/Bessel-TypeFunctions/KelvinBei2/26/01/02/0001/
|
| 344 |
+
def h(n):
|
| 345 |
+
r = -(z/4)**4
|
| 346 |
+
cos, sin = ctx.cospi_sinpi(0.75*n)
|
| 347 |
+
T1 = [cos, z/2], [1, n+2], [], [n+2], [], [1.5, 0.5*(n+3), 0.5*n+1], r
|
| 348 |
+
T2 = [sin, z/2], [1, n], [], [n+1], [], [0.5, 0.5*(n+1), 0.5*n+1], r
|
| 349 |
+
return T1, T2
|
| 350 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 351 |
+
|
| 352 |
+
@defun
|
| 353 |
+
def ker(ctx, n, z, **kwargs):
|
| 354 |
+
n = ctx.convert(n)
|
| 355 |
+
z = ctx.convert(z)
|
| 356 |
+
# http://functions.wolfram.com/Bessel-TypeFunctions/KelvinKer2/26/01/02/0001/
|
| 357 |
+
def h(n):
|
| 358 |
+
r = -(z/4)**4
|
| 359 |
+
cos1, sin1 = ctx.cospi_sinpi(0.25*n)
|
| 360 |
+
cos2, sin2 = ctx.cospi_sinpi(0.75*n)
|
| 361 |
+
T1 = [2, z, 4*cos1], [-n-3, n, 1], [-n], [], [], [0.5, 0.5*(1+n), 0.5*(n+2)], r
|
| 362 |
+
T2 = [2, z, -sin1], [-n-3, 2+n, 1], [-n-1], [], [], [1.5, 0.5*(3+n), 0.5*(n+2)], r
|
| 363 |
+
T3 = [2, z, 4*cos2], [n-3, -n, 1], [n], [], [], [0.5, 0.5*(1-n), 1-0.5*n], r
|
| 364 |
+
T4 = [2, z, -sin2], [n-3, 2-n, 1], [n-1], [], [], [1.5, 0.5*(3-n), 1-0.5*n], r
|
| 365 |
+
return T1, T2, T3, T4
|
| 366 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 367 |
+
|
| 368 |
+
@defun
|
| 369 |
+
def kei(ctx, n, z, **kwargs):
|
| 370 |
+
n = ctx.convert(n)
|
| 371 |
+
z = ctx.convert(z)
|
| 372 |
+
# http://functions.wolfram.com/Bessel-TypeFunctions/KelvinKei2/26/01/02/0001/
|
| 373 |
+
def h(n):
|
| 374 |
+
r = -(z/4)**4
|
| 375 |
+
cos1, sin1 = ctx.cospi_sinpi(0.75*n)
|
| 376 |
+
cos2, sin2 = ctx.cospi_sinpi(0.25*n)
|
| 377 |
+
T1 = [-cos1, 2, z], [1, n-3, 2-n], [n-1], [], [], [1.5, 0.5*(3-n), 1-0.5*n], r
|
| 378 |
+
T2 = [-sin1, 2, z], [1, n-1, -n], [n], [], [], [0.5, 0.5*(1-n), 1-0.5*n], r
|
| 379 |
+
T3 = [-sin2, 2, z], [1, -n-1, n], [-n], [], [], [0.5, 0.5*(n+1), 0.5*(n+2)], r
|
| 380 |
+
T4 = [-cos2, 2, z], [1, -n-3, n+2], [-n-1], [], [], [1.5, 0.5*(n+3), 0.5*(n+2)], r
|
| 381 |
+
return T1, T2, T3, T4
|
| 382 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 383 |
+
|
| 384 |
+
# TODO: do this more generically?
|
| 385 |
+
def c_memo(f):
|
| 386 |
+
name = f.__name__
|
| 387 |
+
def f_wrapped(ctx):
|
| 388 |
+
cache = ctx._misc_const_cache
|
| 389 |
+
prec = ctx.prec
|
| 390 |
+
p,v = cache.get(name, (-1,0))
|
| 391 |
+
if p >= prec:
|
| 392 |
+
return +v
|
| 393 |
+
else:
|
| 394 |
+
cache[name] = (prec, f(ctx))
|
| 395 |
+
return cache[name][1]
|
| 396 |
+
return f_wrapped
|
| 397 |
+
|
| 398 |
+
@c_memo
|
| 399 |
+
def _airyai_C1(ctx):
|
| 400 |
+
return 1 / (ctx.cbrt(9) * ctx.gamma(ctx.mpf(2)/3))
|
| 401 |
+
|
| 402 |
+
@c_memo
|
| 403 |
+
def _airyai_C2(ctx):
|
| 404 |
+
return -1 / (ctx.cbrt(3) * ctx.gamma(ctx.mpf(1)/3))
|
| 405 |
+
|
| 406 |
+
@c_memo
|
| 407 |
+
def _airybi_C1(ctx):
|
| 408 |
+
return 1 / (ctx.nthroot(3,6) * ctx.gamma(ctx.mpf(2)/3))
|
| 409 |
+
|
| 410 |
+
@c_memo
|
| 411 |
+
def _airybi_C2(ctx):
|
| 412 |
+
return ctx.nthroot(3,6) / ctx.gamma(ctx.mpf(1)/3)
|
| 413 |
+
|
| 414 |
+
def _airybi_n2_inf(ctx):
|
| 415 |
+
prec = ctx.prec
|
| 416 |
+
try:
|
| 417 |
+
v = ctx.power(3,'2/3')*ctx.gamma('2/3')/(2*ctx.pi)
|
| 418 |
+
finally:
|
| 419 |
+
ctx.prec = prec
|
| 420 |
+
return +v
|
| 421 |
+
|
| 422 |
+
# Derivatives at z = 0
|
| 423 |
+
# TODO: could be expressed more elegantly using triple factorials
|
| 424 |
+
def _airyderiv_0(ctx, z, n, ntype, which):
|
| 425 |
+
if ntype == 'Z':
|
| 426 |
+
if n < 0:
|
| 427 |
+
return z
|
| 428 |
+
r = ctx.mpq_1_3
|
| 429 |
+
prec = ctx.prec
|
| 430 |
+
try:
|
| 431 |
+
ctx.prec += 10
|
| 432 |
+
v = ctx.gamma((n+1)*r) * ctx.power(3,n*r) / ctx.pi
|
| 433 |
+
if which == 0:
|
| 434 |
+
v *= ctx.sinpi(2*(n+1)*r)
|
| 435 |
+
v /= ctx.power(3,'2/3')
|
| 436 |
+
else:
|
| 437 |
+
v *= abs(ctx.sinpi(2*(n+1)*r))
|
| 438 |
+
v /= ctx.power(3,'1/6')
|
| 439 |
+
finally:
|
| 440 |
+
ctx.prec = prec
|
| 441 |
+
return +v + z
|
| 442 |
+
else:
|
| 443 |
+
# singular (does the limit exist?)
|
| 444 |
+
raise NotImplementedError
|
| 445 |
+
|
| 446 |
+
@defun
|
| 447 |
+
def airyai(ctx, z, derivative=0, **kwargs):
|
| 448 |
+
z = ctx.convert(z)
|
| 449 |
+
if derivative:
|
| 450 |
+
n, ntype = ctx._convert_param(derivative)
|
| 451 |
+
else:
|
| 452 |
+
n = 0
|
| 453 |
+
# Values at infinities
|
| 454 |
+
if not ctx.isnormal(z) and z:
|
| 455 |
+
if n and ntype == 'Z':
|
| 456 |
+
if n == -1:
|
| 457 |
+
if z == ctx.inf:
|
| 458 |
+
return ctx.mpf(1)/3 + 1/z
|
| 459 |
+
if z == ctx.ninf:
|
| 460 |
+
return ctx.mpf(-2)/3 + 1/z
|
| 461 |
+
if n < -1:
|
| 462 |
+
if z == ctx.inf:
|
| 463 |
+
return z
|
| 464 |
+
if z == ctx.ninf:
|
| 465 |
+
return (-1)**n * (-z)
|
| 466 |
+
if (not n) and z == ctx.inf or z == ctx.ninf:
|
| 467 |
+
return 1/z
|
| 468 |
+
# TODO: limits
|
| 469 |
+
raise ValueError("essential singularity of Ai(z)")
|
| 470 |
+
# Account for exponential scaling
|
| 471 |
+
if z:
|
| 472 |
+
extraprec = max(0, int(1.5*ctx.mag(z)))
|
| 473 |
+
else:
|
| 474 |
+
extraprec = 0
|
| 475 |
+
if n:
|
| 476 |
+
if n == 1:
|
| 477 |
+
def h():
|
| 478 |
+
# http://functions.wolfram.com/03.07.06.0005.01
|
| 479 |
+
if ctx._re(z) > 4:
|
| 480 |
+
ctx.prec += extraprec
|
| 481 |
+
w = z**1.5; r = -0.75/w; u = -2*w/3
|
| 482 |
+
ctx.prec -= extraprec
|
| 483 |
+
C = -ctx.exp(u)/(2*ctx.sqrt(ctx.pi))*ctx.nthroot(z,4)
|
| 484 |
+
return ([C],[1],[],[],[(-1,6),(7,6)],[],r),
|
| 485 |
+
# http://functions.wolfram.com/03.07.26.0001.01
|
| 486 |
+
else:
|
| 487 |
+
ctx.prec += extraprec
|
| 488 |
+
w = z**3 / 9
|
| 489 |
+
ctx.prec -= extraprec
|
| 490 |
+
C1 = _airyai_C1(ctx) * 0.5
|
| 491 |
+
C2 = _airyai_C2(ctx)
|
| 492 |
+
T1 = [C1,z],[1,2],[],[],[],[ctx.mpq_5_3],w
|
| 493 |
+
T2 = [C2],[1],[],[],[],[ctx.mpq_1_3],w
|
| 494 |
+
return T1, T2
|
| 495 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 496 |
+
else:
|
| 497 |
+
if z == 0:
|
| 498 |
+
return _airyderiv_0(ctx, z, n, ntype, 0)
|
| 499 |
+
# http://functions.wolfram.com/03.05.20.0004.01
|
| 500 |
+
def h(n):
|
| 501 |
+
ctx.prec += extraprec
|
| 502 |
+
w = z**3/9
|
| 503 |
+
ctx.prec -= extraprec
|
| 504 |
+
q13,q23,q43 = ctx.mpq_1_3, ctx.mpq_2_3, ctx.mpq_4_3
|
| 505 |
+
a1=q13; a2=1; b1=(1-n)*q13; b2=(2-n)*q13; b3=1-n*q13
|
| 506 |
+
T1 = [3, z], [n-q23, -n], [a1], [b1,b2,b3], \
|
| 507 |
+
[a1,a2], [b1,b2,b3], w
|
| 508 |
+
a1=q23; b1=(2-n)*q13; b2=1-n*q13; b3=(4-n)*q13
|
| 509 |
+
T2 = [3, z, -z], [n-q43, -n, 1], [a1], [b1,b2,b3], \
|
| 510 |
+
[a1,a2], [b1,b2,b3], w
|
| 511 |
+
return T1, T2
|
| 512 |
+
v = ctx.hypercomb(h, [n], **kwargs)
|
| 513 |
+
if ctx._is_real_type(z) and ctx.isint(n):
|
| 514 |
+
v = ctx._re(v)
|
| 515 |
+
return v
|
| 516 |
+
else:
|
| 517 |
+
def h():
|
| 518 |
+
if ctx._re(z) > 4:
|
| 519 |
+
# We could use 1F1, but it results in huge cancellation;
|
| 520 |
+
# the following expansion is better.
|
| 521 |
+
# TODO: asymptotic series for derivatives
|
| 522 |
+
ctx.prec += extraprec
|
| 523 |
+
w = z**1.5; r = -0.75/w; u = -2*w/3
|
| 524 |
+
ctx.prec -= extraprec
|
| 525 |
+
C = ctx.exp(u)/(2*ctx.sqrt(ctx.pi)*ctx.nthroot(z,4))
|
| 526 |
+
return ([C],[1],[],[],[(1,6),(5,6)],[],r),
|
| 527 |
+
else:
|
| 528 |
+
ctx.prec += extraprec
|
| 529 |
+
w = z**3 / 9
|
| 530 |
+
ctx.prec -= extraprec
|
| 531 |
+
C1 = _airyai_C1(ctx)
|
| 532 |
+
C2 = _airyai_C2(ctx)
|
| 533 |
+
T1 = [C1],[1],[],[],[],[ctx.mpq_2_3],w
|
| 534 |
+
T2 = [z*C2],[1],[],[],[],[ctx.mpq_4_3],w
|
| 535 |
+
return T1, T2
|
| 536 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 537 |
+
|
| 538 |
+
@defun
|
| 539 |
+
def airybi(ctx, z, derivative=0, **kwargs):
|
| 540 |
+
z = ctx.convert(z)
|
| 541 |
+
if derivative:
|
| 542 |
+
n, ntype = ctx._convert_param(derivative)
|
| 543 |
+
else:
|
| 544 |
+
n = 0
|
| 545 |
+
# Values at infinities
|
| 546 |
+
if not ctx.isnormal(z) and z:
|
| 547 |
+
if n and ntype == 'Z':
|
| 548 |
+
if z == ctx.inf:
|
| 549 |
+
return z
|
| 550 |
+
if z == ctx.ninf:
|
| 551 |
+
if n == -1:
|
| 552 |
+
return 1/z
|
| 553 |
+
if n == -2:
|
| 554 |
+
return _airybi_n2_inf(ctx)
|
| 555 |
+
if n < -2:
|
| 556 |
+
return (-1)**n * (-z)
|
| 557 |
+
if not n:
|
| 558 |
+
if z == ctx.inf:
|
| 559 |
+
return z
|
| 560 |
+
if z == ctx.ninf:
|
| 561 |
+
return 1/z
|
| 562 |
+
# TODO: limits
|
| 563 |
+
raise ValueError("essential singularity of Bi(z)")
|
| 564 |
+
if z:
|
| 565 |
+
extraprec = max(0, int(1.5*ctx.mag(z)))
|
| 566 |
+
else:
|
| 567 |
+
extraprec = 0
|
| 568 |
+
if n:
|
| 569 |
+
if n == 1:
|
| 570 |
+
# http://functions.wolfram.com/03.08.26.0001.01
|
| 571 |
+
def h():
|
| 572 |
+
ctx.prec += extraprec
|
| 573 |
+
w = z**3 / 9
|
| 574 |
+
ctx.prec -= extraprec
|
| 575 |
+
C1 = _airybi_C1(ctx)*0.5
|
| 576 |
+
C2 = _airybi_C2(ctx)
|
| 577 |
+
T1 = [C1,z],[1,2],[],[],[],[ctx.mpq_5_3],w
|
| 578 |
+
T2 = [C2],[1],[],[],[],[ctx.mpq_1_3],w
|
| 579 |
+
return T1, T2
|
| 580 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 581 |
+
else:
|
| 582 |
+
if z == 0:
|
| 583 |
+
return _airyderiv_0(ctx, z, n, ntype, 1)
|
| 584 |
+
def h(n):
|
| 585 |
+
ctx.prec += extraprec
|
| 586 |
+
w = z**3/9
|
| 587 |
+
ctx.prec -= extraprec
|
| 588 |
+
q13,q23,q43 = ctx.mpq_1_3, ctx.mpq_2_3, ctx.mpq_4_3
|
| 589 |
+
q16 = ctx.mpq_1_6
|
| 590 |
+
q56 = ctx.mpq_5_6
|
| 591 |
+
a1=q13; a2=1; b1=(1-n)*q13; b2=(2-n)*q13; b3=1-n*q13
|
| 592 |
+
T1 = [3, z], [n-q16, -n], [a1], [b1,b2,b3], \
|
| 593 |
+
[a1,a2], [b1,b2,b3], w
|
| 594 |
+
a1=q23; b1=(2-n)*q13; b2=1-n*q13; b3=(4-n)*q13
|
| 595 |
+
T2 = [3, z], [n-q56, 1-n], [a1], [b1,b2,b3], \
|
| 596 |
+
[a1,a2], [b1,b2,b3], w
|
| 597 |
+
return T1, T2
|
| 598 |
+
v = ctx.hypercomb(h, [n], **kwargs)
|
| 599 |
+
if ctx._is_real_type(z) and ctx.isint(n):
|
| 600 |
+
v = ctx._re(v)
|
| 601 |
+
return v
|
| 602 |
+
else:
|
| 603 |
+
def h():
|
| 604 |
+
ctx.prec += extraprec
|
| 605 |
+
w = z**3 / 9
|
| 606 |
+
ctx.prec -= extraprec
|
| 607 |
+
C1 = _airybi_C1(ctx)
|
| 608 |
+
C2 = _airybi_C2(ctx)
|
| 609 |
+
T1 = [C1],[1],[],[],[],[ctx.mpq_2_3],w
|
| 610 |
+
T2 = [z*C2],[1],[],[],[],[ctx.mpq_4_3],w
|
| 611 |
+
return T1, T2
|
| 612 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 613 |
+
|
| 614 |
+
def _airy_zero(ctx, which, k, derivative, complex=False):
|
| 615 |
+
# Asymptotic formulas are given in DLMF section 9.9
|
| 616 |
+
def U(t): return t**(2/3.)*(1-7/(t**2*48))
|
| 617 |
+
def T(t): return t**(2/3.)*(1+5/(t**2*48))
|
| 618 |
+
k = int(k)
|
| 619 |
+
if k < 1:
|
| 620 |
+
raise ValueError("k cannot be less than 1")
|
| 621 |
+
if not derivative in (0,1):
|
| 622 |
+
raise ValueError("Derivative should lie between 0 and 1")
|
| 623 |
+
if which == 0:
|
| 624 |
+
if derivative:
|
| 625 |
+
return ctx.findroot(lambda z: ctx.airyai(z,1),
|
| 626 |
+
-U(3*ctx.pi*(4*k-3)/8))
|
| 627 |
+
return ctx.findroot(ctx.airyai, -T(3*ctx.pi*(4*k-1)/8))
|
| 628 |
+
if which == 1 and complex == False:
|
| 629 |
+
if derivative:
|
| 630 |
+
return ctx.findroot(lambda z: ctx.airybi(z,1),
|
| 631 |
+
-U(3*ctx.pi*(4*k-1)/8))
|
| 632 |
+
return ctx.findroot(ctx.airybi, -T(3*ctx.pi*(4*k-3)/8))
|
| 633 |
+
if which == 1 and complex == True:
|
| 634 |
+
if derivative:
|
| 635 |
+
t = 3*ctx.pi*(4*k-3)/8 + 0.75j*ctx.ln2
|
| 636 |
+
s = ctx.expjpi(ctx.mpf(1)/3) * T(t)
|
| 637 |
+
return ctx.findroot(lambda z: ctx.airybi(z,1), s)
|
| 638 |
+
t = 3*ctx.pi*(4*k-1)/8 + 0.75j*ctx.ln2
|
| 639 |
+
s = ctx.expjpi(ctx.mpf(1)/3) * U(t)
|
| 640 |
+
return ctx.findroot(ctx.airybi, s)
|
| 641 |
+
|
| 642 |
+
@defun
|
| 643 |
+
def airyaizero(ctx, k, derivative=0):
|
| 644 |
+
return _airy_zero(ctx, 0, k, derivative, False)
|
| 645 |
+
|
| 646 |
+
@defun
|
| 647 |
+
def airybizero(ctx, k, derivative=0, complex=False):
|
| 648 |
+
return _airy_zero(ctx, 1, k, derivative, complex)
|
| 649 |
+
|
| 650 |
+
def _scorer(ctx, z, which, kwargs):
|
| 651 |
+
z = ctx.convert(z)
|
| 652 |
+
if ctx.isinf(z):
|
| 653 |
+
if z == ctx.inf:
|
| 654 |
+
if which == 0: return 1/z
|
| 655 |
+
if which == 1: return z
|
| 656 |
+
if z == ctx.ninf:
|
| 657 |
+
return 1/z
|
| 658 |
+
raise ValueError("essential singularity")
|
| 659 |
+
if z:
|
| 660 |
+
extraprec = max(0, int(1.5*ctx.mag(z)))
|
| 661 |
+
else:
|
| 662 |
+
extraprec = 0
|
| 663 |
+
if kwargs.get('derivative'):
|
| 664 |
+
raise NotImplementedError
|
| 665 |
+
# Direct asymptotic expansions, to avoid
|
| 666 |
+
# exponentially large cancellation
|
| 667 |
+
try:
|
| 668 |
+
if ctx.mag(z) > 3:
|
| 669 |
+
if which == 0 and abs(ctx.arg(z)) < ctx.pi/3 * 0.999:
|
| 670 |
+
def h():
|
| 671 |
+
return (([ctx.pi,z],[-1,-1],[],[],[(1,3),(2,3),1],[],9/z**3),)
|
| 672 |
+
return ctx.hypercomb(h, [], maxterms=ctx.prec, force_series=True)
|
| 673 |
+
if which == 1 and abs(ctx.arg(-z)) < 2*ctx.pi/3 * 0.999:
|
| 674 |
+
def h():
|
| 675 |
+
return (([-ctx.pi,z],[-1,-1],[],[],[(1,3),(2,3),1],[],9/z**3),)
|
| 676 |
+
return ctx.hypercomb(h, [], maxterms=ctx.prec, force_series=True)
|
| 677 |
+
except ctx.NoConvergence:
|
| 678 |
+
pass
|
| 679 |
+
def h():
|
| 680 |
+
A = ctx.airybi(z, **kwargs)/3
|
| 681 |
+
B = -2*ctx.pi
|
| 682 |
+
if which == 1:
|
| 683 |
+
A *= 2
|
| 684 |
+
B *= -1
|
| 685 |
+
ctx.prec += extraprec
|
| 686 |
+
w = z**3/9
|
| 687 |
+
ctx.prec -= extraprec
|
| 688 |
+
T1 = [A], [1], [], [], [], [], 0
|
| 689 |
+
T2 = [B,z], [-1,2], [], [], [1], [ctx.mpq_4_3,ctx.mpq_5_3], w
|
| 690 |
+
return T1, T2
|
| 691 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 692 |
+
|
| 693 |
+
@defun
|
| 694 |
+
def scorergi(ctx, z, **kwargs):
|
| 695 |
+
return _scorer(ctx, z, 0, kwargs)
|
| 696 |
+
|
| 697 |
+
@defun
|
| 698 |
+
def scorerhi(ctx, z, **kwargs):
|
| 699 |
+
return _scorer(ctx, z, 1, kwargs)
|
| 700 |
+
|
| 701 |
+
@defun_wrapped
|
| 702 |
+
def coulombc(ctx, l, eta, _cache={}):
|
| 703 |
+
if (l, eta) in _cache and _cache[l,eta][0] >= ctx.prec:
|
| 704 |
+
return +_cache[l,eta][1]
|
| 705 |
+
G3 = ctx.loggamma(2*l+2)
|
| 706 |
+
G1 = ctx.loggamma(1+l+ctx.j*eta)
|
| 707 |
+
G2 = ctx.loggamma(1+l-ctx.j*eta)
|
| 708 |
+
v = 2**l * ctx.exp((-ctx.pi*eta+G1+G2)/2 - G3)
|
| 709 |
+
if not (ctx.im(l) or ctx.im(eta)):
|
| 710 |
+
v = ctx.re(v)
|
| 711 |
+
_cache[l,eta] = (ctx.prec, v)
|
| 712 |
+
return v
|
| 713 |
+
|
| 714 |
+
@defun_wrapped
|
| 715 |
+
def coulombf(ctx, l, eta, z, w=1, chop=True, **kwargs):
|
| 716 |
+
# Regular Coulomb wave function
|
| 717 |
+
# Note: w can be either 1 or -1; the other may be better in some cases
|
| 718 |
+
# TODO: check that chop=True chops when and only when it should
|
| 719 |
+
#ctx.prec += 10
|
| 720 |
+
def h(l, eta):
|
| 721 |
+
try:
|
| 722 |
+
jw = ctx.j*w
|
| 723 |
+
jwz = ctx.fmul(jw, z, exact=True)
|
| 724 |
+
jwz2 = ctx.fmul(jwz, -2, exact=True)
|
| 725 |
+
C = ctx.coulombc(l, eta)
|
| 726 |
+
T1 = [C, z, ctx.exp(jwz)], [1, l+1, 1], [], [], [1+l+jw*eta], \
|
| 727 |
+
[2*l+2], jwz2
|
| 728 |
+
except ValueError:
|
| 729 |
+
T1 = [0], [-1], [], [], [], [], 0
|
| 730 |
+
return (T1,)
|
| 731 |
+
v = ctx.hypercomb(h, [l,eta], **kwargs)
|
| 732 |
+
if chop and (not ctx.im(l)) and (not ctx.im(eta)) and (not ctx.im(z)) and \
|
| 733 |
+
(ctx.re(z) >= 0):
|
| 734 |
+
v = ctx.re(v)
|
| 735 |
+
return v
|
| 736 |
+
|
| 737 |
+
@defun_wrapped
|
| 738 |
+
def _coulomb_chi(ctx, l, eta, _cache={}):
|
| 739 |
+
if (l, eta) in _cache and _cache[l,eta][0] >= ctx.prec:
|
| 740 |
+
return _cache[l,eta][1]
|
| 741 |
+
def terms():
|
| 742 |
+
l2 = -l-1
|
| 743 |
+
jeta = ctx.j*eta
|
| 744 |
+
return [ctx.loggamma(1+l+jeta) * (-0.5j),
|
| 745 |
+
ctx.loggamma(1+l-jeta) * (0.5j),
|
| 746 |
+
ctx.loggamma(1+l2+jeta) * (0.5j),
|
| 747 |
+
ctx.loggamma(1+l2-jeta) * (-0.5j),
|
| 748 |
+
-(l+0.5)*ctx.pi]
|
| 749 |
+
v = ctx.sum_accurately(terms, 1)
|
| 750 |
+
_cache[l,eta] = (ctx.prec, v)
|
| 751 |
+
return v
|
| 752 |
+
|
| 753 |
+
@defun_wrapped
|
| 754 |
+
def coulombg(ctx, l, eta, z, w=1, chop=True, **kwargs):
|
| 755 |
+
# Irregular Coulomb wave function
|
| 756 |
+
# Note: w can be either 1 or -1; the other may be better in some cases
|
| 757 |
+
# TODO: check that chop=True chops when and only when it should
|
| 758 |
+
if not ctx._im(l):
|
| 759 |
+
l = ctx._re(l) # XXX: for isint
|
| 760 |
+
def h(l, eta):
|
| 761 |
+
# Force perturbation for integers and half-integers
|
| 762 |
+
if ctx.isint(l*2):
|
| 763 |
+
T1 = [0], [-1], [], [], [], [], 0
|
| 764 |
+
return (T1,)
|
| 765 |
+
l2 = -l-1
|
| 766 |
+
try:
|
| 767 |
+
chi = ctx._coulomb_chi(l, eta)
|
| 768 |
+
jw = ctx.j*w
|
| 769 |
+
s = ctx.sin(chi); c = ctx.cos(chi)
|
| 770 |
+
C1 = ctx.coulombc(l,eta)
|
| 771 |
+
C2 = ctx.coulombc(l2,eta)
|
| 772 |
+
u = ctx.exp(jw*z)
|
| 773 |
+
x = -2*jw*z
|
| 774 |
+
T1 = [s, C1, z, u, c], [-1, 1, l+1, 1, 1], [], [], \
|
| 775 |
+
[1+l+jw*eta], [2*l+2], x
|
| 776 |
+
T2 = [-s, C2, z, u], [-1, 1, l2+1, 1], [], [], \
|
| 777 |
+
[1+l2+jw*eta], [2*l2+2], x
|
| 778 |
+
return T1, T2
|
| 779 |
+
except ValueError:
|
| 780 |
+
T1 = [0], [-1], [], [], [], [], 0
|
| 781 |
+
return (T1,)
|
| 782 |
+
v = ctx.hypercomb(h, [l,eta], **kwargs)
|
| 783 |
+
if chop and (not ctx._im(l)) and (not ctx._im(eta)) and (not ctx._im(z)) and \
|
| 784 |
+
(ctx._re(z) >= 0):
|
| 785 |
+
v = ctx._re(v)
|
| 786 |
+
return v
|
| 787 |
+
|
| 788 |
+
def mcmahon(ctx,kind,prime,v,m):
|
| 789 |
+
"""
|
| 790 |
+
Computes an estimate for the location of the Bessel function zero
|
| 791 |
+
j_{v,m}, y_{v,m}, j'_{v,m} or y'_{v,m} using McMahon's asymptotic
|
| 792 |
+
expansion (Abramowitz & Stegun 9.5.12-13, DLMF 20.21(vi)).
|
| 793 |
+
|
| 794 |
+
Returns (r,err) where r is the estimated location of the root
|
| 795 |
+
and err is a positive number estimating the error of the
|
| 796 |
+
asymptotic expansion.
|
| 797 |
+
"""
|
| 798 |
+
u = 4*v**2
|
| 799 |
+
if kind == 1 and not prime: b = (4*m+2*v-1)*ctx.pi/4
|
| 800 |
+
if kind == 2 and not prime: b = (4*m+2*v-3)*ctx.pi/4
|
| 801 |
+
if kind == 1 and prime: b = (4*m+2*v-3)*ctx.pi/4
|
| 802 |
+
if kind == 2 and prime: b = (4*m+2*v-1)*ctx.pi/4
|
| 803 |
+
if not prime:
|
| 804 |
+
s1 = b
|
| 805 |
+
s2 = -(u-1)/(8*b)
|
| 806 |
+
s3 = -4*(u-1)*(7*u-31)/(3*(8*b)**3)
|
| 807 |
+
s4 = -32*(u-1)*(83*u**2-982*u+3779)/(15*(8*b)**5)
|
| 808 |
+
s5 = -64*(u-1)*(6949*u**3-153855*u**2+1585743*u-6277237)/(105*(8*b)**7)
|
| 809 |
+
if prime:
|
| 810 |
+
s1 = b
|
| 811 |
+
s2 = -(u+3)/(8*b)
|
| 812 |
+
s3 = -4*(7*u**2+82*u-9)/(3*(8*b)**3)
|
| 813 |
+
s4 = -32*(83*u**3+2075*u**2-3039*u+3537)/(15*(8*b)**5)
|
| 814 |
+
s5 = -64*(6949*u**4+296492*u**3-1248002*u**2+7414380*u-5853627)/(105*(8*b)**7)
|
| 815 |
+
terms = [s1,s2,s3,s4,s5]
|
| 816 |
+
s = s1
|
| 817 |
+
err = 0.0
|
| 818 |
+
for i in range(1,len(terms)):
|
| 819 |
+
if abs(terms[i]) < abs(terms[i-1]):
|
| 820 |
+
s += terms[i]
|
| 821 |
+
else:
|
| 822 |
+
err = abs(terms[i])
|
| 823 |
+
if i == len(terms)-1:
|
| 824 |
+
err = abs(terms[-1])
|
| 825 |
+
return s, err
|
| 826 |
+
|
| 827 |
+
def generalized_bisection(ctx,f,a,b,n):
|
| 828 |
+
"""
|
| 829 |
+
Given f known to have exactly n simple roots within [a,b],
|
| 830 |
+
return a list of n intervals isolating the roots
|
| 831 |
+
and having opposite signs at the endpoints.
|
| 832 |
+
|
| 833 |
+
TODO: this can be optimized, e.g. by reusing evaluation points.
|
| 834 |
+
"""
|
| 835 |
+
if n < 1:
|
| 836 |
+
raise ValueError("n cannot be less than 1")
|
| 837 |
+
N = n+1
|
| 838 |
+
points = []
|
| 839 |
+
signs = []
|
| 840 |
+
while 1:
|
| 841 |
+
points = ctx.linspace(a,b,N)
|
| 842 |
+
signs = [ctx.sign(f(x)) for x in points]
|
| 843 |
+
ok_intervals = [(points[i],points[i+1]) for i in range(N-1) \
|
| 844 |
+
if signs[i]*signs[i+1] == -1]
|
| 845 |
+
if len(ok_intervals) == n:
|
| 846 |
+
return ok_intervals
|
| 847 |
+
N = N*2
|
| 848 |
+
|
| 849 |
+
def find_in_interval(ctx, f, ab):
|
| 850 |
+
return ctx.findroot(f, ab, solver='illinois', verify=False)
|
| 851 |
+
|
| 852 |
+
def bessel_zero(ctx, kind, prime, v, m, isoltol=0.01, _interval_cache={}):
|
| 853 |
+
prec = ctx.prec
|
| 854 |
+
workprec = max(prec, ctx.mag(v), ctx.mag(m))+10
|
| 855 |
+
try:
|
| 856 |
+
ctx.prec = workprec
|
| 857 |
+
v = ctx.mpf(v)
|
| 858 |
+
m = int(m)
|
| 859 |
+
prime = int(prime)
|
| 860 |
+
if v < 0:
|
| 861 |
+
raise ValueError("v cannot be negative")
|
| 862 |
+
if m < 1:
|
| 863 |
+
raise ValueError("m cannot be less than 1")
|
| 864 |
+
if not prime in (0,1):
|
| 865 |
+
raise ValueError("prime should lie between 0 and 1")
|
| 866 |
+
if kind == 1:
|
| 867 |
+
if prime: f = lambda x: ctx.besselj(v,x,derivative=1)
|
| 868 |
+
else: f = lambda x: ctx.besselj(v,x)
|
| 869 |
+
if kind == 2:
|
| 870 |
+
if prime: f = lambda x: ctx.bessely(v,x,derivative=1)
|
| 871 |
+
else: f = lambda x: ctx.bessely(v,x)
|
| 872 |
+
# The first root of J' is very close to 0 for small
|
| 873 |
+
# orders, and this needs to be special-cased
|
| 874 |
+
if kind == 1 and prime and m == 1:
|
| 875 |
+
if v == 0:
|
| 876 |
+
return ctx.zero
|
| 877 |
+
if v <= 1:
|
| 878 |
+
# TODO: use v <= j'_{v,1} < y_{v,1}?
|
| 879 |
+
r = 2*ctx.sqrt(v*(1+v)/(v+2))
|
| 880 |
+
return find_in_interval(ctx, f, (r/10, 2*r))
|
| 881 |
+
if (kind,prime,v,m) in _interval_cache:
|
| 882 |
+
return find_in_interval(ctx, f, _interval_cache[kind,prime,v,m])
|
| 883 |
+
r, err = mcmahon(ctx, kind, prime, v, m)
|
| 884 |
+
if err < isoltol:
|
| 885 |
+
return find_in_interval(ctx, f, (r-isoltol, r+isoltol))
|
| 886 |
+
# An x such that 0 < x < r_{v,1}
|
| 887 |
+
if kind == 1 and not prime: low = 2.4
|
| 888 |
+
if kind == 1 and prime: low = 1.8
|
| 889 |
+
if kind == 2 and not prime: low = 0.8
|
| 890 |
+
if kind == 2 and prime: low = 2.0
|
| 891 |
+
n = m+1
|
| 892 |
+
while 1:
|
| 893 |
+
r1, err = mcmahon(ctx, kind, prime, v, n)
|
| 894 |
+
if err < isoltol:
|
| 895 |
+
r2, err2 = mcmahon(ctx, kind, prime, v, n+1)
|
| 896 |
+
intervals = generalized_bisection(ctx, f, low, 0.5*(r1+r2), n)
|
| 897 |
+
for k, ab in enumerate(intervals):
|
| 898 |
+
_interval_cache[kind,prime,v,k+1] = ab
|
| 899 |
+
return find_in_interval(ctx, f, intervals[m-1])
|
| 900 |
+
else:
|
| 901 |
+
n = n*2
|
| 902 |
+
finally:
|
| 903 |
+
ctx.prec = prec
|
| 904 |
+
|
| 905 |
+
@defun
|
| 906 |
+
def besseljzero(ctx, v, m, derivative=0):
|
| 907 |
+
r"""
|
| 908 |
+
For a real order `\nu \ge 0` and a positive integer `m`, returns
|
| 909 |
+
`j_{\nu,m}`, the `m`-th positive zero of the Bessel function of the
|
| 910 |
+
first kind `J_{\nu}(z)` (see :func:`~mpmath.besselj`). Alternatively,
|
| 911 |
+
with *derivative=1*, gives the first nonnegative simple zero
|
| 912 |
+
`j'_{\nu,m}` of `J'_{\nu}(z)`.
|
| 913 |
+
|
| 914 |
+
The indexing convention is that used by Abramowitz & Stegun
|
| 915 |
+
and the DLMF. Note the special case `j'_{0,1} = 0`, while all other
|
| 916 |
+
zeros are positive. In effect, only simple zeros are counted
|
| 917 |
+
(all zeros of Bessel functions are simple except possibly `z = 0`)
|
| 918 |
+
and `j_{\nu,m}` becomes a monotonic function of both `\nu`
|
| 919 |
+
and `m`.
|
| 920 |
+
|
| 921 |
+
The zeros are interlaced according to the inequalities
|
| 922 |
+
|
| 923 |
+
.. math ::
|
| 924 |
+
|
| 925 |
+
j'_{\nu,k} < j_{\nu,k} < j'_{\nu,k+1}
|
| 926 |
+
|
| 927 |
+
j_{\nu,1} < j_{\nu+1,2} < j_{\nu,2} < j_{\nu+1,2} < j_{\nu,3} < \cdots
|
| 928 |
+
|
| 929 |
+
**Examples**
|
| 930 |
+
|
| 931 |
+
Initial zeros of the Bessel functions `J_0(z), J_1(z), J_2(z)`::
|
| 932 |
+
|
| 933 |
+
>>> from mpmath import *
|
| 934 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 935 |
+
>>> besseljzero(0,1); besseljzero(0,2); besseljzero(0,3)
|
| 936 |
+
2.404825557695772768621632
|
| 937 |
+
5.520078110286310649596604
|
| 938 |
+
8.653727912911012216954199
|
| 939 |
+
>>> besseljzero(1,1); besseljzero(1,2); besseljzero(1,3)
|
| 940 |
+
3.831705970207512315614436
|
| 941 |
+
7.01558666981561875353705
|
| 942 |
+
10.17346813506272207718571
|
| 943 |
+
>>> besseljzero(2,1); besseljzero(2,2); besseljzero(2,3)
|
| 944 |
+
5.135622301840682556301402
|
| 945 |
+
8.417244140399864857783614
|
| 946 |
+
11.61984117214905942709415
|
| 947 |
+
|
| 948 |
+
Initial zeros of `J'_0(z), J'_1(z), J'_2(z)`::
|
| 949 |
+
|
| 950 |
+
0.0
|
| 951 |
+
3.831705970207512315614436
|
| 952 |
+
7.01558666981561875353705
|
| 953 |
+
>>> besseljzero(1,1,1); besseljzero(1,2,1); besseljzero(1,3,1)
|
| 954 |
+
1.84118378134065930264363
|
| 955 |
+
5.331442773525032636884016
|
| 956 |
+
8.536316366346285834358961
|
| 957 |
+
>>> besseljzero(2,1,1); besseljzero(2,2,1); besseljzero(2,3,1)
|
| 958 |
+
3.054236928227140322755932
|
| 959 |
+
6.706133194158459146634394
|
| 960 |
+
9.969467823087595793179143
|
| 961 |
+
|
| 962 |
+
Zeros with large index::
|
| 963 |
+
|
| 964 |
+
>>> besseljzero(0,100); besseljzero(0,1000); besseljzero(0,10000)
|
| 965 |
+
313.3742660775278447196902
|
| 966 |
+
3140.807295225078628895545
|
| 967 |
+
31415.14114171350798533666
|
| 968 |
+
>>> besseljzero(5,100); besseljzero(5,1000); besseljzero(5,10000)
|
| 969 |
+
321.1893195676003157339222
|
| 970 |
+
3148.657306813047523500494
|
| 971 |
+
31422.9947255486291798943
|
| 972 |
+
>>> besseljzero(0,100,1); besseljzero(0,1000,1); besseljzero(0,10000,1)
|
| 973 |
+
311.8018681873704508125112
|
| 974 |
+
3139.236339643802482833973
|
| 975 |
+
31413.57032947022399485808
|
| 976 |
+
|
| 977 |
+
Zeros of functions with large order::
|
| 978 |
+
|
| 979 |
+
>>> besseljzero(50,1)
|
| 980 |
+
57.11689916011917411936228
|
| 981 |
+
>>> besseljzero(50,2)
|
| 982 |
+
62.80769876483536093435393
|
| 983 |
+
>>> besseljzero(50,100)
|
| 984 |
+
388.6936600656058834640981
|
| 985 |
+
>>> besseljzero(50,1,1)
|
| 986 |
+
52.99764038731665010944037
|
| 987 |
+
>>> besseljzero(50,2,1)
|
| 988 |
+
60.02631933279942589882363
|
| 989 |
+
>>> besseljzero(50,100,1)
|
| 990 |
+
387.1083151608726181086283
|
| 991 |
+
|
| 992 |
+
Zeros of functions with fractional order::
|
| 993 |
+
|
| 994 |
+
>>> besseljzero(0.5,1); besseljzero(1.5,1); besseljzero(2.25,4)
|
| 995 |
+
3.141592653589793238462643
|
| 996 |
+
4.493409457909064175307881
|
| 997 |
+
15.15657692957458622921634
|
| 998 |
+
|
| 999 |
+
Both `J_{\nu}(z)` and `J'_{\nu}(z)` can be expressed as infinite
|
| 1000 |
+
products over their zeros::
|
| 1001 |
+
|
| 1002 |
+
>>> v,z = 2, mpf(1)
|
| 1003 |
+
>>> (z/2)**v/gamma(v+1) * \
|
| 1004 |
+
... nprod(lambda k: 1-(z/besseljzero(v,k))**2, [1,inf])
|
| 1005 |
+
...
|
| 1006 |
+
0.1149034849319004804696469
|
| 1007 |
+
>>> besselj(v,z)
|
| 1008 |
+
0.1149034849319004804696469
|
| 1009 |
+
>>> (z/2)**(v-1)/2/gamma(v) * \
|
| 1010 |
+
... nprod(lambda k: 1-(z/besseljzero(v,k,1))**2, [1,inf])
|
| 1011 |
+
...
|
| 1012 |
+
0.2102436158811325550203884
|
| 1013 |
+
>>> besselj(v,z,1)
|
| 1014 |
+
0.2102436158811325550203884
|
| 1015 |
+
|
| 1016 |
+
"""
|
| 1017 |
+
return +bessel_zero(ctx, 1, derivative, v, m)
|
| 1018 |
+
|
| 1019 |
+
@defun
|
| 1020 |
+
def besselyzero(ctx, v, m, derivative=0):
|
| 1021 |
+
r"""
|
| 1022 |
+
For a real order `\nu \ge 0` and a positive integer `m`, returns
|
| 1023 |
+
`y_{\nu,m}`, the `m`-th positive zero of the Bessel function of the
|
| 1024 |
+
second kind `Y_{\nu}(z)` (see :func:`~mpmath.bessely`). Alternatively,
|
| 1025 |
+
with *derivative=1*, gives the first positive zero `y'_{\nu,m}` of
|
| 1026 |
+
`Y'_{\nu}(z)`.
|
| 1027 |
+
|
| 1028 |
+
The zeros are interlaced according to the inequalities
|
| 1029 |
+
|
| 1030 |
+
.. math ::
|
| 1031 |
+
|
| 1032 |
+
y_{\nu,k} < y'_{\nu,k} < y_{\nu,k+1}
|
| 1033 |
+
|
| 1034 |
+
y_{\nu,1} < y_{\nu+1,2} < y_{\nu,2} < y_{\nu+1,2} < y_{\nu,3} < \cdots
|
| 1035 |
+
|
| 1036 |
+
**Examples**
|
| 1037 |
+
|
| 1038 |
+
Initial zeros of the Bessel functions `Y_0(z), Y_1(z), Y_2(z)`::
|
| 1039 |
+
|
| 1040 |
+
>>> from mpmath import *
|
| 1041 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1042 |
+
>>> besselyzero(0,1); besselyzero(0,2); besselyzero(0,3)
|
| 1043 |
+
0.8935769662791675215848871
|
| 1044 |
+
3.957678419314857868375677
|
| 1045 |
+
7.086051060301772697623625
|
| 1046 |
+
>>> besselyzero(1,1); besselyzero(1,2); besselyzero(1,3)
|
| 1047 |
+
2.197141326031017035149034
|
| 1048 |
+
5.429681040794135132772005
|
| 1049 |
+
8.596005868331168926429606
|
| 1050 |
+
>>> besselyzero(2,1); besselyzero(2,2); besselyzero(2,3)
|
| 1051 |
+
3.384241767149593472701426
|
| 1052 |
+
6.793807513268267538291167
|
| 1053 |
+
10.02347797936003797850539
|
| 1054 |
+
|
| 1055 |
+
Initial zeros of `Y'_0(z), Y'_1(z), Y'_2(z)`::
|
| 1056 |
+
|
| 1057 |
+
>>> besselyzero(0,1,1); besselyzero(0,2,1); besselyzero(0,3,1)
|
| 1058 |
+
2.197141326031017035149034
|
| 1059 |
+
5.429681040794135132772005
|
| 1060 |
+
8.596005868331168926429606
|
| 1061 |
+
>>> besselyzero(1,1,1); besselyzero(1,2,1); besselyzero(1,3,1)
|
| 1062 |
+
3.683022856585177699898967
|
| 1063 |
+
6.941499953654175655751944
|
| 1064 |
+
10.12340465543661307978775
|
| 1065 |
+
>>> besselyzero(2,1,1); besselyzero(2,2,1); besselyzero(2,3,1)
|
| 1066 |
+
5.002582931446063945200176
|
| 1067 |
+
8.350724701413079526349714
|
| 1068 |
+
11.57419546521764654624265
|
| 1069 |
+
|
| 1070 |
+
Zeros with large index::
|
| 1071 |
+
|
| 1072 |
+
>>> besselyzero(0,100); besselyzero(0,1000); besselyzero(0,10000)
|
| 1073 |
+
311.8034717601871549333419
|
| 1074 |
+
3139.236498918198006794026
|
| 1075 |
+
31413.57034538691205229188
|
| 1076 |
+
>>> besselyzero(5,100); besselyzero(5,1000); besselyzero(5,10000)
|
| 1077 |
+
319.6183338562782156235062
|
| 1078 |
+
3147.086508524556404473186
|
| 1079 |
+
31421.42392920214673402828
|
| 1080 |
+
>>> besselyzero(0,100,1); besselyzero(0,1000,1); besselyzero(0,10000,1)
|
| 1081 |
+
313.3726705426359345050449
|
| 1082 |
+
3140.807136030340213610065
|
| 1083 |
+
31415.14112579761578220175
|
| 1084 |
+
|
| 1085 |
+
Zeros of functions with large order::
|
| 1086 |
+
|
| 1087 |
+
>>> besselyzero(50,1)
|
| 1088 |
+
53.50285882040036394680237
|
| 1089 |
+
>>> besselyzero(50,2)
|
| 1090 |
+
60.11244442774058114686022
|
| 1091 |
+
>>> besselyzero(50,100)
|
| 1092 |
+
387.1096509824943957706835
|
| 1093 |
+
>>> besselyzero(50,1,1)
|
| 1094 |
+
56.96290427516751320063605
|
| 1095 |
+
>>> besselyzero(50,2,1)
|
| 1096 |
+
62.74888166945933944036623
|
| 1097 |
+
>>> besselyzero(50,100,1)
|
| 1098 |
+
388.6923300548309258355475
|
| 1099 |
+
|
| 1100 |
+
Zeros of functions with fractional order::
|
| 1101 |
+
|
| 1102 |
+
>>> besselyzero(0.5,1); besselyzero(1.5,1); besselyzero(2.25,4)
|
| 1103 |
+
1.570796326794896619231322
|
| 1104 |
+
2.798386045783887136720249
|
| 1105 |
+
13.56721208770735123376018
|
| 1106 |
+
|
| 1107 |
+
"""
|
| 1108 |
+
return +bessel_zero(ctx, 2, derivative, v, m)
|
.venv/lib/python3.11/site-packages/mpmath/functions/elliptic.py
ADDED
|
@@ -0,0 +1,1431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
r"""
|
| 2 |
+
Elliptic functions historically comprise the elliptic integrals
|
| 3 |
+
and their inverses, and originate from the problem of computing the
|
| 4 |
+
arc length of an ellipse. From a more modern point of view,
|
| 5 |
+
an elliptic function is defined as a doubly periodic function, i.e.
|
| 6 |
+
a function which satisfies
|
| 7 |
+
|
| 8 |
+
.. math ::
|
| 9 |
+
|
| 10 |
+
f(z + 2 \omega_1) = f(z + 2 \omega_2) = f(z)
|
| 11 |
+
|
| 12 |
+
for some half-periods `\omega_1, \omega_2` with
|
| 13 |
+
`\mathrm{Im}[\omega_1 / \omega_2] > 0`. The canonical elliptic
|
| 14 |
+
functions are the Jacobi elliptic functions. More broadly, this section
|
| 15 |
+
includes quasi-doubly periodic functions (such as the Jacobi theta
|
| 16 |
+
functions) and other functions useful in the study of elliptic functions.
|
| 17 |
+
|
| 18 |
+
Many different conventions for the arguments of
|
| 19 |
+
elliptic functions are in use. It is even standard to use
|
| 20 |
+
different parameterizations for different functions in the same
|
| 21 |
+
text or software (and mpmath is no exception).
|
| 22 |
+
The usual parameters are the elliptic nome `q`, which usually
|
| 23 |
+
must satisfy `|q| < 1`; the elliptic parameter `m` (an arbitrary
|
| 24 |
+
complex number); the elliptic modulus `k` (an arbitrary complex
|
| 25 |
+
number); and the half-period ratio `\tau`, which usually must
|
| 26 |
+
satisfy `\mathrm{Im}[\tau] > 0`.
|
| 27 |
+
These quantities can be expressed in terms of each other
|
| 28 |
+
using the following relations:
|
| 29 |
+
|
| 30 |
+
.. math ::
|
| 31 |
+
|
| 32 |
+
m = k^2
|
| 33 |
+
|
| 34 |
+
.. math ::
|
| 35 |
+
|
| 36 |
+
\tau = i \frac{K(1-m)}{K(m)}
|
| 37 |
+
|
| 38 |
+
.. math ::
|
| 39 |
+
|
| 40 |
+
q = e^{i \pi \tau}
|
| 41 |
+
|
| 42 |
+
.. math ::
|
| 43 |
+
|
| 44 |
+
k = \frac{\vartheta_2^2(q)}{\vartheta_3^2(q)}
|
| 45 |
+
|
| 46 |
+
In addition, an alternative definition is used for the nome in
|
| 47 |
+
number theory, which we here denote by q-bar:
|
| 48 |
+
|
| 49 |
+
.. math ::
|
| 50 |
+
|
| 51 |
+
\bar{q} = q^2 = e^{2 i \pi \tau}
|
| 52 |
+
|
| 53 |
+
For convenience, mpmath provides functions to convert
|
| 54 |
+
between the various parameters (:func:`~mpmath.qfrom`, :func:`~mpmath.mfrom`,
|
| 55 |
+
:func:`~mpmath.kfrom`, :func:`~mpmath.taufrom`, :func:`~mpmath.qbarfrom`).
|
| 56 |
+
|
| 57 |
+
**References**
|
| 58 |
+
|
| 59 |
+
1. [AbramowitzStegun]_
|
| 60 |
+
|
| 61 |
+
2. [WhittakerWatson]_
|
| 62 |
+
|
| 63 |
+
"""
|
| 64 |
+
|
| 65 |
+
from .functions import defun, defun_wrapped
|
| 66 |
+
|
| 67 |
+
@defun_wrapped
|
| 68 |
+
def eta(ctx, tau):
|
| 69 |
+
r"""
|
| 70 |
+
Returns the Dedekind eta function of tau in the upper half-plane.
|
| 71 |
+
|
| 72 |
+
>>> from mpmath import *
|
| 73 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 74 |
+
>>> eta(1j); gamma(0.25) / (2*pi**0.75)
|
| 75 |
+
(0.7682254223260566590025942 + 0.0j)
|
| 76 |
+
0.7682254223260566590025942
|
| 77 |
+
>>> tau = sqrt(2) + sqrt(5)*1j
|
| 78 |
+
>>> eta(-1/tau); sqrt(-1j*tau) * eta(tau)
|
| 79 |
+
(0.9022859908439376463573294 + 0.07985093673948098408048575j)
|
| 80 |
+
(0.9022859908439376463573295 + 0.07985093673948098408048575j)
|
| 81 |
+
>>> eta(tau+1); exp(pi*1j/12) * eta(tau)
|
| 82 |
+
(0.4493066139717553786223114 + 0.3290014793877986663915939j)
|
| 83 |
+
(0.4493066139717553786223114 + 0.3290014793877986663915939j)
|
| 84 |
+
>>> f = lambda z: diff(eta, z) / eta(z)
|
| 85 |
+
>>> chop(36*diff(f,tau)**2 - 24*diff(f,tau,2)*f(tau) + diff(f,tau,3))
|
| 86 |
+
0.0
|
| 87 |
+
|
| 88 |
+
"""
|
| 89 |
+
if ctx.im(tau) <= 0.0:
|
| 90 |
+
raise ValueError("eta is only defined in the upper half-plane")
|
| 91 |
+
q = ctx.expjpi(tau/12)
|
| 92 |
+
return q * ctx.qp(q**24)
|
| 93 |
+
|
| 94 |
+
def nome(ctx, m):
|
| 95 |
+
m = ctx.convert(m)
|
| 96 |
+
if not m:
|
| 97 |
+
return m
|
| 98 |
+
if m == ctx.one:
|
| 99 |
+
return m
|
| 100 |
+
if ctx.isnan(m):
|
| 101 |
+
return m
|
| 102 |
+
if ctx.isinf(m):
|
| 103 |
+
if m == ctx.ninf:
|
| 104 |
+
return type(m)(-1)
|
| 105 |
+
else:
|
| 106 |
+
return ctx.mpc(-1)
|
| 107 |
+
a = ctx.ellipk(ctx.one-m)
|
| 108 |
+
b = ctx.ellipk(m)
|
| 109 |
+
v = ctx.exp(-ctx.pi*a/b)
|
| 110 |
+
if not ctx._im(m) and ctx._re(m) < 1:
|
| 111 |
+
if ctx._is_real_type(m):
|
| 112 |
+
return v.real
|
| 113 |
+
else:
|
| 114 |
+
return v.real + 0j
|
| 115 |
+
elif m == 2:
|
| 116 |
+
v = ctx.mpc(0, v.imag)
|
| 117 |
+
return v
|
| 118 |
+
|
| 119 |
+
@defun_wrapped
|
| 120 |
+
def qfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
|
| 121 |
+
r"""
|
| 122 |
+
Returns the elliptic nome `q`, given any of `q, m, k, \tau, \bar{q}`::
|
| 123 |
+
|
| 124 |
+
>>> from mpmath import *
|
| 125 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 126 |
+
>>> qfrom(q=0.25)
|
| 127 |
+
0.25
|
| 128 |
+
>>> qfrom(m=mfrom(q=0.25))
|
| 129 |
+
0.25
|
| 130 |
+
>>> qfrom(k=kfrom(q=0.25))
|
| 131 |
+
0.25
|
| 132 |
+
>>> qfrom(tau=taufrom(q=0.25))
|
| 133 |
+
(0.25 + 0.0j)
|
| 134 |
+
>>> qfrom(qbar=qbarfrom(q=0.25))
|
| 135 |
+
0.25
|
| 136 |
+
|
| 137 |
+
"""
|
| 138 |
+
if q is not None:
|
| 139 |
+
return ctx.convert(q)
|
| 140 |
+
if m is not None:
|
| 141 |
+
return nome(ctx, m)
|
| 142 |
+
if k is not None:
|
| 143 |
+
return nome(ctx, ctx.convert(k)**2)
|
| 144 |
+
if tau is not None:
|
| 145 |
+
return ctx.expjpi(tau)
|
| 146 |
+
if qbar is not None:
|
| 147 |
+
return ctx.sqrt(qbar)
|
| 148 |
+
|
| 149 |
+
@defun_wrapped
|
| 150 |
+
def qbarfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
|
| 151 |
+
r"""
|
| 152 |
+
Returns the number-theoretic nome `\bar q`, given any of
|
| 153 |
+
`q, m, k, \tau, \bar{q}`::
|
| 154 |
+
|
| 155 |
+
>>> from mpmath import *
|
| 156 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 157 |
+
>>> qbarfrom(qbar=0.25)
|
| 158 |
+
0.25
|
| 159 |
+
>>> qbarfrom(q=qfrom(qbar=0.25))
|
| 160 |
+
0.25
|
| 161 |
+
>>> qbarfrom(m=extraprec(20)(mfrom)(qbar=0.25)) # ill-conditioned
|
| 162 |
+
0.25
|
| 163 |
+
>>> qbarfrom(k=extraprec(20)(kfrom)(qbar=0.25)) # ill-conditioned
|
| 164 |
+
0.25
|
| 165 |
+
>>> qbarfrom(tau=taufrom(qbar=0.25))
|
| 166 |
+
(0.25 + 0.0j)
|
| 167 |
+
|
| 168 |
+
"""
|
| 169 |
+
if qbar is not None:
|
| 170 |
+
return ctx.convert(qbar)
|
| 171 |
+
if q is not None:
|
| 172 |
+
return ctx.convert(q) ** 2
|
| 173 |
+
if m is not None:
|
| 174 |
+
return nome(ctx, m) ** 2
|
| 175 |
+
if k is not None:
|
| 176 |
+
return nome(ctx, ctx.convert(k)**2) ** 2
|
| 177 |
+
if tau is not None:
|
| 178 |
+
return ctx.expjpi(2*tau)
|
| 179 |
+
|
| 180 |
+
@defun_wrapped
|
| 181 |
+
def taufrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
|
| 182 |
+
r"""
|
| 183 |
+
Returns the elliptic half-period ratio `\tau`, given any of
|
| 184 |
+
`q, m, k, \tau, \bar{q}`::
|
| 185 |
+
|
| 186 |
+
>>> from mpmath import *
|
| 187 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 188 |
+
>>> taufrom(tau=0.5j)
|
| 189 |
+
(0.0 + 0.5j)
|
| 190 |
+
>>> taufrom(q=qfrom(tau=0.5j))
|
| 191 |
+
(0.0 + 0.5j)
|
| 192 |
+
>>> taufrom(m=mfrom(tau=0.5j))
|
| 193 |
+
(0.0 + 0.5j)
|
| 194 |
+
>>> taufrom(k=kfrom(tau=0.5j))
|
| 195 |
+
(0.0 + 0.5j)
|
| 196 |
+
>>> taufrom(qbar=qbarfrom(tau=0.5j))
|
| 197 |
+
(0.0 + 0.5j)
|
| 198 |
+
|
| 199 |
+
"""
|
| 200 |
+
if tau is not None:
|
| 201 |
+
return ctx.convert(tau)
|
| 202 |
+
if m is not None:
|
| 203 |
+
m = ctx.convert(m)
|
| 204 |
+
return ctx.j*ctx.ellipk(1-m)/ctx.ellipk(m)
|
| 205 |
+
if k is not None:
|
| 206 |
+
k = ctx.convert(k)
|
| 207 |
+
return ctx.j*ctx.ellipk(1-k**2)/ctx.ellipk(k**2)
|
| 208 |
+
if q is not None:
|
| 209 |
+
return ctx.log(q) / (ctx.pi*ctx.j)
|
| 210 |
+
if qbar is not None:
|
| 211 |
+
qbar = ctx.convert(qbar)
|
| 212 |
+
return ctx.log(qbar) / (2*ctx.pi*ctx.j)
|
| 213 |
+
|
| 214 |
+
@defun_wrapped
|
| 215 |
+
def kfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
|
| 216 |
+
r"""
|
| 217 |
+
Returns the elliptic modulus `k`, given any of
|
| 218 |
+
`q, m, k, \tau, \bar{q}`::
|
| 219 |
+
|
| 220 |
+
>>> from mpmath import *
|
| 221 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 222 |
+
>>> kfrom(k=0.25)
|
| 223 |
+
0.25
|
| 224 |
+
>>> kfrom(m=mfrom(k=0.25))
|
| 225 |
+
0.25
|
| 226 |
+
>>> kfrom(q=qfrom(k=0.25))
|
| 227 |
+
0.25
|
| 228 |
+
>>> kfrom(tau=taufrom(k=0.25))
|
| 229 |
+
(0.25 + 0.0j)
|
| 230 |
+
>>> kfrom(qbar=qbarfrom(k=0.25))
|
| 231 |
+
0.25
|
| 232 |
+
|
| 233 |
+
As `q \to 1` and `q \to -1`, `k` rapidly approaches
|
| 234 |
+
`1` and `i \infty` respectively::
|
| 235 |
+
|
| 236 |
+
>>> kfrom(q=0.75)
|
| 237 |
+
0.9999999999999899166471767
|
| 238 |
+
>>> kfrom(q=-0.75)
|
| 239 |
+
(0.0 + 7041781.096692038332790615j)
|
| 240 |
+
>>> kfrom(q=1)
|
| 241 |
+
1
|
| 242 |
+
>>> kfrom(q=-1)
|
| 243 |
+
(0.0 + +infj)
|
| 244 |
+
"""
|
| 245 |
+
if k is not None:
|
| 246 |
+
return ctx.convert(k)
|
| 247 |
+
if m is not None:
|
| 248 |
+
return ctx.sqrt(m)
|
| 249 |
+
if tau is not None:
|
| 250 |
+
q = ctx.expjpi(tau)
|
| 251 |
+
if qbar is not None:
|
| 252 |
+
q = ctx.sqrt(qbar)
|
| 253 |
+
if q == 1:
|
| 254 |
+
return q
|
| 255 |
+
if q == -1:
|
| 256 |
+
return ctx.mpc(0,'inf')
|
| 257 |
+
return (ctx.jtheta(2,0,q)/ctx.jtheta(3,0,q))**2
|
| 258 |
+
|
| 259 |
+
@defun_wrapped
|
| 260 |
+
def mfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
|
| 261 |
+
r"""
|
| 262 |
+
Returns the elliptic parameter `m`, given any of
|
| 263 |
+
`q, m, k, \tau, \bar{q}`::
|
| 264 |
+
|
| 265 |
+
>>> from mpmath import *
|
| 266 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 267 |
+
>>> mfrom(m=0.25)
|
| 268 |
+
0.25
|
| 269 |
+
>>> mfrom(q=qfrom(m=0.25))
|
| 270 |
+
0.25
|
| 271 |
+
>>> mfrom(k=kfrom(m=0.25))
|
| 272 |
+
0.25
|
| 273 |
+
>>> mfrom(tau=taufrom(m=0.25))
|
| 274 |
+
(0.25 + 0.0j)
|
| 275 |
+
>>> mfrom(qbar=qbarfrom(m=0.25))
|
| 276 |
+
0.25
|
| 277 |
+
|
| 278 |
+
As `q \to 1` and `q \to -1`, `m` rapidly approaches
|
| 279 |
+
`1` and `-\infty` respectively::
|
| 280 |
+
|
| 281 |
+
>>> mfrom(q=0.75)
|
| 282 |
+
0.9999999999999798332943533
|
| 283 |
+
>>> mfrom(q=-0.75)
|
| 284 |
+
-49586681013729.32611558353
|
| 285 |
+
>>> mfrom(q=1)
|
| 286 |
+
1.0
|
| 287 |
+
>>> mfrom(q=-1)
|
| 288 |
+
-inf
|
| 289 |
+
|
| 290 |
+
The inverse nome as a function of `q` has an integer
|
| 291 |
+
Taylor series expansion::
|
| 292 |
+
|
| 293 |
+
>>> taylor(lambda q: mfrom(q), 0, 7)
|
| 294 |
+
[0.0, 16.0, -128.0, 704.0, -3072.0, 11488.0, -38400.0, 117632.0]
|
| 295 |
+
|
| 296 |
+
"""
|
| 297 |
+
if m is not None:
|
| 298 |
+
return m
|
| 299 |
+
if k is not None:
|
| 300 |
+
return k**2
|
| 301 |
+
if tau is not None:
|
| 302 |
+
q = ctx.expjpi(tau)
|
| 303 |
+
if qbar is not None:
|
| 304 |
+
q = ctx.sqrt(qbar)
|
| 305 |
+
if q == 1:
|
| 306 |
+
return ctx.convert(q)
|
| 307 |
+
if q == -1:
|
| 308 |
+
return q*ctx.inf
|
| 309 |
+
v = (ctx.jtheta(2,0,q)/ctx.jtheta(3,0,q))**4
|
| 310 |
+
if ctx._is_real_type(q) and q < 0:
|
| 311 |
+
v = v.real
|
| 312 |
+
return v
|
| 313 |
+
|
| 314 |
+
jacobi_spec = {
|
| 315 |
+
'sn' : ([3],[2],[1],[4], 'sin', 'tanh'),
|
| 316 |
+
'cn' : ([4],[2],[2],[4], 'cos', 'sech'),
|
| 317 |
+
'dn' : ([4],[3],[3],[4], '1', 'sech'),
|
| 318 |
+
'ns' : ([2],[3],[4],[1], 'csc', 'coth'),
|
| 319 |
+
'nc' : ([2],[4],[4],[2], 'sec', 'cosh'),
|
| 320 |
+
'nd' : ([3],[4],[4],[3], '1', 'cosh'),
|
| 321 |
+
'sc' : ([3],[4],[1],[2], 'tan', 'sinh'),
|
| 322 |
+
'sd' : ([3,3],[2,4],[1],[3], 'sin', 'sinh'),
|
| 323 |
+
'cd' : ([3],[2],[2],[3], 'cos', '1'),
|
| 324 |
+
'cs' : ([4],[3],[2],[1], 'cot', 'csch'),
|
| 325 |
+
'dc' : ([2],[3],[3],[2], 'sec', '1'),
|
| 326 |
+
'ds' : ([2,4],[3,3],[3],[1], 'csc', 'csch'),
|
| 327 |
+
'cc' : None,
|
| 328 |
+
'ss' : None,
|
| 329 |
+
'nn' : None,
|
| 330 |
+
'dd' : None
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
@defun
|
| 334 |
+
def ellipfun(ctx, kind, u=None, m=None, q=None, k=None, tau=None):
|
| 335 |
+
try:
|
| 336 |
+
S = jacobi_spec[kind]
|
| 337 |
+
except KeyError:
|
| 338 |
+
raise ValueError("First argument must be a two-character string "
|
| 339 |
+
"containing 's', 'c', 'd' or 'n', e.g.: 'sn'")
|
| 340 |
+
if u is None:
|
| 341 |
+
def f(*args, **kwargs):
|
| 342 |
+
return ctx.ellipfun(kind, *args, **kwargs)
|
| 343 |
+
f.__name__ = kind
|
| 344 |
+
return f
|
| 345 |
+
prec = ctx.prec
|
| 346 |
+
try:
|
| 347 |
+
ctx.prec += 10
|
| 348 |
+
u = ctx.convert(u)
|
| 349 |
+
q = ctx.qfrom(m=m, q=q, k=k, tau=tau)
|
| 350 |
+
if S is None:
|
| 351 |
+
v = ctx.one + 0*q*u
|
| 352 |
+
elif q == ctx.zero:
|
| 353 |
+
if S[4] == '1': v = ctx.one
|
| 354 |
+
else: v = getattr(ctx, S[4])(u)
|
| 355 |
+
v += 0*q*u
|
| 356 |
+
elif q == ctx.one:
|
| 357 |
+
if S[5] == '1': v = ctx.one
|
| 358 |
+
else: v = getattr(ctx, S[5])(u)
|
| 359 |
+
v += 0*q*u
|
| 360 |
+
else:
|
| 361 |
+
t = u / ctx.jtheta(3, 0, q)**2
|
| 362 |
+
v = ctx.one
|
| 363 |
+
for a in S[0]: v *= ctx.jtheta(a, 0, q)
|
| 364 |
+
for b in S[1]: v /= ctx.jtheta(b, 0, q)
|
| 365 |
+
for c in S[2]: v *= ctx.jtheta(c, t, q)
|
| 366 |
+
for d in S[3]: v /= ctx.jtheta(d, t, q)
|
| 367 |
+
finally:
|
| 368 |
+
ctx.prec = prec
|
| 369 |
+
return +v
|
| 370 |
+
|
| 371 |
+
@defun_wrapped
|
| 372 |
+
def kleinj(ctx, tau=None, **kwargs):
|
| 373 |
+
r"""
|
| 374 |
+
Evaluates the Klein j-invariant, which is a modular function defined for
|
| 375 |
+
`\tau` in the upper half-plane as
|
| 376 |
+
|
| 377 |
+
.. math ::
|
| 378 |
+
|
| 379 |
+
J(\tau) = \frac{g_2^3(\tau)}{g_2^3(\tau) - 27 g_3^2(\tau)}
|
| 380 |
+
|
| 381 |
+
where `g_2` and `g_3` are the modular invariants of the Weierstrass
|
| 382 |
+
elliptic function,
|
| 383 |
+
|
| 384 |
+
.. math ::
|
| 385 |
+
|
| 386 |
+
g_2(\tau) = 60 \sum_{(m,n) \in \mathbb{Z}^2 \setminus (0,0)} (m \tau+n)^{-4}
|
| 387 |
+
|
| 388 |
+
g_3(\tau) = 140 \sum_{(m,n) \in \mathbb{Z}^2 \setminus (0,0)} (m \tau+n)^{-6}.
|
| 389 |
+
|
| 390 |
+
An alternative, common notation is that of the j-function
|
| 391 |
+
`j(\tau) = 1728 J(\tau)`.
|
| 392 |
+
|
| 393 |
+
**Plots**
|
| 394 |
+
|
| 395 |
+
.. literalinclude :: /plots/kleinj.py
|
| 396 |
+
.. image :: /plots/kleinj.png
|
| 397 |
+
.. literalinclude :: /plots/kleinj2.py
|
| 398 |
+
.. image :: /plots/kleinj2.png
|
| 399 |
+
|
| 400 |
+
**Examples**
|
| 401 |
+
|
| 402 |
+
Verifying the functional equation `J(\tau) = J(\tau+1) = J(-\tau^{-1})`::
|
| 403 |
+
|
| 404 |
+
>>> from mpmath import *
|
| 405 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 406 |
+
>>> tau = 0.625+0.75*j
|
| 407 |
+
>>> tau = 0.625+0.75*j
|
| 408 |
+
>>> kleinj(tau)
|
| 409 |
+
(-0.1507492166511182267125242 + 0.07595948379084571927228948j)
|
| 410 |
+
>>> kleinj(tau+1)
|
| 411 |
+
(-0.1507492166511182267125242 + 0.07595948379084571927228948j)
|
| 412 |
+
>>> kleinj(-1/tau)
|
| 413 |
+
(-0.1507492166511182267125242 + 0.07595948379084571927228946j)
|
| 414 |
+
|
| 415 |
+
The j-function has a famous Laurent series expansion in terms of the nome
|
| 416 |
+
`\bar{q}`, `j(\tau) = \bar{q}^{-1} + 744 + 196884\bar{q} + \ldots`::
|
| 417 |
+
|
| 418 |
+
>>> mp.dps = 15
|
| 419 |
+
>>> taylor(lambda q: 1728*q*kleinj(qbar=q), 0, 5, singular=True)
|
| 420 |
+
[1.0, 744.0, 196884.0, 21493760.0, 864299970.0, 20245856256.0]
|
| 421 |
+
|
| 422 |
+
The j-function admits exact evaluation at special algebraic points
|
| 423 |
+
related to the Heegner numbers 1, 2, 3, 7, 11, 19, 43, 67, 163::
|
| 424 |
+
|
| 425 |
+
>>> @extraprec(10)
|
| 426 |
+
... def h(n):
|
| 427 |
+
... v = (1+sqrt(n)*j)
|
| 428 |
+
... if n > 2:
|
| 429 |
+
... v *= 0.5
|
| 430 |
+
... return v
|
| 431 |
+
...
|
| 432 |
+
>>> mp.dps = 25
|
| 433 |
+
>>> for n in [1,2,3,7,11,19,43,67,163]:
|
| 434 |
+
... n, chop(1728*kleinj(h(n)))
|
| 435 |
+
...
|
| 436 |
+
(1, 1728.0)
|
| 437 |
+
(2, 8000.0)
|
| 438 |
+
(3, 0.0)
|
| 439 |
+
(7, -3375.0)
|
| 440 |
+
(11, -32768.0)
|
| 441 |
+
(19, -884736.0)
|
| 442 |
+
(43, -884736000.0)
|
| 443 |
+
(67, -147197952000.0)
|
| 444 |
+
(163, -262537412640768000.0)
|
| 445 |
+
|
| 446 |
+
Also at other special points, the j-function assumes explicit
|
| 447 |
+
algebraic values, e.g.::
|
| 448 |
+
|
| 449 |
+
>>> chop(1728*kleinj(j*sqrt(5)))
|
| 450 |
+
1264538.909475140509320227
|
| 451 |
+
>>> identify(cbrt(_)) # note: not simplified
|
| 452 |
+
'((100+sqrt(13520))/2)'
|
| 453 |
+
>>> (50+26*sqrt(5))**3
|
| 454 |
+
1264538.909475140509320227
|
| 455 |
+
|
| 456 |
+
"""
|
| 457 |
+
q = ctx.qfrom(tau=tau, **kwargs)
|
| 458 |
+
t2 = ctx.jtheta(2,0,q)
|
| 459 |
+
t3 = ctx.jtheta(3,0,q)
|
| 460 |
+
t4 = ctx.jtheta(4,0,q)
|
| 461 |
+
P = (t2**8 + t3**8 + t4**8)**3
|
| 462 |
+
Q = 54*(t2*t3*t4)**8
|
| 463 |
+
return P/Q
|
| 464 |
+
|
| 465 |
+
|
| 466 |
+
def RF_calc(ctx, x, y, z, r):
|
| 467 |
+
if y == z: return RC_calc(ctx, x, y, r)
|
| 468 |
+
if x == z: return RC_calc(ctx, y, x, r)
|
| 469 |
+
if x == y: return RC_calc(ctx, z, x, r)
|
| 470 |
+
if not (ctx.isnormal(x) and ctx.isnormal(y) and ctx.isnormal(z)):
|
| 471 |
+
if ctx.isnan(x) or ctx.isnan(y) or ctx.isnan(z):
|
| 472 |
+
return x*y*z
|
| 473 |
+
if ctx.isinf(x) or ctx.isinf(y) or ctx.isinf(z):
|
| 474 |
+
return ctx.zero
|
| 475 |
+
xm,ym,zm = x,y,z
|
| 476 |
+
A0 = Am = (x+y+z)/3
|
| 477 |
+
Q = ctx.root(3*r, -6) * max(abs(A0-x),abs(A0-y),abs(A0-z))
|
| 478 |
+
g = ctx.mpf(0.25)
|
| 479 |
+
pow4 = ctx.one
|
| 480 |
+
while 1:
|
| 481 |
+
xs = ctx.sqrt(xm)
|
| 482 |
+
ys = ctx.sqrt(ym)
|
| 483 |
+
zs = ctx.sqrt(zm)
|
| 484 |
+
lm = xs*ys + xs*zs + ys*zs
|
| 485 |
+
Am1 = (Am+lm)*g
|
| 486 |
+
xm, ym, zm = (xm+lm)*g, (ym+lm)*g, (zm+lm)*g
|
| 487 |
+
if pow4 * Q < abs(Am):
|
| 488 |
+
break
|
| 489 |
+
Am = Am1
|
| 490 |
+
pow4 *= g
|
| 491 |
+
t = pow4/Am
|
| 492 |
+
X = (A0-x)*t
|
| 493 |
+
Y = (A0-y)*t
|
| 494 |
+
Z = -X-Y
|
| 495 |
+
E2 = X*Y-Z**2
|
| 496 |
+
E3 = X*Y*Z
|
| 497 |
+
return ctx.power(Am,-0.5) * (9240-924*E2+385*E2**2+660*E3-630*E2*E3)/9240
|
| 498 |
+
|
| 499 |
+
def RC_calc(ctx, x, y, r, pv=True):
|
| 500 |
+
if not (ctx.isnormal(x) and ctx.isnormal(y)):
|
| 501 |
+
if ctx.isinf(x) or ctx.isinf(y):
|
| 502 |
+
return 1/(x*y)
|
| 503 |
+
if y == 0:
|
| 504 |
+
return ctx.inf
|
| 505 |
+
if x == 0:
|
| 506 |
+
return ctx.pi / ctx.sqrt(y) / 2
|
| 507 |
+
raise ValueError
|
| 508 |
+
# Cauchy principal value
|
| 509 |
+
if pv and ctx._im(y) == 0 and ctx._re(y) < 0:
|
| 510 |
+
return ctx.sqrt(x/(x-y)) * RC_calc(ctx, x-y, -y, r)
|
| 511 |
+
if x == y:
|
| 512 |
+
return 1/ctx.sqrt(x)
|
| 513 |
+
extraprec = 2*max(0,-ctx.mag(x-y)+ctx.mag(x))
|
| 514 |
+
ctx.prec += extraprec
|
| 515 |
+
if ctx._is_real_type(x) and ctx._is_real_type(y):
|
| 516 |
+
x = ctx._re(x)
|
| 517 |
+
y = ctx._re(y)
|
| 518 |
+
a = ctx.sqrt(x/y)
|
| 519 |
+
if x < y:
|
| 520 |
+
b = ctx.sqrt(y-x)
|
| 521 |
+
v = ctx.acos(a)/b
|
| 522 |
+
else:
|
| 523 |
+
b = ctx.sqrt(x-y)
|
| 524 |
+
v = ctx.acosh(a)/b
|
| 525 |
+
else:
|
| 526 |
+
sx = ctx.sqrt(x)
|
| 527 |
+
sy = ctx.sqrt(y)
|
| 528 |
+
v = ctx.acos(sx/sy)/(ctx.sqrt((1-x/y))*sy)
|
| 529 |
+
ctx.prec -= extraprec
|
| 530 |
+
return v
|
| 531 |
+
|
| 532 |
+
def RJ_calc(ctx, x, y, z, p, r, integration):
|
| 533 |
+
"""
|
| 534 |
+
With integration == 0, computes RJ only using Carlson's algorithm
|
| 535 |
+
(may be wrong for some values).
|
| 536 |
+
With integration == 1, uses an initial integration to make sure
|
| 537 |
+
Carlson's algorithm is correct.
|
| 538 |
+
With integration == 2, uses only integration.
|
| 539 |
+
"""
|
| 540 |
+
if not (ctx.isnormal(x) and ctx.isnormal(y) and \
|
| 541 |
+
ctx.isnormal(z) and ctx.isnormal(p)):
|
| 542 |
+
if ctx.isnan(x) or ctx.isnan(y) or ctx.isnan(z) or ctx.isnan(p):
|
| 543 |
+
return x*y*z
|
| 544 |
+
if ctx.isinf(x) or ctx.isinf(y) or ctx.isinf(z) or ctx.isinf(p):
|
| 545 |
+
return ctx.zero
|
| 546 |
+
if not p:
|
| 547 |
+
return ctx.inf
|
| 548 |
+
if (not x) + (not y) + (not z) > 1:
|
| 549 |
+
return ctx.inf
|
| 550 |
+
# Check conditions and fall back on integration for argument
|
| 551 |
+
# reduction if needed. The following conditions might be needlessly
|
| 552 |
+
# restrictive.
|
| 553 |
+
initial_integral = ctx.zero
|
| 554 |
+
if integration >= 1:
|
| 555 |
+
ok = (x.real >= 0 and y.real >= 0 and z.real >= 0 and p.real > 0)
|
| 556 |
+
if not ok:
|
| 557 |
+
if x == p or y == p or z == p:
|
| 558 |
+
ok = True
|
| 559 |
+
if not ok:
|
| 560 |
+
if p.imag != 0 or p.real >= 0:
|
| 561 |
+
if (x.imag == 0 and x.real >= 0 and ctx.conj(y) == z):
|
| 562 |
+
ok = True
|
| 563 |
+
if (y.imag == 0 and y.real >= 0 and ctx.conj(x) == z):
|
| 564 |
+
ok = True
|
| 565 |
+
if (z.imag == 0 and z.real >= 0 and ctx.conj(x) == y):
|
| 566 |
+
ok = True
|
| 567 |
+
if not ok or (integration == 2):
|
| 568 |
+
N = ctx.ceil(-min(x.real, y.real, z.real, p.real)) + 1
|
| 569 |
+
# Integrate around any singularities
|
| 570 |
+
if all((t.imag >= 0 or t.real > 0) for t in [x, y, z, p]):
|
| 571 |
+
margin = ctx.j
|
| 572 |
+
elif all((t.imag < 0 or t.real > 0) for t in [x, y, z, p]):
|
| 573 |
+
margin = -ctx.j
|
| 574 |
+
else:
|
| 575 |
+
margin = 1
|
| 576 |
+
# Go through the upper half-plane, but low enough that any
|
| 577 |
+
# parameter starting in the lower plane doesn't cross the
|
| 578 |
+
# branch cut
|
| 579 |
+
for t in [x, y, z, p]:
|
| 580 |
+
if t.imag >= 0 or t.real > 0:
|
| 581 |
+
continue
|
| 582 |
+
margin = min(margin, abs(t.imag) * 0.5)
|
| 583 |
+
margin *= ctx.j
|
| 584 |
+
N += margin
|
| 585 |
+
F = lambda t: 1/(ctx.sqrt(t+x)*ctx.sqrt(t+y)*ctx.sqrt(t+z)*(t+p))
|
| 586 |
+
if integration == 2:
|
| 587 |
+
return 1.5 * ctx.quadsubdiv(F, [0, N, ctx.inf])
|
| 588 |
+
initial_integral = 1.5 * ctx.quadsubdiv(F, [0, N])
|
| 589 |
+
x += N; y += N; z += N; p += N
|
| 590 |
+
xm,ym,zm,pm = x,y,z,p
|
| 591 |
+
A0 = Am = (x + y + z + 2*p)/5
|
| 592 |
+
delta = (p-x)*(p-y)*(p-z)
|
| 593 |
+
Q = ctx.root(0.25*r, -6) * max(abs(A0-x),abs(A0-y),abs(A0-z),abs(A0-p))
|
| 594 |
+
g = ctx.mpf(0.25)
|
| 595 |
+
pow4 = ctx.one
|
| 596 |
+
S = 0
|
| 597 |
+
while 1:
|
| 598 |
+
sx = ctx.sqrt(xm)
|
| 599 |
+
sy = ctx.sqrt(ym)
|
| 600 |
+
sz = ctx.sqrt(zm)
|
| 601 |
+
sp = ctx.sqrt(pm)
|
| 602 |
+
lm = sx*sy + sx*sz + sy*sz
|
| 603 |
+
Am1 = (Am+lm)*g
|
| 604 |
+
xm = (xm+lm)*g; ym = (ym+lm)*g; zm = (zm+lm)*g; pm = (pm+lm)*g
|
| 605 |
+
dm = (sp+sx) * (sp+sy) * (sp+sz)
|
| 606 |
+
em = delta * pow4**3 / dm**2
|
| 607 |
+
if pow4 * Q < abs(Am):
|
| 608 |
+
break
|
| 609 |
+
T = RC_calc(ctx, ctx.one, ctx.one+em, r) * pow4 / dm
|
| 610 |
+
S += T
|
| 611 |
+
pow4 *= g
|
| 612 |
+
Am = Am1
|
| 613 |
+
t = pow4 / Am
|
| 614 |
+
X = (A0-x)*t
|
| 615 |
+
Y = (A0-y)*t
|
| 616 |
+
Z = (A0-z)*t
|
| 617 |
+
P = (-X-Y-Z)/2
|
| 618 |
+
E2 = X*Y + X*Z + Y*Z - 3*P**2
|
| 619 |
+
E3 = X*Y*Z + 2*E2*P + 4*P**3
|
| 620 |
+
E4 = (2*X*Y*Z + E2*P + 3*P**3)*P
|
| 621 |
+
E5 = X*Y*Z*P**2
|
| 622 |
+
P = 24024 - 5148*E2 + 2457*E2**2 + 4004*E3 - 4158*E2*E3 - 3276*E4 + 2772*E5
|
| 623 |
+
Q = 24024
|
| 624 |
+
v1 = pow4 * ctx.power(Am, -1.5) * P/Q
|
| 625 |
+
v2 = 6*S
|
| 626 |
+
return initial_integral + v1 + v2
|
| 627 |
+
|
| 628 |
+
@defun
|
| 629 |
+
def elliprf(ctx, x, y, z):
|
| 630 |
+
r"""
|
| 631 |
+
Evaluates the Carlson symmetric elliptic integral of the first kind
|
| 632 |
+
|
| 633 |
+
.. math ::
|
| 634 |
+
|
| 635 |
+
R_F(x,y,z) = \frac{1}{2}
|
| 636 |
+
\int_0^{\infty} \frac{dt}{\sqrt{(t+x)(t+y)(t+z)}}
|
| 637 |
+
|
| 638 |
+
which is defined for `x,y,z \notin (-\infty,0)`, and with
|
| 639 |
+
at most one of `x,y,z` being zero.
|
| 640 |
+
|
| 641 |
+
For real `x,y,z \ge 0`, the principal square root is taken in the integrand.
|
| 642 |
+
For complex `x,y,z`, the principal square root is taken as `t \to \infty`
|
| 643 |
+
and as `t \to 0` non-principal branches are chosen as necessary so as to
|
| 644 |
+
make the integrand continuous.
|
| 645 |
+
|
| 646 |
+
**Examples**
|
| 647 |
+
|
| 648 |
+
Some basic values and limits::
|
| 649 |
+
|
| 650 |
+
>>> from mpmath import *
|
| 651 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 652 |
+
>>> elliprf(0,1,1); pi/2
|
| 653 |
+
1.570796326794896619231322
|
| 654 |
+
1.570796326794896619231322
|
| 655 |
+
>>> elliprf(0,1,inf)
|
| 656 |
+
0.0
|
| 657 |
+
>>> elliprf(1,1,1)
|
| 658 |
+
1.0
|
| 659 |
+
>>> elliprf(2,2,2)**2
|
| 660 |
+
0.5
|
| 661 |
+
>>> elliprf(1,0,0); elliprf(0,0,1); elliprf(0,1,0); elliprf(0,0,0)
|
| 662 |
+
+inf
|
| 663 |
+
+inf
|
| 664 |
+
+inf
|
| 665 |
+
+inf
|
| 666 |
+
|
| 667 |
+
Representing complete elliptic integrals in terms of `R_F`::
|
| 668 |
+
|
| 669 |
+
>>> m = mpf(0.75)
|
| 670 |
+
>>> ellipk(m); elliprf(0,1-m,1)
|
| 671 |
+
2.156515647499643235438675
|
| 672 |
+
2.156515647499643235438675
|
| 673 |
+
>>> ellipe(m); elliprf(0,1-m,1)-m*elliprd(0,1-m,1)/3
|
| 674 |
+
1.211056027568459524803563
|
| 675 |
+
1.211056027568459524803563
|
| 676 |
+
|
| 677 |
+
Some symmetries and argument transformations::
|
| 678 |
+
|
| 679 |
+
>>> x,y,z = 2,3,4
|
| 680 |
+
>>> elliprf(x,y,z); elliprf(y,x,z); elliprf(z,y,x)
|
| 681 |
+
0.5840828416771517066928492
|
| 682 |
+
0.5840828416771517066928492
|
| 683 |
+
0.5840828416771517066928492
|
| 684 |
+
>>> k = mpf(100000)
|
| 685 |
+
>>> elliprf(k*x,k*y,k*z); k**(-0.5) * elliprf(x,y,z)
|
| 686 |
+
0.001847032121923321253219284
|
| 687 |
+
0.001847032121923321253219284
|
| 688 |
+
>>> l = sqrt(x*y) + sqrt(y*z) + sqrt(z*x)
|
| 689 |
+
>>> elliprf(x,y,z); 2*elliprf(x+l,y+l,z+l)
|
| 690 |
+
0.5840828416771517066928492
|
| 691 |
+
0.5840828416771517066928492
|
| 692 |
+
>>> elliprf((x+l)/4,(y+l)/4,(z+l)/4)
|
| 693 |
+
0.5840828416771517066928492
|
| 694 |
+
|
| 695 |
+
Comparing with numerical integration::
|
| 696 |
+
|
| 697 |
+
>>> x,y,z = 2,3,4
|
| 698 |
+
>>> elliprf(x,y,z)
|
| 699 |
+
0.5840828416771517066928492
|
| 700 |
+
>>> f = lambda t: 0.5*((t+x)*(t+y)*(t+z))**(-0.5)
|
| 701 |
+
>>> q = extradps(25)(quad)
|
| 702 |
+
>>> q(f, [0,inf])
|
| 703 |
+
0.5840828416771517066928492
|
| 704 |
+
|
| 705 |
+
With the following arguments, the square root in the integrand becomes
|
| 706 |
+
discontinuous at `t = 1/2` if the principal branch is used. To obtain
|
| 707 |
+
the right value, `-\sqrt{r}` must be taken instead of `\sqrt{r}`
|
| 708 |
+
on `t \in (0, 1/2)`::
|
| 709 |
+
|
| 710 |
+
>>> x,y,z = j-1,j,0
|
| 711 |
+
>>> elliprf(x,y,z)
|
| 712 |
+
(0.7961258658423391329305694 - 1.213856669836495986430094j)
|
| 713 |
+
>>> -q(f, [0,0.5]) + q(f, [0.5,inf])
|
| 714 |
+
(0.7961258658423391329305694 - 1.213856669836495986430094j)
|
| 715 |
+
|
| 716 |
+
The so-called *first lemniscate constant*, a transcendental number::
|
| 717 |
+
|
| 718 |
+
>>> elliprf(0,1,2)
|
| 719 |
+
1.31102877714605990523242
|
| 720 |
+
>>> extradps(25)(quad)(lambda t: 1/sqrt(1-t**4), [0,1])
|
| 721 |
+
1.31102877714605990523242
|
| 722 |
+
>>> gamma('1/4')**2/(4*sqrt(2*pi))
|
| 723 |
+
1.31102877714605990523242
|
| 724 |
+
|
| 725 |
+
**References**
|
| 726 |
+
|
| 727 |
+
1. [Carlson]_
|
| 728 |
+
2. [DLMF]_ Chapter 19. Elliptic Integrals
|
| 729 |
+
|
| 730 |
+
"""
|
| 731 |
+
x = ctx.convert(x)
|
| 732 |
+
y = ctx.convert(y)
|
| 733 |
+
z = ctx.convert(z)
|
| 734 |
+
prec = ctx.prec
|
| 735 |
+
try:
|
| 736 |
+
ctx.prec += 20
|
| 737 |
+
tol = ctx.eps * 2**10
|
| 738 |
+
v = RF_calc(ctx, x, y, z, tol)
|
| 739 |
+
finally:
|
| 740 |
+
ctx.prec = prec
|
| 741 |
+
return +v
|
| 742 |
+
|
| 743 |
+
@defun
|
| 744 |
+
def elliprc(ctx, x, y, pv=True):
|
| 745 |
+
r"""
|
| 746 |
+
Evaluates the degenerate Carlson symmetric elliptic integral
|
| 747 |
+
of the first kind
|
| 748 |
+
|
| 749 |
+
.. math ::
|
| 750 |
+
|
| 751 |
+
R_C(x,y) = R_F(x,y,y) =
|
| 752 |
+
\frac{1}{2} \int_0^{\infty} \frac{dt}{(t+y) \sqrt{(t+x)}}.
|
| 753 |
+
|
| 754 |
+
If `y \in (-\infty,0)`, either a value defined by continuity,
|
| 755 |
+
or with *pv=True* the Cauchy principal value, can be computed.
|
| 756 |
+
|
| 757 |
+
If `x \ge 0, y > 0`, the value can be expressed in terms of
|
| 758 |
+
elementary functions as
|
| 759 |
+
|
| 760 |
+
.. math ::
|
| 761 |
+
|
| 762 |
+
R_C(x,y) =
|
| 763 |
+
\begin{cases}
|
| 764 |
+
\dfrac{1}{\sqrt{y-x}}
|
| 765 |
+
\cos^{-1}\left(\sqrt{\dfrac{x}{y}}\right), & x < y \\
|
| 766 |
+
\dfrac{1}{\sqrt{y}}, & x = y \\
|
| 767 |
+
\dfrac{1}{\sqrt{x-y}}
|
| 768 |
+
\cosh^{-1}\left(\sqrt{\dfrac{x}{y}}\right), & x > y \\
|
| 769 |
+
\end{cases}.
|
| 770 |
+
|
| 771 |
+
**Examples**
|
| 772 |
+
|
| 773 |
+
Some special values and limits::
|
| 774 |
+
|
| 775 |
+
>>> from mpmath import *
|
| 776 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 777 |
+
>>> elliprc(1,2)*4; elliprc(0,1)*2; +pi
|
| 778 |
+
3.141592653589793238462643
|
| 779 |
+
3.141592653589793238462643
|
| 780 |
+
3.141592653589793238462643
|
| 781 |
+
>>> elliprc(1,0)
|
| 782 |
+
+inf
|
| 783 |
+
>>> elliprc(5,5)**2
|
| 784 |
+
0.2
|
| 785 |
+
>>> elliprc(1,inf); elliprc(inf,1); elliprc(inf,inf)
|
| 786 |
+
0.0
|
| 787 |
+
0.0
|
| 788 |
+
0.0
|
| 789 |
+
|
| 790 |
+
Comparing with the elementary closed-form solution::
|
| 791 |
+
|
| 792 |
+
>>> elliprc('1/3', '1/5'); sqrt(7.5)*acosh(sqrt('5/3'))
|
| 793 |
+
2.041630778983498390751238
|
| 794 |
+
2.041630778983498390751238
|
| 795 |
+
>>> elliprc('1/5', '1/3'); sqrt(7.5)*acos(sqrt('3/5'))
|
| 796 |
+
1.875180765206547065111085
|
| 797 |
+
1.875180765206547065111085
|
| 798 |
+
|
| 799 |
+
Comparing with numerical integration::
|
| 800 |
+
|
| 801 |
+
>>> q = extradps(25)(quad)
|
| 802 |
+
>>> elliprc(2, -3, pv=True)
|
| 803 |
+
0.3333969101113672670749334
|
| 804 |
+
>>> elliprc(2, -3, pv=False)
|
| 805 |
+
(0.3333969101113672670749334 + 0.7024814731040726393156375j)
|
| 806 |
+
>>> 0.5*q(lambda t: 1/(sqrt(t+2)*(t-3)), [0,3-j,6,inf])
|
| 807 |
+
(0.3333969101113672670749334 + 0.7024814731040726393156375j)
|
| 808 |
+
|
| 809 |
+
"""
|
| 810 |
+
x = ctx.convert(x)
|
| 811 |
+
y = ctx.convert(y)
|
| 812 |
+
prec = ctx.prec
|
| 813 |
+
try:
|
| 814 |
+
ctx.prec += 20
|
| 815 |
+
tol = ctx.eps * 2**10
|
| 816 |
+
v = RC_calc(ctx, x, y, tol, pv)
|
| 817 |
+
finally:
|
| 818 |
+
ctx.prec = prec
|
| 819 |
+
return +v
|
| 820 |
+
|
| 821 |
+
@defun
|
| 822 |
+
def elliprj(ctx, x, y, z, p, integration=1):
|
| 823 |
+
r"""
|
| 824 |
+
Evaluates the Carlson symmetric elliptic integral of the third kind
|
| 825 |
+
|
| 826 |
+
.. math ::
|
| 827 |
+
|
| 828 |
+
R_J(x,y,z,p) = \frac{3}{2}
|
| 829 |
+
\int_0^{\infty} \frac{dt}{(t+p)\sqrt{(t+x)(t+y)(t+z)}}.
|
| 830 |
+
|
| 831 |
+
Like :func:`~mpmath.elliprf`, the branch of the square root in the integrand
|
| 832 |
+
is defined so as to be continuous along the path of integration for
|
| 833 |
+
complex values of the arguments.
|
| 834 |
+
|
| 835 |
+
**Examples**
|
| 836 |
+
|
| 837 |
+
Some values and limits::
|
| 838 |
+
|
| 839 |
+
>>> from mpmath import *
|
| 840 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 841 |
+
>>> elliprj(1,1,1,1)
|
| 842 |
+
1.0
|
| 843 |
+
>>> elliprj(2,2,2,2); 1/(2*sqrt(2))
|
| 844 |
+
0.3535533905932737622004222
|
| 845 |
+
0.3535533905932737622004222
|
| 846 |
+
>>> elliprj(0,1,2,2)
|
| 847 |
+
1.067937989667395702268688
|
| 848 |
+
>>> 3*(2*gamma('5/4')**2-pi**2/gamma('1/4')**2)/(sqrt(2*pi))
|
| 849 |
+
1.067937989667395702268688
|
| 850 |
+
>>> elliprj(0,1,1,2); 3*pi*(2-sqrt(2))/4
|
| 851 |
+
1.380226776765915172432054
|
| 852 |
+
1.380226776765915172432054
|
| 853 |
+
>>> elliprj(1,3,2,0); elliprj(0,1,1,0); elliprj(0,0,0,0)
|
| 854 |
+
+inf
|
| 855 |
+
+inf
|
| 856 |
+
+inf
|
| 857 |
+
>>> elliprj(1,inf,1,0); elliprj(1,1,1,inf)
|
| 858 |
+
0.0
|
| 859 |
+
0.0
|
| 860 |
+
>>> chop(elliprj(1+j, 1-j, 1, 1))
|
| 861 |
+
0.8505007163686739432927844
|
| 862 |
+
|
| 863 |
+
Scale transformation::
|
| 864 |
+
|
| 865 |
+
>>> x,y,z,p = 2,3,4,5
|
| 866 |
+
>>> k = mpf(100000)
|
| 867 |
+
>>> elliprj(k*x,k*y,k*z,k*p); k**(-1.5)*elliprj(x,y,z,p)
|
| 868 |
+
4.521291677592745527851168e-9
|
| 869 |
+
4.521291677592745527851168e-9
|
| 870 |
+
|
| 871 |
+
Comparing with numerical integration::
|
| 872 |
+
|
| 873 |
+
>>> elliprj(1,2,3,4)
|
| 874 |
+
0.2398480997495677621758617
|
| 875 |
+
>>> f = lambda t: 1/((t+4)*sqrt((t+1)*(t+2)*(t+3)))
|
| 876 |
+
>>> 1.5*quad(f, [0,inf])
|
| 877 |
+
0.2398480997495677621758617
|
| 878 |
+
>>> elliprj(1,2+1j,3,4-2j)
|
| 879 |
+
(0.216888906014633498739952 + 0.04081912627366673332369512j)
|
| 880 |
+
>>> f = lambda t: 1/((t+4-2j)*sqrt((t+1)*(t+2+1j)*(t+3)))
|
| 881 |
+
>>> 1.5*quad(f, [0,inf])
|
| 882 |
+
(0.216888906014633498739952 + 0.04081912627366673332369511j)
|
| 883 |
+
|
| 884 |
+
"""
|
| 885 |
+
x = ctx.convert(x)
|
| 886 |
+
y = ctx.convert(y)
|
| 887 |
+
z = ctx.convert(z)
|
| 888 |
+
p = ctx.convert(p)
|
| 889 |
+
prec = ctx.prec
|
| 890 |
+
try:
|
| 891 |
+
ctx.prec += 20
|
| 892 |
+
tol = ctx.eps * 2**10
|
| 893 |
+
v = RJ_calc(ctx, x, y, z, p, tol, integration)
|
| 894 |
+
finally:
|
| 895 |
+
ctx.prec = prec
|
| 896 |
+
return +v
|
| 897 |
+
|
| 898 |
+
@defun
|
| 899 |
+
def elliprd(ctx, x, y, z):
|
| 900 |
+
r"""
|
| 901 |
+
Evaluates the degenerate Carlson symmetric elliptic integral
|
| 902 |
+
of the third kind or Carlson elliptic integral of the
|
| 903 |
+
second kind `R_D(x,y,z) = R_J(x,y,z,z)`.
|
| 904 |
+
|
| 905 |
+
See :func:`~mpmath.elliprj` for additional information.
|
| 906 |
+
|
| 907 |
+
**Examples**
|
| 908 |
+
|
| 909 |
+
>>> from mpmath import *
|
| 910 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 911 |
+
>>> elliprd(1,2,3)
|
| 912 |
+
0.2904602810289906442326534
|
| 913 |
+
>>> elliprj(1,2,3,3)
|
| 914 |
+
0.2904602810289906442326534
|
| 915 |
+
|
| 916 |
+
The so-called *second lemniscate constant*, a transcendental number::
|
| 917 |
+
|
| 918 |
+
>>> elliprd(0,2,1)/3
|
| 919 |
+
0.5990701173677961037199612
|
| 920 |
+
>>> extradps(25)(quad)(lambda t: t**2/sqrt(1-t**4), [0,1])
|
| 921 |
+
0.5990701173677961037199612
|
| 922 |
+
>>> gamma('3/4')**2/sqrt(2*pi)
|
| 923 |
+
0.5990701173677961037199612
|
| 924 |
+
|
| 925 |
+
"""
|
| 926 |
+
return ctx.elliprj(x,y,z,z)
|
| 927 |
+
|
| 928 |
+
@defun
|
| 929 |
+
def elliprg(ctx, x, y, z):
|
| 930 |
+
r"""
|
| 931 |
+
Evaluates the Carlson completely symmetric elliptic integral
|
| 932 |
+
of the second kind
|
| 933 |
+
|
| 934 |
+
.. math ::
|
| 935 |
+
|
| 936 |
+
R_G(x,y,z) = \frac{1}{4} \int_0^{\infty}
|
| 937 |
+
\frac{t}{\sqrt{(t+x)(t+y)(t+z)}}
|
| 938 |
+
\left( \frac{x}{t+x} + \frac{y}{t+y} + \frac{z}{t+z}\right) dt.
|
| 939 |
+
|
| 940 |
+
**Examples**
|
| 941 |
+
|
| 942 |
+
Evaluation for real and complex arguments::
|
| 943 |
+
|
| 944 |
+
>>> from mpmath import *
|
| 945 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 946 |
+
>>> elliprg(0,1,1)*4; +pi
|
| 947 |
+
3.141592653589793238462643
|
| 948 |
+
3.141592653589793238462643
|
| 949 |
+
>>> elliprg(0,0.5,1)
|
| 950 |
+
0.6753219405238377512600874
|
| 951 |
+
>>> chop(elliprg(1+j, 1-j, 2))
|
| 952 |
+
1.172431327676416604532822
|
| 953 |
+
|
| 954 |
+
A double integral that can be evaluated in terms of `R_G`::
|
| 955 |
+
|
| 956 |
+
>>> x,y,z = 2,3,4
|
| 957 |
+
>>> def f(t,u):
|
| 958 |
+
... st = fp.sin(t); ct = fp.cos(t)
|
| 959 |
+
... su = fp.sin(u); cu = fp.cos(u)
|
| 960 |
+
... return (x*(st*cu)**2 + y*(st*su)**2 + z*ct**2)**0.5 * st
|
| 961 |
+
...
|
| 962 |
+
>>> nprint(mpf(fp.quad(f, [0,fp.pi], [0,2*fp.pi])/(4*fp.pi)), 13)
|
| 963 |
+
1.725503028069
|
| 964 |
+
>>> nprint(elliprg(x,y,z), 13)
|
| 965 |
+
1.725503028069
|
| 966 |
+
|
| 967 |
+
"""
|
| 968 |
+
x = ctx.convert(x)
|
| 969 |
+
y = ctx.convert(y)
|
| 970 |
+
z = ctx.convert(z)
|
| 971 |
+
zeros = (not x) + (not y) + (not z)
|
| 972 |
+
if zeros == 3:
|
| 973 |
+
return (x+y+z)*0
|
| 974 |
+
if zeros == 2:
|
| 975 |
+
if x: return 0.5*ctx.sqrt(x)
|
| 976 |
+
if y: return 0.5*ctx.sqrt(y)
|
| 977 |
+
return 0.5*ctx.sqrt(z)
|
| 978 |
+
if zeros == 1:
|
| 979 |
+
if not z:
|
| 980 |
+
x, z = z, x
|
| 981 |
+
def terms():
|
| 982 |
+
T1 = 0.5*z*ctx.elliprf(x,y,z)
|
| 983 |
+
T2 = -0.5*(x-z)*(y-z)*ctx.elliprd(x,y,z)/3
|
| 984 |
+
T3 = 0.5*ctx.sqrt(x)*ctx.sqrt(y)/ctx.sqrt(z)
|
| 985 |
+
return T1,T2,T3
|
| 986 |
+
return ctx.sum_accurately(terms)
|
| 987 |
+
|
| 988 |
+
|
| 989 |
+
@defun_wrapped
|
| 990 |
+
def ellipf(ctx, phi, m):
|
| 991 |
+
r"""
|
| 992 |
+
Evaluates the Legendre incomplete elliptic integral of the first kind
|
| 993 |
+
|
| 994 |
+
.. math ::
|
| 995 |
+
|
| 996 |
+
F(\phi,m) = \int_0^{\phi} \frac{dt}{\sqrt{1-m \sin^2 t}}
|
| 997 |
+
|
| 998 |
+
or equivalently
|
| 999 |
+
|
| 1000 |
+
.. math ::
|
| 1001 |
+
|
| 1002 |
+
F(\phi,m) = \int_0^{\sin \phi}
|
| 1003 |
+
\frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)}.
|
| 1004 |
+
|
| 1005 |
+
The function reduces to a complete elliptic integral of the first kind
|
| 1006 |
+
(see :func:`~mpmath.ellipk`) when `\phi = \frac{\pi}{2}`; that is,
|
| 1007 |
+
|
| 1008 |
+
.. math ::
|
| 1009 |
+
|
| 1010 |
+
F\left(\frac{\pi}{2}, m\right) = K(m).
|
| 1011 |
+
|
| 1012 |
+
In the defining integral, it is assumed that the principal branch
|
| 1013 |
+
of the square root is taken and that the path of integration avoids
|
| 1014 |
+
crossing any branch cuts. Outside `-\pi/2 \le \Re(\phi) \le \pi/2`,
|
| 1015 |
+
the function extends quasi-periodically as
|
| 1016 |
+
|
| 1017 |
+
.. math ::
|
| 1018 |
+
|
| 1019 |
+
F(\phi + n \pi, m) = 2 n K(m) + F(\phi,m), n \in \mathbb{Z}.
|
| 1020 |
+
|
| 1021 |
+
**Plots**
|
| 1022 |
+
|
| 1023 |
+
.. literalinclude :: /plots/ellipf.py
|
| 1024 |
+
.. image :: /plots/ellipf.png
|
| 1025 |
+
|
| 1026 |
+
**Examples**
|
| 1027 |
+
|
| 1028 |
+
Basic values and limits::
|
| 1029 |
+
|
| 1030 |
+
>>> from mpmath import *
|
| 1031 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1032 |
+
>>> ellipf(0,1)
|
| 1033 |
+
0.0
|
| 1034 |
+
>>> ellipf(0,0)
|
| 1035 |
+
0.0
|
| 1036 |
+
>>> ellipf(1,0); ellipf(2+3j,0)
|
| 1037 |
+
1.0
|
| 1038 |
+
(2.0 + 3.0j)
|
| 1039 |
+
>>> ellipf(1,1); log(sec(1)+tan(1))
|
| 1040 |
+
1.226191170883517070813061
|
| 1041 |
+
1.226191170883517070813061
|
| 1042 |
+
>>> ellipf(pi/2, -0.5); ellipk(-0.5)
|
| 1043 |
+
1.415737208425956198892166
|
| 1044 |
+
1.415737208425956198892166
|
| 1045 |
+
>>> ellipf(pi/2+eps, 1); ellipf(-pi/2-eps, 1)
|
| 1046 |
+
+inf
|
| 1047 |
+
+inf
|
| 1048 |
+
>>> ellipf(1.5, 1)
|
| 1049 |
+
3.340677542798311003320813
|
| 1050 |
+
|
| 1051 |
+
Comparing with numerical integration::
|
| 1052 |
+
|
| 1053 |
+
>>> z,m = 0.5, 1.25
|
| 1054 |
+
>>> ellipf(z,m)
|
| 1055 |
+
0.5287219202206327872978255
|
| 1056 |
+
>>> quad(lambda t: (1-m*sin(t)**2)**(-0.5), [0,z])
|
| 1057 |
+
0.5287219202206327872978255
|
| 1058 |
+
|
| 1059 |
+
The arguments may be complex numbers::
|
| 1060 |
+
|
| 1061 |
+
>>> ellipf(3j, 0.5)
|
| 1062 |
+
(0.0 + 1.713602407841590234804143j)
|
| 1063 |
+
>>> ellipf(3+4j, 5-6j)
|
| 1064 |
+
(1.269131241950351323305741 - 0.3561052815014558335412538j)
|
| 1065 |
+
>>> z,m = 2+3j, 1.25
|
| 1066 |
+
>>> k = 1011
|
| 1067 |
+
>>> ellipf(z+pi*k,m); ellipf(z,m) + 2*k*ellipk(m)
|
| 1068 |
+
(4086.184383622179764082821 - 3003.003538923749396546871j)
|
| 1069 |
+
(4086.184383622179764082821 - 3003.003538923749396546871j)
|
| 1070 |
+
|
| 1071 |
+
For `|\Re(z)| < \pi/2`, the function can be expressed as a
|
| 1072 |
+
hypergeometric series of two variables
|
| 1073 |
+
(see :func:`~mpmath.appellf1`)::
|
| 1074 |
+
|
| 1075 |
+
>>> z,m = 0.5, 0.25
|
| 1076 |
+
>>> ellipf(z,m)
|
| 1077 |
+
0.5050887275786480788831083
|
| 1078 |
+
>>> sin(z)*appellf1(0.5,0.5,0.5,1.5,sin(z)**2,m*sin(z)**2)
|
| 1079 |
+
0.5050887275786480788831083
|
| 1080 |
+
|
| 1081 |
+
"""
|
| 1082 |
+
z = phi
|
| 1083 |
+
if not (ctx.isnormal(z) and ctx.isnormal(m)):
|
| 1084 |
+
if m == 0:
|
| 1085 |
+
return z + m
|
| 1086 |
+
if z == 0:
|
| 1087 |
+
return z * m
|
| 1088 |
+
if m == ctx.inf or m == ctx.ninf: return z/m
|
| 1089 |
+
raise ValueError
|
| 1090 |
+
x = z.real
|
| 1091 |
+
ctx.prec += max(0, ctx.mag(x))
|
| 1092 |
+
pi = +ctx.pi
|
| 1093 |
+
away = abs(x) > pi/2
|
| 1094 |
+
if m == 1:
|
| 1095 |
+
if away:
|
| 1096 |
+
return ctx.inf
|
| 1097 |
+
if away:
|
| 1098 |
+
d = ctx.nint(x/pi)
|
| 1099 |
+
z = z-pi*d
|
| 1100 |
+
P = 2*d*ctx.ellipk(m)
|
| 1101 |
+
else:
|
| 1102 |
+
P = 0
|
| 1103 |
+
c, s = ctx.cos_sin(z)
|
| 1104 |
+
return s * ctx.elliprf(c**2, 1-m*s**2, 1) + P
|
| 1105 |
+
|
| 1106 |
+
@defun_wrapped
|
| 1107 |
+
def ellipe(ctx, *args):
|
| 1108 |
+
r"""
|
| 1109 |
+
Called with a single argument `m`, evaluates the Legendre complete
|
| 1110 |
+
elliptic integral of the second kind, `E(m)`, defined by
|
| 1111 |
+
|
| 1112 |
+
.. math :: E(m) = \int_0^{\pi/2} \sqrt{1-m \sin^2 t} \, dt \,=\,
|
| 1113 |
+
\frac{\pi}{2}
|
| 1114 |
+
\,_2F_1\left(\frac{1}{2}, -\frac{1}{2}, 1, m\right).
|
| 1115 |
+
|
| 1116 |
+
Called with two arguments `\phi, m`, evaluates the incomplete elliptic
|
| 1117 |
+
integral of the second kind
|
| 1118 |
+
|
| 1119 |
+
.. math ::
|
| 1120 |
+
|
| 1121 |
+
E(\phi,m) = \int_0^{\phi} \sqrt{1-m \sin^2 t} \, dt =
|
| 1122 |
+
\int_0^{\sin z}
|
| 1123 |
+
\frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt.
|
| 1124 |
+
|
| 1125 |
+
The incomplete integral reduces to a complete integral when
|
| 1126 |
+
`\phi = \frac{\pi}{2}`; that is,
|
| 1127 |
+
|
| 1128 |
+
.. math ::
|
| 1129 |
+
|
| 1130 |
+
E\left(\frac{\pi}{2}, m\right) = E(m).
|
| 1131 |
+
|
| 1132 |
+
In the defining integral, it is assumed that the principal branch
|
| 1133 |
+
of the square root is taken and that the path of integration avoids
|
| 1134 |
+
crossing any branch cuts. Outside `-\pi/2 \le \Re(z) \le \pi/2`,
|
| 1135 |
+
the function extends quasi-periodically as
|
| 1136 |
+
|
| 1137 |
+
.. math ::
|
| 1138 |
+
|
| 1139 |
+
E(\phi + n \pi, m) = 2 n E(m) + E(\phi,m), n \in \mathbb{Z}.
|
| 1140 |
+
|
| 1141 |
+
**Plots**
|
| 1142 |
+
|
| 1143 |
+
.. literalinclude :: /plots/ellipe.py
|
| 1144 |
+
.. image :: /plots/ellipe.png
|
| 1145 |
+
|
| 1146 |
+
**Examples for the complete integral**
|
| 1147 |
+
|
| 1148 |
+
Basic values and limits::
|
| 1149 |
+
|
| 1150 |
+
>>> from mpmath import *
|
| 1151 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1152 |
+
>>> ellipe(0)
|
| 1153 |
+
1.570796326794896619231322
|
| 1154 |
+
>>> ellipe(1)
|
| 1155 |
+
1.0
|
| 1156 |
+
>>> ellipe(-1)
|
| 1157 |
+
1.910098894513856008952381
|
| 1158 |
+
>>> ellipe(2)
|
| 1159 |
+
(0.5990701173677961037199612 + 0.5990701173677961037199612j)
|
| 1160 |
+
>>> ellipe(inf)
|
| 1161 |
+
(0.0 + +infj)
|
| 1162 |
+
>>> ellipe(-inf)
|
| 1163 |
+
+inf
|
| 1164 |
+
|
| 1165 |
+
Verifying the defining integral and hypergeometric
|
| 1166 |
+
representation::
|
| 1167 |
+
|
| 1168 |
+
>>> ellipe(0.5)
|
| 1169 |
+
1.350643881047675502520175
|
| 1170 |
+
>>> quad(lambda t: sqrt(1-0.5*sin(t)**2), [0, pi/2])
|
| 1171 |
+
1.350643881047675502520175
|
| 1172 |
+
>>> pi/2*hyp2f1(0.5,-0.5,1,0.5)
|
| 1173 |
+
1.350643881047675502520175
|
| 1174 |
+
|
| 1175 |
+
Evaluation is supported for arbitrary complex `m`::
|
| 1176 |
+
|
| 1177 |
+
>>> ellipe(0.5+0.25j)
|
| 1178 |
+
(1.360868682163129682716687 - 0.1238733442561786843557315j)
|
| 1179 |
+
>>> ellipe(3+4j)
|
| 1180 |
+
(1.499553520933346954333612 - 1.577879007912758274533309j)
|
| 1181 |
+
|
| 1182 |
+
A definite integral::
|
| 1183 |
+
|
| 1184 |
+
>>> quad(ellipe, [0,1])
|
| 1185 |
+
1.333333333333333333333333
|
| 1186 |
+
|
| 1187 |
+
**Examples for the incomplete integral**
|
| 1188 |
+
|
| 1189 |
+
Basic values and limits::
|
| 1190 |
+
|
| 1191 |
+
>>> ellipe(0,1)
|
| 1192 |
+
0.0
|
| 1193 |
+
>>> ellipe(0,0)
|
| 1194 |
+
0.0
|
| 1195 |
+
>>> ellipe(1,0)
|
| 1196 |
+
1.0
|
| 1197 |
+
>>> ellipe(2+3j,0)
|
| 1198 |
+
(2.0 + 3.0j)
|
| 1199 |
+
>>> ellipe(1,1); sin(1)
|
| 1200 |
+
0.8414709848078965066525023
|
| 1201 |
+
0.8414709848078965066525023
|
| 1202 |
+
>>> ellipe(pi/2, -0.5); ellipe(-0.5)
|
| 1203 |
+
1.751771275694817862026502
|
| 1204 |
+
1.751771275694817862026502
|
| 1205 |
+
>>> ellipe(pi/2, 1); ellipe(-pi/2, 1)
|
| 1206 |
+
1.0
|
| 1207 |
+
-1.0
|
| 1208 |
+
>>> ellipe(1.5, 1)
|
| 1209 |
+
0.9974949866040544309417234
|
| 1210 |
+
|
| 1211 |
+
Comparing with numerical integration::
|
| 1212 |
+
|
| 1213 |
+
>>> z,m = 0.5, 1.25
|
| 1214 |
+
>>> ellipe(z,m)
|
| 1215 |
+
0.4740152182652628394264449
|
| 1216 |
+
>>> quad(lambda t: sqrt(1-m*sin(t)**2), [0,z])
|
| 1217 |
+
0.4740152182652628394264449
|
| 1218 |
+
|
| 1219 |
+
The arguments may be complex numbers::
|
| 1220 |
+
|
| 1221 |
+
>>> ellipe(3j, 0.5)
|
| 1222 |
+
(0.0 + 7.551991234890371873502105j)
|
| 1223 |
+
>>> ellipe(3+4j, 5-6j)
|
| 1224 |
+
(24.15299022574220502424466 + 75.2503670480325997418156j)
|
| 1225 |
+
>>> k = 35
|
| 1226 |
+
>>> z,m = 2+3j, 1.25
|
| 1227 |
+
>>> ellipe(z+pi*k,m); ellipe(z,m) + 2*k*ellipe(m)
|
| 1228 |
+
(48.30138799412005235090766 + 17.47255216721987688224357j)
|
| 1229 |
+
(48.30138799412005235090766 + 17.47255216721987688224357j)
|
| 1230 |
+
|
| 1231 |
+
For `|\Re(z)| < \pi/2`, the function can be expressed as a
|
| 1232 |
+
hypergeometric series of two variables
|
| 1233 |
+
(see :func:`~mpmath.appellf1`)::
|
| 1234 |
+
|
| 1235 |
+
>>> z,m = 0.5, 0.25
|
| 1236 |
+
>>> ellipe(z,m)
|
| 1237 |
+
0.4950017030164151928870375
|
| 1238 |
+
>>> sin(z)*appellf1(0.5,0.5,-0.5,1.5,sin(z)**2,m*sin(z)**2)
|
| 1239 |
+
0.4950017030164151928870376
|
| 1240 |
+
|
| 1241 |
+
"""
|
| 1242 |
+
if len(args) == 1:
|
| 1243 |
+
return ctx._ellipe(args[0])
|
| 1244 |
+
else:
|
| 1245 |
+
phi, m = args
|
| 1246 |
+
z = phi
|
| 1247 |
+
if not (ctx.isnormal(z) and ctx.isnormal(m)):
|
| 1248 |
+
if m == 0:
|
| 1249 |
+
return z + m
|
| 1250 |
+
if z == 0:
|
| 1251 |
+
return z * m
|
| 1252 |
+
if m == ctx.inf or m == ctx.ninf:
|
| 1253 |
+
return ctx.inf
|
| 1254 |
+
raise ValueError
|
| 1255 |
+
x = z.real
|
| 1256 |
+
ctx.prec += max(0, ctx.mag(x))
|
| 1257 |
+
pi = +ctx.pi
|
| 1258 |
+
away = abs(x) > pi/2
|
| 1259 |
+
if away:
|
| 1260 |
+
d = ctx.nint(x/pi)
|
| 1261 |
+
z = z-pi*d
|
| 1262 |
+
P = 2*d*ctx.ellipe(m)
|
| 1263 |
+
else:
|
| 1264 |
+
P = 0
|
| 1265 |
+
def terms():
|
| 1266 |
+
c, s = ctx.cos_sin(z)
|
| 1267 |
+
x = c**2
|
| 1268 |
+
y = 1-m*s**2
|
| 1269 |
+
RF = ctx.elliprf(x, y, 1)
|
| 1270 |
+
RD = ctx.elliprd(x, y, 1)
|
| 1271 |
+
return s*RF, -m*s**3*RD/3
|
| 1272 |
+
return ctx.sum_accurately(terms) + P
|
| 1273 |
+
|
| 1274 |
+
@defun_wrapped
|
| 1275 |
+
def ellippi(ctx, *args):
|
| 1276 |
+
r"""
|
| 1277 |
+
Called with three arguments `n, \phi, m`, evaluates the Legendre
|
| 1278 |
+
incomplete elliptic integral of the third kind
|
| 1279 |
+
|
| 1280 |
+
.. math ::
|
| 1281 |
+
|
| 1282 |
+
\Pi(n; \phi, m) = \int_0^{\phi}
|
| 1283 |
+
\frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} =
|
| 1284 |
+
\int_0^{\sin \phi}
|
| 1285 |
+
\frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}}.
|
| 1286 |
+
|
| 1287 |
+
Called with two arguments `n, m`, evaluates the complete
|
| 1288 |
+
elliptic integral of the third kind
|
| 1289 |
+
`\Pi(n,m) = \Pi(n; \frac{\pi}{2},m)`.
|
| 1290 |
+
|
| 1291 |
+
In the defining integral, it is assumed that the principal branch
|
| 1292 |
+
of the square root is taken and that the path of integration avoids
|
| 1293 |
+
crossing any branch cuts. Outside `-\pi/2 \le \Re(\phi) \le \pi/2`,
|
| 1294 |
+
the function extends quasi-periodically as
|
| 1295 |
+
|
| 1296 |
+
.. math ::
|
| 1297 |
+
|
| 1298 |
+
\Pi(n,\phi+k\pi,m) = 2k\Pi(n,m) + \Pi(n,\phi,m), k \in \mathbb{Z}.
|
| 1299 |
+
|
| 1300 |
+
**Plots**
|
| 1301 |
+
|
| 1302 |
+
.. literalinclude :: /plots/ellippi.py
|
| 1303 |
+
.. image :: /plots/ellippi.png
|
| 1304 |
+
|
| 1305 |
+
**Examples for the complete integral**
|
| 1306 |
+
|
| 1307 |
+
Some basic values and limits::
|
| 1308 |
+
|
| 1309 |
+
>>> from mpmath import *
|
| 1310 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1311 |
+
>>> ellippi(0,-5); ellipk(-5)
|
| 1312 |
+
0.9555039270640439337379334
|
| 1313 |
+
0.9555039270640439337379334
|
| 1314 |
+
>>> ellippi(inf,2)
|
| 1315 |
+
0.0
|
| 1316 |
+
>>> ellippi(2,inf)
|
| 1317 |
+
0.0
|
| 1318 |
+
>>> abs(ellippi(1,5))
|
| 1319 |
+
+inf
|
| 1320 |
+
>>> abs(ellippi(0.25,1))
|
| 1321 |
+
+inf
|
| 1322 |
+
|
| 1323 |
+
Evaluation in terms of simpler functions::
|
| 1324 |
+
|
| 1325 |
+
>>> ellippi(0.25,0.25); ellipe(0.25)/(1-0.25)
|
| 1326 |
+
1.956616279119236207279727
|
| 1327 |
+
1.956616279119236207279727
|
| 1328 |
+
>>> ellippi(3,0); pi/(2*sqrt(-2))
|
| 1329 |
+
(0.0 - 1.11072073453959156175397j)
|
| 1330 |
+
(0.0 - 1.11072073453959156175397j)
|
| 1331 |
+
>>> ellippi(-3,0); pi/(2*sqrt(4))
|
| 1332 |
+
0.7853981633974483096156609
|
| 1333 |
+
0.7853981633974483096156609
|
| 1334 |
+
|
| 1335 |
+
**Examples for the incomplete integral**
|
| 1336 |
+
|
| 1337 |
+
Basic values and limits::
|
| 1338 |
+
|
| 1339 |
+
>>> ellippi(0.25,-0.5); ellippi(0.25,pi/2,-0.5)
|
| 1340 |
+
1.622944760954741603710555
|
| 1341 |
+
1.622944760954741603710555
|
| 1342 |
+
>>> ellippi(1,0,1)
|
| 1343 |
+
0.0
|
| 1344 |
+
>>> ellippi(inf,0,1)
|
| 1345 |
+
0.0
|
| 1346 |
+
>>> ellippi(0,0.25,0.5); ellipf(0.25,0.5)
|
| 1347 |
+
0.2513040086544925794134591
|
| 1348 |
+
0.2513040086544925794134591
|
| 1349 |
+
>>> ellippi(1,1,1); (log(sec(1)+tan(1))+sec(1)*tan(1))/2
|
| 1350 |
+
2.054332933256248668692452
|
| 1351 |
+
2.054332933256248668692452
|
| 1352 |
+
>>> ellippi(0.25, 53*pi/2, 0.75); 53*ellippi(0.25,0.75)
|
| 1353 |
+
135.240868757890840755058
|
| 1354 |
+
135.240868757890840755058
|
| 1355 |
+
>>> ellippi(0.5,pi/4,0.5); 2*ellipe(pi/4,0.5)-1/sqrt(3)
|
| 1356 |
+
0.9190227391656969903987269
|
| 1357 |
+
0.9190227391656969903987269
|
| 1358 |
+
|
| 1359 |
+
Complex arguments are supported::
|
| 1360 |
+
|
| 1361 |
+
>>> ellippi(0.5, 5+6j-2*pi, -7-8j)
|
| 1362 |
+
(-0.3612856620076747660410167 + 0.5217735339984807829755815j)
|
| 1363 |
+
|
| 1364 |
+
Some degenerate cases::
|
| 1365 |
+
|
| 1366 |
+
>>> ellippi(1,1)
|
| 1367 |
+
+inf
|
| 1368 |
+
>>> ellippi(1,0)
|
| 1369 |
+
+inf
|
| 1370 |
+
>>> ellippi(1,2,0)
|
| 1371 |
+
+inf
|
| 1372 |
+
>>> ellippi(1,2,1)
|
| 1373 |
+
+inf
|
| 1374 |
+
>>> ellippi(1,0,1)
|
| 1375 |
+
0.0
|
| 1376 |
+
|
| 1377 |
+
"""
|
| 1378 |
+
if len(args) == 2:
|
| 1379 |
+
n, m = args
|
| 1380 |
+
complete = True
|
| 1381 |
+
z = phi = ctx.pi/2
|
| 1382 |
+
else:
|
| 1383 |
+
n, phi, m = args
|
| 1384 |
+
complete = False
|
| 1385 |
+
z = phi
|
| 1386 |
+
if not (ctx.isnormal(n) and ctx.isnormal(z) and ctx.isnormal(m)):
|
| 1387 |
+
if ctx.isnan(n) or ctx.isnan(z) or ctx.isnan(m):
|
| 1388 |
+
raise ValueError
|
| 1389 |
+
if complete:
|
| 1390 |
+
if m == 0:
|
| 1391 |
+
if n == 1:
|
| 1392 |
+
return ctx.inf
|
| 1393 |
+
return ctx.pi/(2*ctx.sqrt(1-n))
|
| 1394 |
+
if n == 0: return ctx.ellipk(m)
|
| 1395 |
+
if ctx.isinf(n) or ctx.isinf(m): return ctx.zero
|
| 1396 |
+
else:
|
| 1397 |
+
if z == 0: return z
|
| 1398 |
+
if ctx.isinf(n): return ctx.zero
|
| 1399 |
+
if ctx.isinf(m): return ctx.zero
|
| 1400 |
+
if ctx.isinf(n) or ctx.isinf(z) or ctx.isinf(m):
|
| 1401 |
+
raise ValueError
|
| 1402 |
+
if complete:
|
| 1403 |
+
if m == 1:
|
| 1404 |
+
if n == 1:
|
| 1405 |
+
return ctx.inf
|
| 1406 |
+
return -ctx.inf/ctx.sign(n-1)
|
| 1407 |
+
away = False
|
| 1408 |
+
else:
|
| 1409 |
+
x = z.real
|
| 1410 |
+
ctx.prec += max(0, ctx.mag(x))
|
| 1411 |
+
pi = +ctx.pi
|
| 1412 |
+
away = abs(x) > pi/2
|
| 1413 |
+
if away:
|
| 1414 |
+
d = ctx.nint(x/pi)
|
| 1415 |
+
z = z-pi*d
|
| 1416 |
+
P = 2*d*ctx.ellippi(n,m)
|
| 1417 |
+
if ctx.isinf(P):
|
| 1418 |
+
return ctx.inf
|
| 1419 |
+
else:
|
| 1420 |
+
P = 0
|
| 1421 |
+
def terms():
|
| 1422 |
+
if complete:
|
| 1423 |
+
c, s = ctx.zero, ctx.one
|
| 1424 |
+
else:
|
| 1425 |
+
c, s = ctx.cos_sin(z)
|
| 1426 |
+
x = c**2
|
| 1427 |
+
y = 1-m*s**2
|
| 1428 |
+
RF = ctx.elliprf(x, y, 1)
|
| 1429 |
+
RJ = ctx.elliprj(x, y, 1, 1-n*s**2)
|
| 1430 |
+
return s*RF, n*s**3*RJ/3
|
| 1431 |
+
return ctx.sum_accurately(terms) + P
|
.venv/lib/python3.11/site-packages/mpmath/functions/expintegrals.py
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .functions import defun, defun_wrapped
|
| 2 |
+
|
| 3 |
+
@defun_wrapped
|
| 4 |
+
def _erf_complex(ctx, z):
|
| 5 |
+
z2 = ctx.square_exp_arg(z, -1)
|
| 6 |
+
#z2 = -z**2
|
| 7 |
+
v = (2/ctx.sqrt(ctx.pi))*z * ctx.hyp1f1((1,2),(3,2), z2)
|
| 8 |
+
if not ctx._re(z):
|
| 9 |
+
v = ctx._im(v)*ctx.j
|
| 10 |
+
return v
|
| 11 |
+
|
| 12 |
+
@defun_wrapped
|
| 13 |
+
def _erfc_complex(ctx, z):
|
| 14 |
+
if ctx.re(z) > 2:
|
| 15 |
+
z2 = ctx.square_exp_arg(z)
|
| 16 |
+
nz2 = ctx.fneg(z2, exact=True)
|
| 17 |
+
v = ctx.exp(nz2)/ctx.sqrt(ctx.pi) * ctx.hyperu((1,2),(1,2), z2)
|
| 18 |
+
else:
|
| 19 |
+
v = 1 - ctx._erf_complex(z)
|
| 20 |
+
if not ctx._re(z):
|
| 21 |
+
v = 1+ctx._im(v)*ctx.j
|
| 22 |
+
return v
|
| 23 |
+
|
| 24 |
+
@defun
|
| 25 |
+
def erf(ctx, z):
|
| 26 |
+
z = ctx.convert(z)
|
| 27 |
+
if ctx._is_real_type(z):
|
| 28 |
+
try:
|
| 29 |
+
return ctx._erf(z)
|
| 30 |
+
except NotImplementedError:
|
| 31 |
+
pass
|
| 32 |
+
if ctx._is_complex_type(z) and not z.imag:
|
| 33 |
+
try:
|
| 34 |
+
return type(z)(ctx._erf(z.real))
|
| 35 |
+
except NotImplementedError:
|
| 36 |
+
pass
|
| 37 |
+
return ctx._erf_complex(z)
|
| 38 |
+
|
| 39 |
+
@defun
|
| 40 |
+
def erfc(ctx, z):
|
| 41 |
+
z = ctx.convert(z)
|
| 42 |
+
if ctx._is_real_type(z):
|
| 43 |
+
try:
|
| 44 |
+
return ctx._erfc(z)
|
| 45 |
+
except NotImplementedError:
|
| 46 |
+
pass
|
| 47 |
+
if ctx._is_complex_type(z) and not z.imag:
|
| 48 |
+
try:
|
| 49 |
+
return type(z)(ctx._erfc(z.real))
|
| 50 |
+
except NotImplementedError:
|
| 51 |
+
pass
|
| 52 |
+
return ctx._erfc_complex(z)
|
| 53 |
+
|
| 54 |
+
@defun
|
| 55 |
+
def square_exp_arg(ctx, z, mult=1, reciprocal=False):
|
| 56 |
+
prec = ctx.prec*4+20
|
| 57 |
+
if reciprocal:
|
| 58 |
+
z2 = ctx.fmul(z, z, prec=prec)
|
| 59 |
+
z2 = ctx.fdiv(ctx.one, z2, prec=prec)
|
| 60 |
+
else:
|
| 61 |
+
z2 = ctx.fmul(z, z, prec=prec)
|
| 62 |
+
if mult != 1:
|
| 63 |
+
z2 = ctx.fmul(z2, mult, exact=True)
|
| 64 |
+
return z2
|
| 65 |
+
|
| 66 |
+
@defun_wrapped
|
| 67 |
+
def erfi(ctx, z):
|
| 68 |
+
if not z:
|
| 69 |
+
return z
|
| 70 |
+
z2 = ctx.square_exp_arg(z)
|
| 71 |
+
v = (2/ctx.sqrt(ctx.pi)*z) * ctx.hyp1f1((1,2), (3,2), z2)
|
| 72 |
+
if not ctx._re(z):
|
| 73 |
+
v = ctx._im(v)*ctx.j
|
| 74 |
+
return v
|
| 75 |
+
|
| 76 |
+
@defun_wrapped
|
| 77 |
+
def erfinv(ctx, x):
|
| 78 |
+
xre = ctx._re(x)
|
| 79 |
+
if (xre != x) or (xre < -1) or (xre > 1):
|
| 80 |
+
return ctx.bad_domain("erfinv(x) is defined only for -1 <= x <= 1")
|
| 81 |
+
x = xre
|
| 82 |
+
#if ctx.isnan(x): return x
|
| 83 |
+
if not x: return x
|
| 84 |
+
if x == 1: return ctx.inf
|
| 85 |
+
if x == -1: return ctx.ninf
|
| 86 |
+
if abs(x) < 0.9:
|
| 87 |
+
a = 0.53728*x**3 + 0.813198*x
|
| 88 |
+
else:
|
| 89 |
+
# An asymptotic formula
|
| 90 |
+
u = ctx.ln(2/ctx.pi/(abs(x)-1)**2)
|
| 91 |
+
a = ctx.sign(x) * ctx.sqrt(u - ctx.ln(u))/ctx.sqrt(2)
|
| 92 |
+
ctx.prec += 10
|
| 93 |
+
return ctx.findroot(lambda t: ctx.erf(t)-x, a)
|
| 94 |
+
|
| 95 |
+
@defun_wrapped
|
| 96 |
+
def npdf(ctx, x, mu=0, sigma=1):
|
| 97 |
+
sigma = ctx.convert(sigma)
|
| 98 |
+
return ctx.exp(-(x-mu)**2/(2*sigma**2)) / (sigma*ctx.sqrt(2*ctx.pi))
|
| 99 |
+
|
| 100 |
+
@defun_wrapped
|
| 101 |
+
def ncdf(ctx, x, mu=0, sigma=1):
|
| 102 |
+
a = (x-mu)/(sigma*ctx.sqrt(2))
|
| 103 |
+
if a < 0:
|
| 104 |
+
return ctx.erfc(-a)/2
|
| 105 |
+
else:
|
| 106 |
+
return (1+ctx.erf(a))/2
|
| 107 |
+
|
| 108 |
+
@defun_wrapped
|
| 109 |
+
def betainc(ctx, a, b, x1=0, x2=1, regularized=False):
|
| 110 |
+
if x1 == x2:
|
| 111 |
+
v = 0
|
| 112 |
+
elif not x1:
|
| 113 |
+
if x1 == 0 and x2 == 1:
|
| 114 |
+
v = ctx.beta(a, b)
|
| 115 |
+
else:
|
| 116 |
+
v = x2**a * ctx.hyp2f1(a, 1-b, a+1, x2) / a
|
| 117 |
+
else:
|
| 118 |
+
m, d = ctx.nint_distance(a)
|
| 119 |
+
if m <= 0:
|
| 120 |
+
if d < -ctx.prec:
|
| 121 |
+
h = +ctx.eps
|
| 122 |
+
ctx.prec *= 2
|
| 123 |
+
a += h
|
| 124 |
+
elif d < -4:
|
| 125 |
+
ctx.prec -= d
|
| 126 |
+
s1 = x2**a * ctx.hyp2f1(a,1-b,a+1,x2)
|
| 127 |
+
s2 = x1**a * ctx.hyp2f1(a,1-b,a+1,x1)
|
| 128 |
+
v = (s1 - s2) / a
|
| 129 |
+
if regularized:
|
| 130 |
+
v /= ctx.beta(a,b)
|
| 131 |
+
return v
|
| 132 |
+
|
| 133 |
+
@defun
|
| 134 |
+
def gammainc(ctx, z, a=0, b=None, regularized=False):
|
| 135 |
+
regularized = bool(regularized)
|
| 136 |
+
z = ctx.convert(z)
|
| 137 |
+
if a is None:
|
| 138 |
+
a = ctx.zero
|
| 139 |
+
lower_modified = False
|
| 140 |
+
else:
|
| 141 |
+
a = ctx.convert(a)
|
| 142 |
+
lower_modified = a != ctx.zero
|
| 143 |
+
if b is None:
|
| 144 |
+
b = ctx.inf
|
| 145 |
+
upper_modified = False
|
| 146 |
+
else:
|
| 147 |
+
b = ctx.convert(b)
|
| 148 |
+
upper_modified = b != ctx.inf
|
| 149 |
+
# Complete gamma function
|
| 150 |
+
if not (upper_modified or lower_modified):
|
| 151 |
+
if regularized:
|
| 152 |
+
if ctx.re(z) < 0:
|
| 153 |
+
return ctx.inf
|
| 154 |
+
elif ctx.re(z) > 0:
|
| 155 |
+
return ctx.one
|
| 156 |
+
else:
|
| 157 |
+
return ctx.nan
|
| 158 |
+
return ctx.gamma(z)
|
| 159 |
+
if a == b:
|
| 160 |
+
return ctx.zero
|
| 161 |
+
# Standardize
|
| 162 |
+
if ctx.re(a) > ctx.re(b):
|
| 163 |
+
return -ctx.gammainc(z, b, a, regularized)
|
| 164 |
+
# Generalized gamma
|
| 165 |
+
if upper_modified and lower_modified:
|
| 166 |
+
return +ctx._gamma3(z, a, b, regularized)
|
| 167 |
+
# Upper gamma
|
| 168 |
+
elif lower_modified:
|
| 169 |
+
return ctx._upper_gamma(z, a, regularized)
|
| 170 |
+
# Lower gamma
|
| 171 |
+
elif upper_modified:
|
| 172 |
+
return ctx._lower_gamma(z, b, regularized)
|
| 173 |
+
|
| 174 |
+
@defun
|
| 175 |
+
def _lower_gamma(ctx, z, b, regularized=False):
|
| 176 |
+
# Pole
|
| 177 |
+
if ctx.isnpint(z):
|
| 178 |
+
return type(z)(ctx.inf)
|
| 179 |
+
G = [z] * regularized
|
| 180 |
+
negb = ctx.fneg(b, exact=True)
|
| 181 |
+
def h(z):
|
| 182 |
+
T1 = [ctx.exp(negb), b, z], [1, z, -1], [], G, [1], [1+z], b
|
| 183 |
+
return (T1,)
|
| 184 |
+
return ctx.hypercomb(h, [z])
|
| 185 |
+
|
| 186 |
+
@defun
|
| 187 |
+
def _upper_gamma(ctx, z, a, regularized=False):
|
| 188 |
+
# Fast integer case, when available
|
| 189 |
+
if ctx.isint(z):
|
| 190 |
+
try:
|
| 191 |
+
if regularized:
|
| 192 |
+
# Gamma pole
|
| 193 |
+
if ctx.isnpint(z):
|
| 194 |
+
return type(z)(ctx.zero)
|
| 195 |
+
orig = ctx.prec
|
| 196 |
+
try:
|
| 197 |
+
ctx.prec += 10
|
| 198 |
+
return ctx._gamma_upper_int(z, a) / ctx.gamma(z)
|
| 199 |
+
finally:
|
| 200 |
+
ctx.prec = orig
|
| 201 |
+
else:
|
| 202 |
+
return ctx._gamma_upper_int(z, a)
|
| 203 |
+
except NotImplementedError:
|
| 204 |
+
pass
|
| 205 |
+
# hypercomb is unable to detect the exact zeros, so handle them here
|
| 206 |
+
if z == 2 and a == -1:
|
| 207 |
+
return (z+a)*0
|
| 208 |
+
if z == 3 and (a == -1-1j or a == -1+1j):
|
| 209 |
+
return (z+a)*0
|
| 210 |
+
nega = ctx.fneg(a, exact=True)
|
| 211 |
+
G = [z] * regularized
|
| 212 |
+
# Use 2F0 series when possible; fall back to lower gamma representation
|
| 213 |
+
try:
|
| 214 |
+
def h(z):
|
| 215 |
+
r = z-1
|
| 216 |
+
return [([ctx.exp(nega), a], [1, r], [], G, [1, -r], [], 1/nega)]
|
| 217 |
+
return ctx.hypercomb(h, [z], force_series=True)
|
| 218 |
+
except ctx.NoConvergence:
|
| 219 |
+
def h(z):
|
| 220 |
+
T1 = [], [1, z-1], [z], G, [], [], 0
|
| 221 |
+
T2 = [-ctx.exp(nega), a, z], [1, z, -1], [], G, [1], [1+z], a
|
| 222 |
+
return T1, T2
|
| 223 |
+
return ctx.hypercomb(h, [z])
|
| 224 |
+
|
| 225 |
+
@defun
|
| 226 |
+
def _gamma3(ctx, z, a, b, regularized=False):
|
| 227 |
+
pole = ctx.isnpint(z)
|
| 228 |
+
if regularized and pole:
|
| 229 |
+
return ctx.zero
|
| 230 |
+
try:
|
| 231 |
+
ctx.prec += 15
|
| 232 |
+
# We don't know in advance whether it's better to write as a difference
|
| 233 |
+
# of lower or upper gamma functions, so try both
|
| 234 |
+
T1 = ctx.gammainc(z, a, regularized=regularized)
|
| 235 |
+
T2 = ctx.gammainc(z, b, regularized=regularized)
|
| 236 |
+
R = T1 - T2
|
| 237 |
+
if ctx.mag(R) - max(ctx.mag(T1), ctx.mag(T2)) > -10:
|
| 238 |
+
return R
|
| 239 |
+
if not pole:
|
| 240 |
+
T1 = ctx.gammainc(z, 0, b, regularized=regularized)
|
| 241 |
+
T2 = ctx.gammainc(z, 0, a, regularized=regularized)
|
| 242 |
+
R = T1 - T2
|
| 243 |
+
# May be ok, but should probably at least print a warning
|
| 244 |
+
# about possible cancellation
|
| 245 |
+
if 1: #ctx.mag(R) - max(ctx.mag(T1), ctx.mag(T2)) > -10:
|
| 246 |
+
return R
|
| 247 |
+
finally:
|
| 248 |
+
ctx.prec -= 15
|
| 249 |
+
raise NotImplementedError
|
| 250 |
+
|
| 251 |
+
@defun_wrapped
|
| 252 |
+
def expint(ctx, n, z):
|
| 253 |
+
if ctx.isint(n) and ctx._is_real_type(z):
|
| 254 |
+
try:
|
| 255 |
+
return ctx._expint_int(n, z)
|
| 256 |
+
except NotImplementedError:
|
| 257 |
+
pass
|
| 258 |
+
if ctx.isnan(n) or ctx.isnan(z):
|
| 259 |
+
return z*n
|
| 260 |
+
if z == ctx.inf:
|
| 261 |
+
return 1/z
|
| 262 |
+
if z == 0:
|
| 263 |
+
# integral from 1 to infinity of t^n
|
| 264 |
+
if ctx.re(n) <= 1:
|
| 265 |
+
# TODO: reasonable sign of infinity
|
| 266 |
+
return type(z)(ctx.inf)
|
| 267 |
+
else:
|
| 268 |
+
return ctx.one/(n-1)
|
| 269 |
+
if n == 0:
|
| 270 |
+
return ctx.exp(-z)/z
|
| 271 |
+
if n == -1:
|
| 272 |
+
return ctx.exp(-z)*(z+1)/z**2
|
| 273 |
+
return z**(n-1) * ctx.gammainc(1-n, z)
|
| 274 |
+
|
| 275 |
+
@defun_wrapped
|
| 276 |
+
def li(ctx, z, offset=False):
|
| 277 |
+
if offset:
|
| 278 |
+
if z == 2:
|
| 279 |
+
return ctx.zero
|
| 280 |
+
return ctx.ei(ctx.ln(z)) - ctx.ei(ctx.ln2)
|
| 281 |
+
if not z:
|
| 282 |
+
return z
|
| 283 |
+
if z == 1:
|
| 284 |
+
return ctx.ninf
|
| 285 |
+
return ctx.ei(ctx.ln(z))
|
| 286 |
+
|
| 287 |
+
@defun
|
| 288 |
+
def ei(ctx, z):
|
| 289 |
+
try:
|
| 290 |
+
return ctx._ei(z)
|
| 291 |
+
except NotImplementedError:
|
| 292 |
+
return ctx._ei_generic(z)
|
| 293 |
+
|
| 294 |
+
@defun_wrapped
|
| 295 |
+
def _ei_generic(ctx, z):
|
| 296 |
+
# Note: the following is currently untested because mp and fp
|
| 297 |
+
# both use special-case ei code
|
| 298 |
+
if z == ctx.inf:
|
| 299 |
+
return z
|
| 300 |
+
if z == ctx.ninf:
|
| 301 |
+
return ctx.zero
|
| 302 |
+
if ctx.mag(z) > 1:
|
| 303 |
+
try:
|
| 304 |
+
r = ctx.one/z
|
| 305 |
+
v = ctx.exp(z)*ctx.hyper([1,1],[],r,
|
| 306 |
+
maxterms=ctx.prec, force_series=True)/z
|
| 307 |
+
im = ctx._im(z)
|
| 308 |
+
if im > 0:
|
| 309 |
+
v += ctx.pi*ctx.j
|
| 310 |
+
if im < 0:
|
| 311 |
+
v -= ctx.pi*ctx.j
|
| 312 |
+
return v
|
| 313 |
+
except ctx.NoConvergence:
|
| 314 |
+
pass
|
| 315 |
+
v = z*ctx.hyp2f2(1,1,2,2,z) + ctx.euler
|
| 316 |
+
if ctx._im(z):
|
| 317 |
+
v += 0.5*(ctx.log(z) - ctx.log(ctx.one/z))
|
| 318 |
+
else:
|
| 319 |
+
v += ctx.log(abs(z))
|
| 320 |
+
return v
|
| 321 |
+
|
| 322 |
+
@defun
|
| 323 |
+
def e1(ctx, z):
|
| 324 |
+
try:
|
| 325 |
+
return ctx._e1(z)
|
| 326 |
+
except NotImplementedError:
|
| 327 |
+
return ctx.expint(1, z)
|
| 328 |
+
|
| 329 |
+
@defun
|
| 330 |
+
def ci(ctx, z):
|
| 331 |
+
try:
|
| 332 |
+
return ctx._ci(z)
|
| 333 |
+
except NotImplementedError:
|
| 334 |
+
return ctx._ci_generic(z)
|
| 335 |
+
|
| 336 |
+
@defun_wrapped
|
| 337 |
+
def _ci_generic(ctx, z):
|
| 338 |
+
if ctx.isinf(z):
|
| 339 |
+
if z == ctx.inf: return ctx.zero
|
| 340 |
+
if z == ctx.ninf: return ctx.pi*1j
|
| 341 |
+
jz = ctx.fmul(ctx.j,z,exact=True)
|
| 342 |
+
njz = ctx.fneg(jz,exact=True)
|
| 343 |
+
v = 0.5*(ctx.ei(jz) + ctx.ei(njz))
|
| 344 |
+
zreal = ctx._re(z)
|
| 345 |
+
zimag = ctx._im(z)
|
| 346 |
+
if zreal == 0:
|
| 347 |
+
if zimag > 0: v += ctx.pi*0.5j
|
| 348 |
+
if zimag < 0: v -= ctx.pi*0.5j
|
| 349 |
+
if zreal < 0:
|
| 350 |
+
if zimag >= 0: v += ctx.pi*1j
|
| 351 |
+
if zimag < 0: v -= ctx.pi*1j
|
| 352 |
+
if ctx._is_real_type(z) and zreal > 0:
|
| 353 |
+
v = ctx._re(v)
|
| 354 |
+
return v
|
| 355 |
+
|
| 356 |
+
@defun
|
| 357 |
+
def si(ctx, z):
|
| 358 |
+
try:
|
| 359 |
+
return ctx._si(z)
|
| 360 |
+
except NotImplementedError:
|
| 361 |
+
return ctx._si_generic(z)
|
| 362 |
+
|
| 363 |
+
@defun_wrapped
|
| 364 |
+
def _si_generic(ctx, z):
|
| 365 |
+
if ctx.isinf(z):
|
| 366 |
+
if z == ctx.inf: return 0.5*ctx.pi
|
| 367 |
+
if z == ctx.ninf: return -0.5*ctx.pi
|
| 368 |
+
# Suffers from cancellation near 0
|
| 369 |
+
if ctx.mag(z) >= -1:
|
| 370 |
+
jz = ctx.fmul(ctx.j,z,exact=True)
|
| 371 |
+
njz = ctx.fneg(jz,exact=True)
|
| 372 |
+
v = (-0.5j)*(ctx.ei(jz) - ctx.ei(njz))
|
| 373 |
+
zreal = ctx._re(z)
|
| 374 |
+
if zreal > 0:
|
| 375 |
+
v -= 0.5*ctx.pi
|
| 376 |
+
if zreal < 0:
|
| 377 |
+
v += 0.5*ctx.pi
|
| 378 |
+
if ctx._is_real_type(z):
|
| 379 |
+
v = ctx._re(v)
|
| 380 |
+
return v
|
| 381 |
+
else:
|
| 382 |
+
return z*ctx.hyp1f2((1,2),(3,2),(3,2),-0.25*z*z)
|
| 383 |
+
|
| 384 |
+
@defun_wrapped
|
| 385 |
+
def chi(ctx, z):
|
| 386 |
+
nz = ctx.fneg(z, exact=True)
|
| 387 |
+
v = 0.5*(ctx.ei(z) + ctx.ei(nz))
|
| 388 |
+
zreal = ctx._re(z)
|
| 389 |
+
zimag = ctx._im(z)
|
| 390 |
+
if zimag > 0:
|
| 391 |
+
v += ctx.pi*0.5j
|
| 392 |
+
elif zimag < 0:
|
| 393 |
+
v -= ctx.pi*0.5j
|
| 394 |
+
elif zreal < 0:
|
| 395 |
+
v += ctx.pi*1j
|
| 396 |
+
return v
|
| 397 |
+
|
| 398 |
+
@defun_wrapped
|
| 399 |
+
def shi(ctx, z):
|
| 400 |
+
# Suffers from cancellation near 0
|
| 401 |
+
if ctx.mag(z) >= -1:
|
| 402 |
+
nz = ctx.fneg(z, exact=True)
|
| 403 |
+
v = 0.5*(ctx.ei(z) - ctx.ei(nz))
|
| 404 |
+
zimag = ctx._im(z)
|
| 405 |
+
if zimag > 0: v -= 0.5j*ctx.pi
|
| 406 |
+
if zimag < 0: v += 0.5j*ctx.pi
|
| 407 |
+
return v
|
| 408 |
+
else:
|
| 409 |
+
return z * ctx.hyp1f2((1,2),(3,2),(3,2),0.25*z*z)
|
| 410 |
+
|
| 411 |
+
@defun_wrapped
|
| 412 |
+
def fresnels(ctx, z):
|
| 413 |
+
if z == ctx.inf:
|
| 414 |
+
return ctx.mpf(0.5)
|
| 415 |
+
if z == ctx.ninf:
|
| 416 |
+
return ctx.mpf(-0.5)
|
| 417 |
+
return ctx.pi*z**3/6*ctx.hyp1f2((3,4),(3,2),(7,4),-ctx.pi**2*z**4/16)
|
| 418 |
+
|
| 419 |
+
@defun_wrapped
|
| 420 |
+
def fresnelc(ctx, z):
|
| 421 |
+
if z == ctx.inf:
|
| 422 |
+
return ctx.mpf(0.5)
|
| 423 |
+
if z == ctx.ninf:
|
| 424 |
+
return ctx.mpf(-0.5)
|
| 425 |
+
return z*ctx.hyp1f2((1,4),(1,2),(5,4),-ctx.pi**2*z**4/16)
|
.venv/lib/python3.11/site-packages/mpmath/functions/factorials.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ..libmp.backend import xrange
|
| 2 |
+
from .functions import defun, defun_wrapped
|
| 3 |
+
|
| 4 |
+
@defun
|
| 5 |
+
def gammaprod(ctx, a, b, _infsign=False):
|
| 6 |
+
a = [ctx.convert(x) for x in a]
|
| 7 |
+
b = [ctx.convert(x) for x in b]
|
| 8 |
+
poles_num = []
|
| 9 |
+
poles_den = []
|
| 10 |
+
regular_num = []
|
| 11 |
+
regular_den = []
|
| 12 |
+
for x in a: [regular_num, poles_num][ctx.isnpint(x)].append(x)
|
| 13 |
+
for x in b: [regular_den, poles_den][ctx.isnpint(x)].append(x)
|
| 14 |
+
# One more pole in numerator or denominator gives 0 or inf
|
| 15 |
+
if len(poles_num) < len(poles_den): return ctx.zero
|
| 16 |
+
if len(poles_num) > len(poles_den):
|
| 17 |
+
# Get correct sign of infinity for x+h, h -> 0 from above
|
| 18 |
+
# XXX: hack, this should be done properly
|
| 19 |
+
if _infsign:
|
| 20 |
+
a = [x and x*(1+ctx.eps) or x+ctx.eps for x in poles_num]
|
| 21 |
+
b = [x and x*(1+ctx.eps) or x+ctx.eps for x in poles_den]
|
| 22 |
+
return ctx.sign(ctx.gammaprod(a+regular_num,b+regular_den)) * ctx.inf
|
| 23 |
+
else:
|
| 24 |
+
return ctx.inf
|
| 25 |
+
# All poles cancel
|
| 26 |
+
# lim G(i)/G(j) = (-1)**(i+j) * gamma(1-j) / gamma(1-i)
|
| 27 |
+
p = ctx.one
|
| 28 |
+
orig = ctx.prec
|
| 29 |
+
try:
|
| 30 |
+
ctx.prec = orig + 15
|
| 31 |
+
while poles_num:
|
| 32 |
+
i = poles_num.pop()
|
| 33 |
+
j = poles_den.pop()
|
| 34 |
+
p *= (-1)**(i+j) * ctx.gamma(1-j) / ctx.gamma(1-i)
|
| 35 |
+
for x in regular_num: p *= ctx.gamma(x)
|
| 36 |
+
for x in regular_den: p /= ctx.gamma(x)
|
| 37 |
+
finally:
|
| 38 |
+
ctx.prec = orig
|
| 39 |
+
return +p
|
| 40 |
+
|
| 41 |
+
@defun
|
| 42 |
+
def beta(ctx, x, y):
|
| 43 |
+
x = ctx.convert(x)
|
| 44 |
+
y = ctx.convert(y)
|
| 45 |
+
if ctx.isinf(y):
|
| 46 |
+
x, y = y, x
|
| 47 |
+
if ctx.isinf(x):
|
| 48 |
+
if x == ctx.inf and not ctx._im(y):
|
| 49 |
+
if y == ctx.ninf:
|
| 50 |
+
return ctx.nan
|
| 51 |
+
if y > 0:
|
| 52 |
+
return ctx.zero
|
| 53 |
+
if ctx.isint(y):
|
| 54 |
+
return ctx.nan
|
| 55 |
+
if y < 0:
|
| 56 |
+
return ctx.sign(ctx.gamma(y)) * ctx.inf
|
| 57 |
+
return ctx.nan
|
| 58 |
+
xy = ctx.fadd(x, y, prec=2*ctx.prec)
|
| 59 |
+
return ctx.gammaprod([x, y], [xy])
|
| 60 |
+
|
| 61 |
+
@defun
|
| 62 |
+
def binomial(ctx, n, k):
|
| 63 |
+
n1 = ctx.fadd(n, 1, prec=2*ctx.prec)
|
| 64 |
+
k1 = ctx.fadd(k, 1, prec=2*ctx.prec)
|
| 65 |
+
nk1 = ctx.fsub(n1, k, prec=2*ctx.prec)
|
| 66 |
+
return ctx.gammaprod([n1], [k1, nk1])
|
| 67 |
+
|
| 68 |
+
@defun
|
| 69 |
+
def rf(ctx, x, n):
|
| 70 |
+
xn = ctx.fadd(x, n, prec=2*ctx.prec)
|
| 71 |
+
return ctx.gammaprod([xn], [x])
|
| 72 |
+
|
| 73 |
+
@defun
|
| 74 |
+
def ff(ctx, x, n):
|
| 75 |
+
x1 = ctx.fadd(x, 1, prec=2*ctx.prec)
|
| 76 |
+
xn1 = ctx.fadd(ctx.fsub(x, n, prec=2*ctx.prec), 1, prec=2*ctx.prec)
|
| 77 |
+
return ctx.gammaprod([x1], [xn1])
|
| 78 |
+
|
| 79 |
+
@defun_wrapped
|
| 80 |
+
def fac2(ctx, x):
|
| 81 |
+
if ctx.isinf(x):
|
| 82 |
+
if x == ctx.inf:
|
| 83 |
+
return x
|
| 84 |
+
return ctx.nan
|
| 85 |
+
return 2**(x/2)*(ctx.pi/2)**((ctx.cospi(x)-1)/4)*ctx.gamma(x/2+1)
|
| 86 |
+
|
| 87 |
+
@defun_wrapped
|
| 88 |
+
def barnesg(ctx, z):
|
| 89 |
+
if ctx.isinf(z):
|
| 90 |
+
if z == ctx.inf:
|
| 91 |
+
return z
|
| 92 |
+
return ctx.nan
|
| 93 |
+
if ctx.isnan(z):
|
| 94 |
+
return z
|
| 95 |
+
if (not ctx._im(z)) and ctx._re(z) <= 0 and ctx.isint(ctx._re(z)):
|
| 96 |
+
return z*0
|
| 97 |
+
# Account for size (would not be needed if computing log(G))
|
| 98 |
+
if abs(z) > 5:
|
| 99 |
+
ctx.dps += 2*ctx.log(abs(z),2)
|
| 100 |
+
# Reflection formula
|
| 101 |
+
if ctx.re(z) < -ctx.dps:
|
| 102 |
+
w = 1-z
|
| 103 |
+
pi2 = 2*ctx.pi
|
| 104 |
+
u = ctx.expjpi(2*w)
|
| 105 |
+
v = ctx.j*ctx.pi/12 - ctx.j*ctx.pi*w**2/2 + w*ctx.ln(1-u) - \
|
| 106 |
+
ctx.j*ctx.polylog(2, u)/pi2
|
| 107 |
+
v = ctx.barnesg(2-z)*ctx.exp(v)/pi2**w
|
| 108 |
+
if ctx._is_real_type(z):
|
| 109 |
+
v = ctx._re(v)
|
| 110 |
+
return v
|
| 111 |
+
# Estimate terms for asymptotic expansion
|
| 112 |
+
# TODO: fixme, obviously
|
| 113 |
+
N = ctx.dps // 2 + 5
|
| 114 |
+
G = 1
|
| 115 |
+
while abs(z) < N or ctx.re(z) < 1:
|
| 116 |
+
G /= ctx.gamma(z)
|
| 117 |
+
z += 1
|
| 118 |
+
z -= 1
|
| 119 |
+
s = ctx.mpf(1)/12
|
| 120 |
+
s -= ctx.log(ctx.glaisher)
|
| 121 |
+
s += z*ctx.log(2*ctx.pi)/2
|
| 122 |
+
s += (z**2/2-ctx.mpf(1)/12)*ctx.log(z)
|
| 123 |
+
s -= 3*z**2/4
|
| 124 |
+
z2k = z2 = z**2
|
| 125 |
+
for k in xrange(1, N+1):
|
| 126 |
+
t = ctx.bernoulli(2*k+2) / (4*k*(k+1)*z2k)
|
| 127 |
+
if abs(t) < ctx.eps:
|
| 128 |
+
#print k, N # check how many terms were needed
|
| 129 |
+
break
|
| 130 |
+
z2k *= z2
|
| 131 |
+
s += t
|
| 132 |
+
#if k == N:
|
| 133 |
+
# print "warning: series for barnesg failed to converge", ctx.dps
|
| 134 |
+
return G*ctx.exp(s)
|
| 135 |
+
|
| 136 |
+
@defun
|
| 137 |
+
def superfac(ctx, z):
|
| 138 |
+
return ctx.barnesg(z+2)
|
| 139 |
+
|
| 140 |
+
@defun_wrapped
|
| 141 |
+
def hyperfac(ctx, z):
|
| 142 |
+
# XXX: estimate needed extra bits accurately
|
| 143 |
+
if z == ctx.inf:
|
| 144 |
+
return z
|
| 145 |
+
if abs(z) > 5:
|
| 146 |
+
extra = 4*int(ctx.log(abs(z),2))
|
| 147 |
+
else:
|
| 148 |
+
extra = 0
|
| 149 |
+
ctx.prec += extra
|
| 150 |
+
if not ctx._im(z) and ctx._re(z) < 0 and ctx.isint(ctx._re(z)):
|
| 151 |
+
n = int(ctx.re(z))
|
| 152 |
+
h = ctx.hyperfac(-n-1)
|
| 153 |
+
if ((n+1)//2) & 1:
|
| 154 |
+
h = -h
|
| 155 |
+
if ctx._is_complex_type(z):
|
| 156 |
+
return h + 0j
|
| 157 |
+
return h
|
| 158 |
+
zp1 = z+1
|
| 159 |
+
# Wrong branch cut
|
| 160 |
+
#v = ctx.gamma(zp1)**z
|
| 161 |
+
#ctx.prec -= extra
|
| 162 |
+
#return v / ctx.barnesg(zp1)
|
| 163 |
+
v = ctx.exp(z*ctx.loggamma(zp1))
|
| 164 |
+
ctx.prec -= extra
|
| 165 |
+
return v / ctx.barnesg(zp1)
|
| 166 |
+
|
| 167 |
+
'''
|
| 168 |
+
@defun
|
| 169 |
+
def psi0(ctx, z):
|
| 170 |
+
"""Shortcut for psi(0,z) (the digamma function)"""
|
| 171 |
+
return ctx.psi(0, z)
|
| 172 |
+
|
| 173 |
+
@defun
|
| 174 |
+
def psi1(ctx, z):
|
| 175 |
+
"""Shortcut for psi(1,z) (the trigamma function)"""
|
| 176 |
+
return ctx.psi(1, z)
|
| 177 |
+
|
| 178 |
+
@defun
|
| 179 |
+
def psi2(ctx, z):
|
| 180 |
+
"""Shortcut for psi(2,z) (the tetragamma function)"""
|
| 181 |
+
return ctx.psi(2, z)
|
| 182 |
+
|
| 183 |
+
@defun
|
| 184 |
+
def psi3(ctx, z):
|
| 185 |
+
"""Shortcut for psi(3,z) (the pentagamma function)"""
|
| 186 |
+
return ctx.psi(3, z)
|
| 187 |
+
'''
|
.venv/lib/python3.11/site-packages/mpmath/functions/functions.py
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ..libmp.backend import xrange
|
| 2 |
+
|
| 3 |
+
class SpecialFunctions(object):
|
| 4 |
+
"""
|
| 5 |
+
This class implements special functions using high-level code.
|
| 6 |
+
|
| 7 |
+
Elementary and some other functions (e.g. gamma function, basecase
|
| 8 |
+
hypergeometric series) are assumed to be predefined by the context as
|
| 9 |
+
"builtins" or "low-level" functions.
|
| 10 |
+
"""
|
| 11 |
+
defined_functions = {}
|
| 12 |
+
|
| 13 |
+
# The series for the Jacobi theta functions converge for |q| < 1;
|
| 14 |
+
# in the current implementation they throw a ValueError for
|
| 15 |
+
# abs(q) > THETA_Q_LIM
|
| 16 |
+
THETA_Q_LIM = 1 - 10**-7
|
| 17 |
+
|
| 18 |
+
def __init__(self):
|
| 19 |
+
cls = self.__class__
|
| 20 |
+
for name in cls.defined_functions:
|
| 21 |
+
f, wrap = cls.defined_functions[name]
|
| 22 |
+
cls._wrap_specfun(name, f, wrap)
|
| 23 |
+
|
| 24 |
+
self.mpq_1 = self._mpq((1,1))
|
| 25 |
+
self.mpq_0 = self._mpq((0,1))
|
| 26 |
+
self.mpq_1_2 = self._mpq((1,2))
|
| 27 |
+
self.mpq_3_2 = self._mpq((3,2))
|
| 28 |
+
self.mpq_1_4 = self._mpq((1,4))
|
| 29 |
+
self.mpq_1_16 = self._mpq((1,16))
|
| 30 |
+
self.mpq_3_16 = self._mpq((3,16))
|
| 31 |
+
self.mpq_5_2 = self._mpq((5,2))
|
| 32 |
+
self.mpq_3_4 = self._mpq((3,4))
|
| 33 |
+
self.mpq_7_4 = self._mpq((7,4))
|
| 34 |
+
self.mpq_5_4 = self._mpq((5,4))
|
| 35 |
+
self.mpq_1_3 = self._mpq((1,3))
|
| 36 |
+
self.mpq_2_3 = self._mpq((2,3))
|
| 37 |
+
self.mpq_4_3 = self._mpq((4,3))
|
| 38 |
+
self.mpq_1_6 = self._mpq((1,6))
|
| 39 |
+
self.mpq_5_6 = self._mpq((5,6))
|
| 40 |
+
self.mpq_5_3 = self._mpq((5,3))
|
| 41 |
+
|
| 42 |
+
self._misc_const_cache = {}
|
| 43 |
+
|
| 44 |
+
self._aliases.update({
|
| 45 |
+
'phase' : 'arg',
|
| 46 |
+
'conjugate' : 'conj',
|
| 47 |
+
'nthroot' : 'root',
|
| 48 |
+
'polygamma' : 'psi',
|
| 49 |
+
'hurwitz' : 'zeta',
|
| 50 |
+
#'digamma' : 'psi0',
|
| 51 |
+
#'trigamma' : 'psi1',
|
| 52 |
+
#'tetragamma' : 'psi2',
|
| 53 |
+
#'pentagamma' : 'psi3',
|
| 54 |
+
'fibonacci' : 'fib',
|
| 55 |
+
'factorial' : 'fac',
|
| 56 |
+
})
|
| 57 |
+
|
| 58 |
+
self.zetazero_memoized = self.memoize(self.zetazero)
|
| 59 |
+
|
| 60 |
+
# Default -- do nothing
|
| 61 |
+
@classmethod
|
| 62 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 63 |
+
setattr(cls, name, f)
|
| 64 |
+
|
| 65 |
+
# Optional fast versions of common functions in common cases.
|
| 66 |
+
# If not overridden, default (generic hypergeometric series)
|
| 67 |
+
# implementations will be used
|
| 68 |
+
def _besselj(ctx, n, z): raise NotImplementedError
|
| 69 |
+
def _erf(ctx, z): raise NotImplementedError
|
| 70 |
+
def _erfc(ctx, z): raise NotImplementedError
|
| 71 |
+
def _gamma_upper_int(ctx, z, a): raise NotImplementedError
|
| 72 |
+
def _expint_int(ctx, n, z): raise NotImplementedError
|
| 73 |
+
def _zeta(ctx, s): raise NotImplementedError
|
| 74 |
+
def _zetasum_fast(ctx, s, a, n, derivatives, reflect): raise NotImplementedError
|
| 75 |
+
def _ei(ctx, z): raise NotImplementedError
|
| 76 |
+
def _e1(ctx, z): raise NotImplementedError
|
| 77 |
+
def _ci(ctx, z): raise NotImplementedError
|
| 78 |
+
def _si(ctx, z): raise NotImplementedError
|
| 79 |
+
def _altzeta(ctx, s): raise NotImplementedError
|
| 80 |
+
|
| 81 |
+
def defun_wrapped(f):
|
| 82 |
+
SpecialFunctions.defined_functions[f.__name__] = f, True
|
| 83 |
+
return f
|
| 84 |
+
|
| 85 |
+
def defun(f):
|
| 86 |
+
SpecialFunctions.defined_functions[f.__name__] = f, False
|
| 87 |
+
return f
|
| 88 |
+
|
| 89 |
+
def defun_static(f):
|
| 90 |
+
setattr(SpecialFunctions, f.__name__, f)
|
| 91 |
+
return f
|
| 92 |
+
|
| 93 |
+
@defun_wrapped
|
| 94 |
+
def cot(ctx, z): return ctx.one / ctx.tan(z)
|
| 95 |
+
|
| 96 |
+
@defun_wrapped
|
| 97 |
+
def sec(ctx, z): return ctx.one / ctx.cos(z)
|
| 98 |
+
|
| 99 |
+
@defun_wrapped
|
| 100 |
+
def csc(ctx, z): return ctx.one / ctx.sin(z)
|
| 101 |
+
|
| 102 |
+
@defun_wrapped
|
| 103 |
+
def coth(ctx, z): return ctx.one / ctx.tanh(z)
|
| 104 |
+
|
| 105 |
+
@defun_wrapped
|
| 106 |
+
def sech(ctx, z): return ctx.one / ctx.cosh(z)
|
| 107 |
+
|
| 108 |
+
@defun_wrapped
|
| 109 |
+
def csch(ctx, z): return ctx.one / ctx.sinh(z)
|
| 110 |
+
|
| 111 |
+
@defun_wrapped
|
| 112 |
+
def acot(ctx, z):
|
| 113 |
+
if not z:
|
| 114 |
+
return ctx.pi * 0.5
|
| 115 |
+
else:
|
| 116 |
+
return ctx.atan(ctx.one / z)
|
| 117 |
+
|
| 118 |
+
@defun_wrapped
|
| 119 |
+
def asec(ctx, z): return ctx.acos(ctx.one / z)
|
| 120 |
+
|
| 121 |
+
@defun_wrapped
|
| 122 |
+
def acsc(ctx, z): return ctx.asin(ctx.one / z)
|
| 123 |
+
|
| 124 |
+
@defun_wrapped
|
| 125 |
+
def acoth(ctx, z):
|
| 126 |
+
if not z:
|
| 127 |
+
return ctx.pi * 0.5j
|
| 128 |
+
else:
|
| 129 |
+
return ctx.atanh(ctx.one / z)
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
@defun_wrapped
|
| 133 |
+
def asech(ctx, z): return ctx.acosh(ctx.one / z)
|
| 134 |
+
|
| 135 |
+
@defun_wrapped
|
| 136 |
+
def acsch(ctx, z): return ctx.asinh(ctx.one / z)
|
| 137 |
+
|
| 138 |
+
@defun
|
| 139 |
+
def sign(ctx, x):
|
| 140 |
+
x = ctx.convert(x)
|
| 141 |
+
if not x or ctx.isnan(x):
|
| 142 |
+
return x
|
| 143 |
+
if ctx._is_real_type(x):
|
| 144 |
+
if x > 0:
|
| 145 |
+
return ctx.one
|
| 146 |
+
else:
|
| 147 |
+
return -ctx.one
|
| 148 |
+
return x / abs(x)
|
| 149 |
+
|
| 150 |
+
@defun
|
| 151 |
+
def agm(ctx, a, b=1):
|
| 152 |
+
if b == 1:
|
| 153 |
+
return ctx.agm1(a)
|
| 154 |
+
a = ctx.convert(a)
|
| 155 |
+
b = ctx.convert(b)
|
| 156 |
+
return ctx._agm(a, b)
|
| 157 |
+
|
| 158 |
+
@defun_wrapped
|
| 159 |
+
def sinc(ctx, x):
|
| 160 |
+
if ctx.isinf(x):
|
| 161 |
+
return 1/x
|
| 162 |
+
if not x:
|
| 163 |
+
return x+1
|
| 164 |
+
return ctx.sin(x)/x
|
| 165 |
+
|
| 166 |
+
@defun_wrapped
|
| 167 |
+
def sincpi(ctx, x):
|
| 168 |
+
if ctx.isinf(x):
|
| 169 |
+
return 1/x
|
| 170 |
+
if not x:
|
| 171 |
+
return x+1
|
| 172 |
+
return ctx.sinpi(x)/(ctx.pi*x)
|
| 173 |
+
|
| 174 |
+
# TODO: tests; improve implementation
|
| 175 |
+
@defun_wrapped
|
| 176 |
+
def expm1(ctx, x):
|
| 177 |
+
if not x:
|
| 178 |
+
return ctx.zero
|
| 179 |
+
# exp(x) - 1 ~ x
|
| 180 |
+
if ctx.mag(x) < -ctx.prec:
|
| 181 |
+
return x + 0.5*x**2
|
| 182 |
+
# TODO: accurately eval the smaller of the real/imag parts
|
| 183 |
+
return ctx.sum_accurately(lambda: iter([ctx.exp(x),-1]),1)
|
| 184 |
+
|
| 185 |
+
@defun_wrapped
|
| 186 |
+
def log1p(ctx, x):
|
| 187 |
+
if not x:
|
| 188 |
+
return ctx.zero
|
| 189 |
+
if ctx.mag(x) < -ctx.prec:
|
| 190 |
+
return x - 0.5*x**2
|
| 191 |
+
return ctx.log(ctx.fadd(1, x, prec=2*ctx.prec))
|
| 192 |
+
|
| 193 |
+
@defun_wrapped
|
| 194 |
+
def powm1(ctx, x, y):
|
| 195 |
+
mag = ctx.mag
|
| 196 |
+
one = ctx.one
|
| 197 |
+
w = x**y - one
|
| 198 |
+
M = mag(w)
|
| 199 |
+
# Only moderate cancellation
|
| 200 |
+
if M > -8:
|
| 201 |
+
return w
|
| 202 |
+
# Check for the only possible exact cases
|
| 203 |
+
if not w:
|
| 204 |
+
if (not y) or (x in (1, -1, 1j, -1j) and ctx.isint(y)):
|
| 205 |
+
return w
|
| 206 |
+
x1 = x - one
|
| 207 |
+
magy = mag(y)
|
| 208 |
+
lnx = ctx.ln(x)
|
| 209 |
+
# Small y: x^y - 1 ~ log(x)*y + O(log(x)^2 * y^2)
|
| 210 |
+
if magy + mag(lnx) < -ctx.prec:
|
| 211 |
+
return lnx*y + (lnx*y)**2/2
|
| 212 |
+
# TODO: accurately eval the smaller of the real/imag part
|
| 213 |
+
return ctx.sum_accurately(lambda: iter([x**y, -1]), 1)
|
| 214 |
+
|
| 215 |
+
@defun
|
| 216 |
+
def _rootof1(ctx, k, n):
|
| 217 |
+
k = int(k)
|
| 218 |
+
n = int(n)
|
| 219 |
+
k %= n
|
| 220 |
+
if not k:
|
| 221 |
+
return ctx.one
|
| 222 |
+
elif 2*k == n:
|
| 223 |
+
return -ctx.one
|
| 224 |
+
elif 4*k == n:
|
| 225 |
+
return ctx.j
|
| 226 |
+
elif 4*k == 3*n:
|
| 227 |
+
return -ctx.j
|
| 228 |
+
return ctx.expjpi(2*ctx.mpf(k)/n)
|
| 229 |
+
|
| 230 |
+
@defun
|
| 231 |
+
def root(ctx, x, n, k=0):
|
| 232 |
+
n = int(n)
|
| 233 |
+
x = ctx.convert(x)
|
| 234 |
+
if k:
|
| 235 |
+
# Special case: there is an exact real root
|
| 236 |
+
if (n & 1 and 2*k == n-1) and (not ctx.im(x)) and (ctx.re(x) < 0):
|
| 237 |
+
return -ctx.root(-x, n)
|
| 238 |
+
# Multiply by root of unity
|
| 239 |
+
prec = ctx.prec
|
| 240 |
+
try:
|
| 241 |
+
ctx.prec += 10
|
| 242 |
+
v = ctx.root(x, n, 0) * ctx._rootof1(k, n)
|
| 243 |
+
finally:
|
| 244 |
+
ctx.prec = prec
|
| 245 |
+
return +v
|
| 246 |
+
return ctx._nthroot(x, n)
|
| 247 |
+
|
| 248 |
+
@defun
|
| 249 |
+
def unitroots(ctx, n, primitive=False):
|
| 250 |
+
gcd = ctx._gcd
|
| 251 |
+
prec = ctx.prec
|
| 252 |
+
try:
|
| 253 |
+
ctx.prec += 10
|
| 254 |
+
if primitive:
|
| 255 |
+
v = [ctx._rootof1(k,n) for k in range(n) if gcd(k,n) == 1]
|
| 256 |
+
else:
|
| 257 |
+
# TODO: this can be done *much* faster
|
| 258 |
+
v = [ctx._rootof1(k,n) for k in range(n)]
|
| 259 |
+
finally:
|
| 260 |
+
ctx.prec = prec
|
| 261 |
+
return [+x for x in v]
|
| 262 |
+
|
| 263 |
+
@defun
|
| 264 |
+
def arg(ctx, x):
|
| 265 |
+
x = ctx.convert(x)
|
| 266 |
+
re = ctx._re(x)
|
| 267 |
+
im = ctx._im(x)
|
| 268 |
+
return ctx.atan2(im, re)
|
| 269 |
+
|
| 270 |
+
@defun
|
| 271 |
+
def fabs(ctx, x):
|
| 272 |
+
return abs(ctx.convert(x))
|
| 273 |
+
|
| 274 |
+
@defun
|
| 275 |
+
def re(ctx, x):
|
| 276 |
+
x = ctx.convert(x)
|
| 277 |
+
if hasattr(x, "real"): # py2.5 doesn't have .real/.imag for all numbers
|
| 278 |
+
return x.real
|
| 279 |
+
return x
|
| 280 |
+
|
| 281 |
+
@defun
|
| 282 |
+
def im(ctx, x):
|
| 283 |
+
x = ctx.convert(x)
|
| 284 |
+
if hasattr(x, "imag"): # py2.5 doesn't have .real/.imag for all numbers
|
| 285 |
+
return x.imag
|
| 286 |
+
return ctx.zero
|
| 287 |
+
|
| 288 |
+
@defun
|
| 289 |
+
def conj(ctx, x):
|
| 290 |
+
x = ctx.convert(x)
|
| 291 |
+
try:
|
| 292 |
+
return x.conjugate()
|
| 293 |
+
except AttributeError:
|
| 294 |
+
return x
|
| 295 |
+
|
| 296 |
+
@defun
|
| 297 |
+
def polar(ctx, z):
|
| 298 |
+
return (ctx.fabs(z), ctx.arg(z))
|
| 299 |
+
|
| 300 |
+
@defun_wrapped
|
| 301 |
+
def rect(ctx, r, phi):
|
| 302 |
+
return r * ctx.mpc(*ctx.cos_sin(phi))
|
| 303 |
+
|
| 304 |
+
@defun
|
| 305 |
+
def log(ctx, x, b=None):
|
| 306 |
+
if b is None:
|
| 307 |
+
return ctx.ln(x)
|
| 308 |
+
wp = ctx.prec + 20
|
| 309 |
+
return ctx.ln(x, prec=wp) / ctx.ln(b, prec=wp)
|
| 310 |
+
|
| 311 |
+
@defun
|
| 312 |
+
def log10(ctx, x):
|
| 313 |
+
return ctx.log(x, 10)
|
| 314 |
+
|
| 315 |
+
@defun
|
| 316 |
+
def fmod(ctx, x, y):
|
| 317 |
+
return ctx.convert(x) % ctx.convert(y)
|
| 318 |
+
|
| 319 |
+
@defun
|
| 320 |
+
def degrees(ctx, x):
|
| 321 |
+
return x / ctx.degree
|
| 322 |
+
|
| 323 |
+
@defun
|
| 324 |
+
def radians(ctx, x):
|
| 325 |
+
return x * ctx.degree
|
| 326 |
+
|
| 327 |
+
def _lambertw_special(ctx, z, k):
|
| 328 |
+
# W(0,0) = 0; all other branches are singular
|
| 329 |
+
if not z:
|
| 330 |
+
if not k:
|
| 331 |
+
return z
|
| 332 |
+
return ctx.ninf + z
|
| 333 |
+
if z == ctx.inf:
|
| 334 |
+
if k == 0:
|
| 335 |
+
return z
|
| 336 |
+
else:
|
| 337 |
+
return z + 2*k*ctx.pi*ctx.j
|
| 338 |
+
if z == ctx.ninf:
|
| 339 |
+
return (-z) + (2*k+1)*ctx.pi*ctx.j
|
| 340 |
+
# Some kind of nan or complex inf/nan?
|
| 341 |
+
return ctx.ln(z)
|
| 342 |
+
|
| 343 |
+
import math
|
| 344 |
+
import cmath
|
| 345 |
+
|
| 346 |
+
def _lambertw_approx_hybrid(z, k):
|
| 347 |
+
imag_sign = 0
|
| 348 |
+
if hasattr(z, "imag"):
|
| 349 |
+
x = float(z.real)
|
| 350 |
+
y = z.imag
|
| 351 |
+
if y:
|
| 352 |
+
imag_sign = (-1) ** (y < 0)
|
| 353 |
+
y = float(y)
|
| 354 |
+
else:
|
| 355 |
+
x = float(z)
|
| 356 |
+
y = 0.0
|
| 357 |
+
imag_sign = 0
|
| 358 |
+
# hack to work regardless of whether Python supports -0.0
|
| 359 |
+
if not y:
|
| 360 |
+
y = 0.0
|
| 361 |
+
z = complex(x,y)
|
| 362 |
+
if k == 0:
|
| 363 |
+
if -4.0 < y < 4.0 and -1.0 < x < 2.5:
|
| 364 |
+
if imag_sign:
|
| 365 |
+
# Taylor series in upper/lower half-plane
|
| 366 |
+
if y > 1.00: return (0.876+0.645j) + (0.118-0.174j)*(z-(0.75+2.5j))
|
| 367 |
+
if y > 0.25: return (0.505+0.204j) + (0.375-0.132j)*(z-(0.75+0.5j))
|
| 368 |
+
if y < -1.00: return (0.876-0.645j) + (0.118+0.174j)*(z-(0.75-2.5j))
|
| 369 |
+
if y < -0.25: return (0.505-0.204j) + (0.375+0.132j)*(z-(0.75-0.5j))
|
| 370 |
+
# Taylor series near -1
|
| 371 |
+
if x < -0.5:
|
| 372 |
+
if imag_sign >= 0:
|
| 373 |
+
return (-0.318+1.34j) + (-0.697-0.593j)*(z+1)
|
| 374 |
+
else:
|
| 375 |
+
return (-0.318-1.34j) + (-0.697+0.593j)*(z+1)
|
| 376 |
+
# return real type
|
| 377 |
+
r = -0.367879441171442
|
| 378 |
+
if (not imag_sign) and x > r:
|
| 379 |
+
z = x
|
| 380 |
+
# Singularity near -1/e
|
| 381 |
+
if x < -0.2:
|
| 382 |
+
return -1 + 2.33164398159712*(z-r)**0.5 - 1.81218788563936*(z-r)
|
| 383 |
+
# Taylor series near 0
|
| 384 |
+
if x < 0.5: return z
|
| 385 |
+
# Simple linear approximation
|
| 386 |
+
return 0.2 + 0.3*z
|
| 387 |
+
if (not imag_sign) and x > 0.0:
|
| 388 |
+
L1 = math.log(x); L2 = math.log(L1)
|
| 389 |
+
else:
|
| 390 |
+
L1 = cmath.log(z); L2 = cmath.log(L1)
|
| 391 |
+
elif k == -1:
|
| 392 |
+
# return real type
|
| 393 |
+
r = -0.367879441171442
|
| 394 |
+
if (not imag_sign) and r < x < 0.0:
|
| 395 |
+
z = x
|
| 396 |
+
if (imag_sign >= 0) and y < 0.1 and -0.6 < x < -0.2:
|
| 397 |
+
return -1 - 2.33164398159712*(z-r)**0.5 - 1.81218788563936*(z-r)
|
| 398 |
+
if (not imag_sign) and -0.2 <= x < 0.0:
|
| 399 |
+
L1 = math.log(-x)
|
| 400 |
+
return L1 - math.log(-L1)
|
| 401 |
+
else:
|
| 402 |
+
if imag_sign == -1 and (not y) and x < 0.0:
|
| 403 |
+
L1 = cmath.log(z) - 3.1415926535897932j
|
| 404 |
+
else:
|
| 405 |
+
L1 = cmath.log(z) - 6.2831853071795865j
|
| 406 |
+
L2 = cmath.log(L1)
|
| 407 |
+
return L1 - L2 + L2/L1 + L2*(L2-2)/(2*L1**2)
|
| 408 |
+
|
| 409 |
+
def _lambertw_series(ctx, z, k, tol):
|
| 410 |
+
"""
|
| 411 |
+
Return rough approximation for W_k(z) from an asymptotic series,
|
| 412 |
+
sufficiently accurate for the Halley iteration to converge to
|
| 413 |
+
the correct value.
|
| 414 |
+
"""
|
| 415 |
+
magz = ctx.mag(z)
|
| 416 |
+
if (-10 < magz < 900) and (-1000 < k < 1000):
|
| 417 |
+
# Near the branch point at -1/e
|
| 418 |
+
if magz < 1 and abs(z+0.36787944117144) < 0.05:
|
| 419 |
+
if k == 0 or (k == -1 and ctx._im(z) >= 0) or \
|
| 420 |
+
(k == 1 and ctx._im(z) < 0):
|
| 421 |
+
delta = ctx.sum_accurately(lambda: [z, ctx.exp(-1)])
|
| 422 |
+
cancellation = -ctx.mag(delta)
|
| 423 |
+
ctx.prec += cancellation
|
| 424 |
+
# Use series given in Corless et al.
|
| 425 |
+
p = ctx.sqrt(2*(ctx.e*z+1))
|
| 426 |
+
ctx.prec -= cancellation
|
| 427 |
+
u = {0:ctx.mpf(-1), 1:ctx.mpf(1)}
|
| 428 |
+
a = {0:ctx.mpf(2), 1:ctx.mpf(-1)}
|
| 429 |
+
if k != 0:
|
| 430 |
+
p = -p
|
| 431 |
+
s = ctx.zero
|
| 432 |
+
# The series converges, so we could use it directly, but unless
|
| 433 |
+
# *extremely* close, it is better to just use the first few
|
| 434 |
+
# terms to get a good approximation for the iteration
|
| 435 |
+
for l in xrange(max(2,cancellation)):
|
| 436 |
+
if l not in u:
|
| 437 |
+
a[l] = ctx.fsum(u[j]*u[l+1-j] for j in xrange(2,l))
|
| 438 |
+
u[l] = (l-1)*(u[l-2]/2+a[l-2]/4)/(l+1)-a[l]/2-u[l-1]/(l+1)
|
| 439 |
+
term = u[l] * p**l
|
| 440 |
+
s += term
|
| 441 |
+
if ctx.mag(term) < -tol:
|
| 442 |
+
return s, True
|
| 443 |
+
l += 1
|
| 444 |
+
ctx.prec += cancellation//2
|
| 445 |
+
return s, False
|
| 446 |
+
if k == 0 or k == -1:
|
| 447 |
+
return _lambertw_approx_hybrid(z, k), False
|
| 448 |
+
if k == 0:
|
| 449 |
+
if magz < -1:
|
| 450 |
+
return z*(1-z), False
|
| 451 |
+
L1 = ctx.ln(z)
|
| 452 |
+
L2 = ctx.ln(L1)
|
| 453 |
+
elif k == -1 and (not ctx._im(z)) and (-0.36787944117144 < ctx._re(z) < 0):
|
| 454 |
+
L1 = ctx.ln(-z)
|
| 455 |
+
return L1 - ctx.ln(-L1), False
|
| 456 |
+
else:
|
| 457 |
+
# This holds both as z -> 0 and z -> inf.
|
| 458 |
+
# Relative error is O(1/log(z)).
|
| 459 |
+
L1 = ctx.ln(z) + 2j*ctx.pi*k
|
| 460 |
+
L2 = ctx.ln(L1)
|
| 461 |
+
return L1 - L2 + L2/L1 + L2*(L2-2)/(2*L1**2), False
|
| 462 |
+
|
| 463 |
+
@defun
|
| 464 |
+
def lambertw(ctx, z, k=0):
|
| 465 |
+
z = ctx.convert(z)
|
| 466 |
+
k = int(k)
|
| 467 |
+
if not ctx.isnormal(z):
|
| 468 |
+
return _lambertw_special(ctx, z, k)
|
| 469 |
+
prec = ctx.prec
|
| 470 |
+
ctx.prec += 20 + ctx.mag(k or 1)
|
| 471 |
+
wp = ctx.prec
|
| 472 |
+
tol = wp - 5
|
| 473 |
+
w, done = _lambertw_series(ctx, z, k, tol)
|
| 474 |
+
if not done:
|
| 475 |
+
# Use Halley iteration to solve w*exp(w) = z
|
| 476 |
+
two = ctx.mpf(2)
|
| 477 |
+
for i in xrange(100):
|
| 478 |
+
ew = ctx.exp(w)
|
| 479 |
+
wew = w*ew
|
| 480 |
+
wewz = wew-z
|
| 481 |
+
wn = w - wewz/(wew+ew-(w+two)*wewz/(two*w+two))
|
| 482 |
+
if ctx.mag(wn-w) <= ctx.mag(wn) - tol:
|
| 483 |
+
w = wn
|
| 484 |
+
break
|
| 485 |
+
else:
|
| 486 |
+
w = wn
|
| 487 |
+
if i == 100:
|
| 488 |
+
ctx.warn("Lambert W iteration failed to converge for z = %s" % z)
|
| 489 |
+
ctx.prec = prec
|
| 490 |
+
return +w
|
| 491 |
+
|
| 492 |
+
@defun_wrapped
|
| 493 |
+
def bell(ctx, n, x=1):
|
| 494 |
+
x = ctx.convert(x)
|
| 495 |
+
if not n:
|
| 496 |
+
if ctx.isnan(x):
|
| 497 |
+
return x
|
| 498 |
+
return type(x)(1)
|
| 499 |
+
if ctx.isinf(x) or ctx.isinf(n) or ctx.isnan(x) or ctx.isnan(n):
|
| 500 |
+
return x**n
|
| 501 |
+
if n == 1: return x
|
| 502 |
+
if n == 2: return x*(x+1)
|
| 503 |
+
if x == 0: return ctx.sincpi(n)
|
| 504 |
+
return _polyexp(ctx, n, x, True) / ctx.exp(x)
|
| 505 |
+
|
| 506 |
+
def _polyexp(ctx, n, x, extra=False):
|
| 507 |
+
def _terms():
|
| 508 |
+
if extra:
|
| 509 |
+
yield ctx.sincpi(n)
|
| 510 |
+
t = x
|
| 511 |
+
k = 1
|
| 512 |
+
while 1:
|
| 513 |
+
yield k**n * t
|
| 514 |
+
k += 1
|
| 515 |
+
t = t*x/k
|
| 516 |
+
return ctx.sum_accurately(_terms, check_step=4)
|
| 517 |
+
|
| 518 |
+
@defun_wrapped
|
| 519 |
+
def polyexp(ctx, s, z):
|
| 520 |
+
if ctx.isinf(z) or ctx.isinf(s) or ctx.isnan(z) or ctx.isnan(s):
|
| 521 |
+
return z**s
|
| 522 |
+
if z == 0: return z*s
|
| 523 |
+
if s == 0: return ctx.expm1(z)
|
| 524 |
+
if s == 1: return ctx.exp(z)*z
|
| 525 |
+
if s == 2: return ctx.exp(z)*z*(z+1)
|
| 526 |
+
return _polyexp(ctx, s, z)
|
| 527 |
+
|
| 528 |
+
@defun_wrapped
|
| 529 |
+
def cyclotomic(ctx, n, z):
|
| 530 |
+
n = int(n)
|
| 531 |
+
if n < 0:
|
| 532 |
+
raise ValueError("n cannot be negative")
|
| 533 |
+
p = ctx.one
|
| 534 |
+
if n == 0:
|
| 535 |
+
return p
|
| 536 |
+
if n == 1:
|
| 537 |
+
return z - p
|
| 538 |
+
if n == 2:
|
| 539 |
+
return z + p
|
| 540 |
+
# Use divisor product representation. Unfortunately, this sometimes
|
| 541 |
+
# includes singularities for roots of unity, which we have to cancel out.
|
| 542 |
+
# Matching zeros/poles pairwise, we have (1-z^a)/(1-z^b) ~ a/b + O(z-1).
|
| 543 |
+
a_prod = 1
|
| 544 |
+
b_prod = 1
|
| 545 |
+
num_zeros = 0
|
| 546 |
+
num_poles = 0
|
| 547 |
+
for d in range(1,n+1):
|
| 548 |
+
if not n % d:
|
| 549 |
+
w = ctx.moebius(n//d)
|
| 550 |
+
# Use powm1 because it is important that we get 0 only
|
| 551 |
+
# if it really is exactly 0
|
| 552 |
+
b = -ctx.powm1(z, d)
|
| 553 |
+
if b:
|
| 554 |
+
p *= b**w
|
| 555 |
+
else:
|
| 556 |
+
if w == 1:
|
| 557 |
+
a_prod *= d
|
| 558 |
+
num_zeros += 1
|
| 559 |
+
elif w == -1:
|
| 560 |
+
b_prod *= d
|
| 561 |
+
num_poles += 1
|
| 562 |
+
#print n, num_zeros, num_poles
|
| 563 |
+
if num_zeros:
|
| 564 |
+
if num_zeros > num_poles:
|
| 565 |
+
p *= 0
|
| 566 |
+
else:
|
| 567 |
+
p *= a_prod
|
| 568 |
+
p /= b_prod
|
| 569 |
+
return p
|
| 570 |
+
|
| 571 |
+
@defun
|
| 572 |
+
def mangoldt(ctx, n):
|
| 573 |
+
r"""
|
| 574 |
+
Evaluates the von Mangoldt function `\Lambda(n) = \log p`
|
| 575 |
+
if `n = p^k` a power of a prime, and `\Lambda(n) = 0` otherwise.
|
| 576 |
+
|
| 577 |
+
**Examples**
|
| 578 |
+
|
| 579 |
+
>>> from mpmath import *
|
| 580 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 581 |
+
>>> [mangoldt(n) for n in range(-2,3)]
|
| 582 |
+
[0.0, 0.0, 0.0, 0.0, 0.6931471805599453094172321]
|
| 583 |
+
>>> mangoldt(6)
|
| 584 |
+
0.0
|
| 585 |
+
>>> mangoldt(7)
|
| 586 |
+
1.945910149055313305105353
|
| 587 |
+
>>> mangoldt(8)
|
| 588 |
+
0.6931471805599453094172321
|
| 589 |
+
>>> fsum(mangoldt(n) for n in range(101))
|
| 590 |
+
94.04531122935739224600493
|
| 591 |
+
>>> fsum(mangoldt(n) for n in range(10001))
|
| 592 |
+
10013.39669326311478372032
|
| 593 |
+
|
| 594 |
+
"""
|
| 595 |
+
n = int(n)
|
| 596 |
+
if n < 2:
|
| 597 |
+
return ctx.zero
|
| 598 |
+
if n % 2 == 0:
|
| 599 |
+
# Must be a power of two
|
| 600 |
+
if n & (n-1) == 0:
|
| 601 |
+
return +ctx.ln2
|
| 602 |
+
else:
|
| 603 |
+
return ctx.zero
|
| 604 |
+
# TODO: the following could be generalized into a perfect
|
| 605 |
+
# power testing function
|
| 606 |
+
# ---
|
| 607 |
+
# Look for a small factor
|
| 608 |
+
for p in (3,5,7,11,13,17,19,23,29,31):
|
| 609 |
+
if not n % p:
|
| 610 |
+
q, r = n // p, 0
|
| 611 |
+
while q > 1:
|
| 612 |
+
q, r = divmod(q, p)
|
| 613 |
+
if r:
|
| 614 |
+
return ctx.zero
|
| 615 |
+
return ctx.ln(p)
|
| 616 |
+
if ctx.isprime(n):
|
| 617 |
+
return ctx.ln(n)
|
| 618 |
+
# Obviously, we could use arbitrary-precision arithmetic for this...
|
| 619 |
+
if n > 10**30:
|
| 620 |
+
raise NotImplementedError
|
| 621 |
+
k = 2
|
| 622 |
+
while 1:
|
| 623 |
+
p = int(n**(1./k) + 0.5)
|
| 624 |
+
if p < 2:
|
| 625 |
+
return ctx.zero
|
| 626 |
+
if p ** k == n:
|
| 627 |
+
if ctx.isprime(p):
|
| 628 |
+
return ctx.ln(p)
|
| 629 |
+
k += 1
|
| 630 |
+
|
| 631 |
+
@defun
|
| 632 |
+
def stirling1(ctx, n, k, exact=False):
|
| 633 |
+
v = ctx._stirling1(int(n), int(k))
|
| 634 |
+
if exact:
|
| 635 |
+
return int(v)
|
| 636 |
+
else:
|
| 637 |
+
return ctx.mpf(v)
|
| 638 |
+
|
| 639 |
+
@defun
|
| 640 |
+
def stirling2(ctx, n, k, exact=False):
|
| 641 |
+
v = ctx._stirling2(int(n), int(k))
|
| 642 |
+
if exact:
|
| 643 |
+
return int(v)
|
| 644 |
+
else:
|
| 645 |
+
return ctx.mpf(v)
|
.venv/lib/python3.11/site-packages/mpmath/functions/hypergeometric.py
ADDED
|
@@ -0,0 +1,1413 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ..libmp.backend import xrange
|
| 2 |
+
from .functions import defun, defun_wrapped
|
| 3 |
+
|
| 4 |
+
def _check_need_perturb(ctx, terms, prec, discard_known_zeros):
|
| 5 |
+
perturb = recompute = False
|
| 6 |
+
extraprec = 0
|
| 7 |
+
discard = []
|
| 8 |
+
for term_index, term in enumerate(terms):
|
| 9 |
+
w_s, c_s, alpha_s, beta_s, a_s, b_s, z = term
|
| 10 |
+
have_singular_nongamma_weight = False
|
| 11 |
+
# Avoid division by zero in leading factors (TODO:
|
| 12 |
+
# also check for near division by zero?)
|
| 13 |
+
for k, w in enumerate(w_s):
|
| 14 |
+
if not w:
|
| 15 |
+
if ctx.re(c_s[k]) <= 0 and c_s[k]:
|
| 16 |
+
perturb = recompute = True
|
| 17 |
+
have_singular_nongamma_weight = True
|
| 18 |
+
pole_count = [0, 0, 0]
|
| 19 |
+
# Check for gamma and series poles and near-poles
|
| 20 |
+
for data_index, data in enumerate([alpha_s, beta_s, b_s]):
|
| 21 |
+
for i, x in enumerate(data):
|
| 22 |
+
n, d = ctx.nint_distance(x)
|
| 23 |
+
# Poles
|
| 24 |
+
if n > 0:
|
| 25 |
+
continue
|
| 26 |
+
if d == ctx.ninf:
|
| 27 |
+
# OK if we have a polynomial
|
| 28 |
+
# ------------------------------
|
| 29 |
+
ok = False
|
| 30 |
+
if data_index == 2:
|
| 31 |
+
for u in a_s:
|
| 32 |
+
if ctx.isnpint(u) and u >= int(n):
|
| 33 |
+
ok = True
|
| 34 |
+
break
|
| 35 |
+
if ok:
|
| 36 |
+
continue
|
| 37 |
+
pole_count[data_index] += 1
|
| 38 |
+
# ------------------------------
|
| 39 |
+
#perturb = recompute = True
|
| 40 |
+
#return perturb, recompute, extraprec
|
| 41 |
+
elif d < -4:
|
| 42 |
+
extraprec += -d
|
| 43 |
+
recompute = True
|
| 44 |
+
if discard_known_zeros and pole_count[1] > pole_count[0] + pole_count[2] \
|
| 45 |
+
and not have_singular_nongamma_weight:
|
| 46 |
+
discard.append(term_index)
|
| 47 |
+
elif sum(pole_count):
|
| 48 |
+
perturb = recompute = True
|
| 49 |
+
return perturb, recompute, extraprec, discard
|
| 50 |
+
|
| 51 |
+
_hypercomb_msg = """
|
| 52 |
+
hypercomb() failed to converge to the requested %i bits of accuracy
|
| 53 |
+
using a working precision of %i bits. The function value may be zero or
|
| 54 |
+
infinite; try passing zeroprec=N or infprec=M to bound finite values between
|
| 55 |
+
2^(-N) and 2^M. Otherwise try a higher maxprec or maxterms.
|
| 56 |
+
"""
|
| 57 |
+
|
| 58 |
+
@defun
|
| 59 |
+
def hypercomb(ctx, function, params=[], discard_known_zeros=True, **kwargs):
|
| 60 |
+
orig = ctx.prec
|
| 61 |
+
sumvalue = ctx.zero
|
| 62 |
+
dist = ctx.nint_distance
|
| 63 |
+
ninf = ctx.ninf
|
| 64 |
+
orig_params = params[:]
|
| 65 |
+
verbose = kwargs.get('verbose', False)
|
| 66 |
+
maxprec = kwargs.get('maxprec', ctx._default_hyper_maxprec(orig))
|
| 67 |
+
kwargs['maxprec'] = maxprec # For calls to hypsum
|
| 68 |
+
zeroprec = kwargs.get('zeroprec')
|
| 69 |
+
infprec = kwargs.get('infprec')
|
| 70 |
+
perturbed_reference_value = None
|
| 71 |
+
hextra = 0
|
| 72 |
+
try:
|
| 73 |
+
while 1:
|
| 74 |
+
ctx.prec += 10
|
| 75 |
+
if ctx.prec > maxprec:
|
| 76 |
+
raise ValueError(_hypercomb_msg % (orig, ctx.prec))
|
| 77 |
+
orig2 = ctx.prec
|
| 78 |
+
params = orig_params[:]
|
| 79 |
+
terms = function(*params)
|
| 80 |
+
if verbose:
|
| 81 |
+
print()
|
| 82 |
+
print("ENTERING hypercomb main loop")
|
| 83 |
+
print("prec =", ctx.prec)
|
| 84 |
+
print("hextra", hextra)
|
| 85 |
+
perturb, recompute, extraprec, discard = \
|
| 86 |
+
_check_need_perturb(ctx, terms, orig, discard_known_zeros)
|
| 87 |
+
ctx.prec += extraprec
|
| 88 |
+
if perturb:
|
| 89 |
+
if "hmag" in kwargs:
|
| 90 |
+
hmag = kwargs["hmag"]
|
| 91 |
+
elif ctx._fixed_precision:
|
| 92 |
+
hmag = int(ctx.prec*0.3)
|
| 93 |
+
else:
|
| 94 |
+
hmag = orig + 10 + hextra
|
| 95 |
+
h = ctx.ldexp(ctx.one, -hmag)
|
| 96 |
+
ctx.prec = orig2 + 10 + hmag + 10
|
| 97 |
+
for k in range(len(params)):
|
| 98 |
+
params[k] += h
|
| 99 |
+
# Heuristically ensure that the perturbations
|
| 100 |
+
# are "independent" so that two perturbations
|
| 101 |
+
# don't accidentally cancel each other out
|
| 102 |
+
# in a subtraction.
|
| 103 |
+
h += h/(k+1)
|
| 104 |
+
if recompute:
|
| 105 |
+
terms = function(*params)
|
| 106 |
+
if discard_known_zeros:
|
| 107 |
+
terms = [term for (i, term) in enumerate(terms) if i not in discard]
|
| 108 |
+
if not terms:
|
| 109 |
+
return ctx.zero
|
| 110 |
+
evaluated_terms = []
|
| 111 |
+
for term_index, term_data in enumerate(terms):
|
| 112 |
+
w_s, c_s, alpha_s, beta_s, a_s, b_s, z = term_data
|
| 113 |
+
if verbose:
|
| 114 |
+
print()
|
| 115 |
+
print(" Evaluating term %i/%i : %iF%i" % \
|
| 116 |
+
(term_index+1, len(terms), len(a_s), len(b_s)))
|
| 117 |
+
print(" powers", ctx.nstr(w_s), ctx.nstr(c_s))
|
| 118 |
+
print(" gamma", ctx.nstr(alpha_s), ctx.nstr(beta_s))
|
| 119 |
+
print(" hyper", ctx.nstr(a_s), ctx.nstr(b_s))
|
| 120 |
+
print(" z", ctx.nstr(z))
|
| 121 |
+
#v = ctx.hyper(a_s, b_s, z, **kwargs)
|
| 122 |
+
#for a in alpha_s: v *= ctx.gamma(a)
|
| 123 |
+
#for b in beta_s: v *= ctx.rgamma(b)
|
| 124 |
+
#for w, c in zip(w_s, c_s): v *= ctx.power(w, c)
|
| 125 |
+
v = ctx.fprod([ctx.hyper(a_s, b_s, z, **kwargs)] + \
|
| 126 |
+
[ctx.gamma(a) for a in alpha_s] + \
|
| 127 |
+
[ctx.rgamma(b) for b in beta_s] + \
|
| 128 |
+
[ctx.power(w,c) for (w,c) in zip(w_s,c_s)])
|
| 129 |
+
if verbose:
|
| 130 |
+
print(" Value:", v)
|
| 131 |
+
evaluated_terms.append(v)
|
| 132 |
+
|
| 133 |
+
if len(terms) == 1 and (not perturb):
|
| 134 |
+
sumvalue = evaluated_terms[0]
|
| 135 |
+
break
|
| 136 |
+
|
| 137 |
+
if ctx._fixed_precision:
|
| 138 |
+
sumvalue = ctx.fsum(evaluated_terms)
|
| 139 |
+
break
|
| 140 |
+
|
| 141 |
+
sumvalue = ctx.fsum(evaluated_terms)
|
| 142 |
+
term_magnitudes = [ctx.mag(x) for x in evaluated_terms]
|
| 143 |
+
max_magnitude = max(term_magnitudes)
|
| 144 |
+
sum_magnitude = ctx.mag(sumvalue)
|
| 145 |
+
cancellation = max_magnitude - sum_magnitude
|
| 146 |
+
if verbose:
|
| 147 |
+
print()
|
| 148 |
+
print(" Cancellation:", cancellation, "bits")
|
| 149 |
+
print(" Increased precision:", ctx.prec - orig, "bits")
|
| 150 |
+
|
| 151 |
+
precision_ok = cancellation < ctx.prec - orig
|
| 152 |
+
|
| 153 |
+
if zeroprec is None:
|
| 154 |
+
zero_ok = False
|
| 155 |
+
else:
|
| 156 |
+
zero_ok = max_magnitude - ctx.prec < -zeroprec
|
| 157 |
+
if infprec is None:
|
| 158 |
+
inf_ok = False
|
| 159 |
+
else:
|
| 160 |
+
inf_ok = max_magnitude > infprec
|
| 161 |
+
|
| 162 |
+
if precision_ok and (not perturb) or ctx.isnan(cancellation):
|
| 163 |
+
break
|
| 164 |
+
elif precision_ok:
|
| 165 |
+
if perturbed_reference_value is None:
|
| 166 |
+
hextra += 20
|
| 167 |
+
perturbed_reference_value = sumvalue
|
| 168 |
+
continue
|
| 169 |
+
elif ctx.mag(sumvalue - perturbed_reference_value) <= \
|
| 170 |
+
ctx.mag(sumvalue) - orig:
|
| 171 |
+
break
|
| 172 |
+
elif zero_ok:
|
| 173 |
+
sumvalue = ctx.zero
|
| 174 |
+
break
|
| 175 |
+
elif inf_ok:
|
| 176 |
+
sumvalue = ctx.inf
|
| 177 |
+
break
|
| 178 |
+
elif 'hmag' in kwargs:
|
| 179 |
+
break
|
| 180 |
+
else:
|
| 181 |
+
hextra *= 2
|
| 182 |
+
perturbed_reference_value = sumvalue
|
| 183 |
+
# Increase precision
|
| 184 |
+
else:
|
| 185 |
+
increment = min(max(cancellation, orig//2), max(extraprec,orig))
|
| 186 |
+
ctx.prec += increment
|
| 187 |
+
if verbose:
|
| 188 |
+
print(" Must start over with increased precision")
|
| 189 |
+
continue
|
| 190 |
+
finally:
|
| 191 |
+
ctx.prec = orig
|
| 192 |
+
return +sumvalue
|
| 193 |
+
|
| 194 |
+
@defun
|
| 195 |
+
def hyper(ctx, a_s, b_s, z, **kwargs):
|
| 196 |
+
"""
|
| 197 |
+
Hypergeometric function, general case.
|
| 198 |
+
"""
|
| 199 |
+
z = ctx.convert(z)
|
| 200 |
+
p = len(a_s)
|
| 201 |
+
q = len(b_s)
|
| 202 |
+
a_s = [ctx._convert_param(a) for a in a_s]
|
| 203 |
+
b_s = [ctx._convert_param(b) for b in b_s]
|
| 204 |
+
# Reduce degree by eliminating common parameters
|
| 205 |
+
if kwargs.get('eliminate', True):
|
| 206 |
+
elim_nonpositive = kwargs.get('eliminate_all', False)
|
| 207 |
+
i = 0
|
| 208 |
+
while i < q and a_s:
|
| 209 |
+
b = b_s[i]
|
| 210 |
+
if b in a_s and (elim_nonpositive or not ctx.isnpint(b[0])):
|
| 211 |
+
a_s.remove(b)
|
| 212 |
+
b_s.remove(b)
|
| 213 |
+
p -= 1
|
| 214 |
+
q -= 1
|
| 215 |
+
else:
|
| 216 |
+
i += 1
|
| 217 |
+
# Handle special cases
|
| 218 |
+
if p == 0:
|
| 219 |
+
if q == 1: return ctx._hyp0f1(b_s, z, **kwargs)
|
| 220 |
+
elif q == 0: return ctx.exp(z)
|
| 221 |
+
elif p == 1:
|
| 222 |
+
if q == 1: return ctx._hyp1f1(a_s, b_s, z, **kwargs)
|
| 223 |
+
elif q == 2: return ctx._hyp1f2(a_s, b_s, z, **kwargs)
|
| 224 |
+
elif q == 0: return ctx._hyp1f0(a_s[0][0], z)
|
| 225 |
+
elif p == 2:
|
| 226 |
+
if q == 1: return ctx._hyp2f1(a_s, b_s, z, **kwargs)
|
| 227 |
+
elif q == 2: return ctx._hyp2f2(a_s, b_s, z, **kwargs)
|
| 228 |
+
elif q == 3: return ctx._hyp2f3(a_s, b_s, z, **kwargs)
|
| 229 |
+
elif q == 0: return ctx._hyp2f0(a_s, b_s, z, **kwargs)
|
| 230 |
+
elif p == q+1:
|
| 231 |
+
return ctx._hypq1fq(p, q, a_s, b_s, z, **kwargs)
|
| 232 |
+
elif p > q+1 and not kwargs.get('force_series'):
|
| 233 |
+
return ctx._hyp_borel(p, q, a_s, b_s, z, **kwargs)
|
| 234 |
+
coeffs, types = zip(*(a_s+b_s))
|
| 235 |
+
return ctx.hypsum(p, q, types, coeffs, z, **kwargs)
|
| 236 |
+
|
| 237 |
+
@defun
|
| 238 |
+
def hyp0f1(ctx,b,z,**kwargs):
|
| 239 |
+
return ctx.hyper([],[b],z,**kwargs)
|
| 240 |
+
|
| 241 |
+
@defun
|
| 242 |
+
def hyp1f1(ctx,a,b,z,**kwargs):
|
| 243 |
+
return ctx.hyper([a],[b],z,**kwargs)
|
| 244 |
+
|
| 245 |
+
@defun
|
| 246 |
+
def hyp1f2(ctx,a1,b1,b2,z,**kwargs):
|
| 247 |
+
return ctx.hyper([a1],[b1,b2],z,**kwargs)
|
| 248 |
+
|
| 249 |
+
@defun
|
| 250 |
+
def hyp2f1(ctx,a,b,c,z,**kwargs):
|
| 251 |
+
return ctx.hyper([a,b],[c],z,**kwargs)
|
| 252 |
+
|
| 253 |
+
@defun
|
| 254 |
+
def hyp2f2(ctx,a1,a2,b1,b2,z,**kwargs):
|
| 255 |
+
return ctx.hyper([a1,a2],[b1,b2],z,**kwargs)
|
| 256 |
+
|
| 257 |
+
@defun
|
| 258 |
+
def hyp2f3(ctx,a1,a2,b1,b2,b3,z,**kwargs):
|
| 259 |
+
return ctx.hyper([a1,a2],[b1,b2,b3],z,**kwargs)
|
| 260 |
+
|
| 261 |
+
@defun
|
| 262 |
+
def hyp2f0(ctx,a,b,z,**kwargs):
|
| 263 |
+
return ctx.hyper([a,b],[],z,**kwargs)
|
| 264 |
+
|
| 265 |
+
@defun
|
| 266 |
+
def hyp3f2(ctx,a1,a2,a3,b1,b2,z,**kwargs):
|
| 267 |
+
return ctx.hyper([a1,a2,a3],[b1,b2],z,**kwargs)
|
| 268 |
+
|
| 269 |
+
@defun_wrapped
|
| 270 |
+
def _hyp1f0(ctx, a, z):
|
| 271 |
+
return (1-z) ** (-a)
|
| 272 |
+
|
| 273 |
+
@defun
|
| 274 |
+
def _hyp0f1(ctx, b_s, z, **kwargs):
|
| 275 |
+
(b, btype), = b_s
|
| 276 |
+
if z:
|
| 277 |
+
magz = ctx.mag(z)
|
| 278 |
+
else:
|
| 279 |
+
magz = 0
|
| 280 |
+
if magz >= 8 and not kwargs.get('force_series'):
|
| 281 |
+
try:
|
| 282 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 283 |
+
# Hypergeometric0F1/06/02/03/0004/
|
| 284 |
+
# TODO: handle the all-real case more efficiently!
|
| 285 |
+
# TODO: figure out how much precision is needed (exponential growth)
|
| 286 |
+
orig = ctx.prec
|
| 287 |
+
try:
|
| 288 |
+
ctx.prec += 12 + magz//2
|
| 289 |
+
def h():
|
| 290 |
+
w = ctx.sqrt(-z)
|
| 291 |
+
jw = ctx.j*w
|
| 292 |
+
u = 1/(4*jw)
|
| 293 |
+
c = ctx.mpq_1_2 - b
|
| 294 |
+
E = ctx.exp(2*jw)
|
| 295 |
+
T1 = ([-jw,E], [c,-1], [], [], [b-ctx.mpq_1_2, ctx.mpq_3_2-b], [], -u)
|
| 296 |
+
T2 = ([jw,E], [c,1], [], [], [b-ctx.mpq_1_2, ctx.mpq_3_2-b], [], u)
|
| 297 |
+
return T1, T2
|
| 298 |
+
v = ctx.hypercomb(h, [], force_series=True)
|
| 299 |
+
v = ctx.gamma(b)/(2*ctx.sqrt(ctx.pi))*v
|
| 300 |
+
finally:
|
| 301 |
+
ctx.prec = orig
|
| 302 |
+
if ctx._is_real_type(b) and ctx._is_real_type(z):
|
| 303 |
+
v = ctx._re(v)
|
| 304 |
+
return +v
|
| 305 |
+
except ctx.NoConvergence:
|
| 306 |
+
pass
|
| 307 |
+
return ctx.hypsum(0, 1, (btype,), [b], z, **kwargs)
|
| 308 |
+
|
| 309 |
+
@defun
|
| 310 |
+
def _hyp1f1(ctx, a_s, b_s, z, **kwargs):
|
| 311 |
+
(a, atype), = a_s
|
| 312 |
+
(b, btype), = b_s
|
| 313 |
+
if not z:
|
| 314 |
+
return ctx.one+z
|
| 315 |
+
magz = ctx.mag(z)
|
| 316 |
+
if magz >= 7 and not (ctx.isint(a) and ctx.re(a) <= 0):
|
| 317 |
+
if ctx.isinf(z):
|
| 318 |
+
if ctx.sign(a) == ctx.sign(b) == ctx.sign(z) == 1:
|
| 319 |
+
return ctx.inf
|
| 320 |
+
return ctx.nan * z
|
| 321 |
+
try:
|
| 322 |
+
try:
|
| 323 |
+
ctx.prec += magz
|
| 324 |
+
sector = ctx._im(z) < 0
|
| 325 |
+
def h(a,b):
|
| 326 |
+
if sector:
|
| 327 |
+
E = ctx.expjpi(ctx.fneg(a, exact=True))
|
| 328 |
+
else:
|
| 329 |
+
E = ctx.expjpi(a)
|
| 330 |
+
rz = 1/z
|
| 331 |
+
T1 = ([E,z], [1,-a], [b], [b-a], [a, 1+a-b], [], -rz)
|
| 332 |
+
T2 = ([ctx.exp(z),z], [1,a-b], [b], [a], [b-a, 1-a], [], rz)
|
| 333 |
+
return T1, T2
|
| 334 |
+
v = ctx.hypercomb(h, [a,b], force_series=True)
|
| 335 |
+
if ctx._is_real_type(a) and ctx._is_real_type(b) and ctx._is_real_type(z):
|
| 336 |
+
v = ctx._re(v)
|
| 337 |
+
return +v
|
| 338 |
+
except ctx.NoConvergence:
|
| 339 |
+
pass
|
| 340 |
+
finally:
|
| 341 |
+
ctx.prec -= magz
|
| 342 |
+
v = ctx.hypsum(1, 1, (atype, btype), [a, b], z, **kwargs)
|
| 343 |
+
return v
|
| 344 |
+
|
| 345 |
+
def _hyp2f1_gosper(ctx,a,b,c,z,**kwargs):
|
| 346 |
+
# Use Gosper's recurrence
|
| 347 |
+
# See http://www.math.utexas.edu/pipermail/maxima/2006/000126.html
|
| 348 |
+
_a,_b,_c,_z = a, b, c, z
|
| 349 |
+
orig = ctx.prec
|
| 350 |
+
maxprec = kwargs.get('maxprec', 100*orig)
|
| 351 |
+
extra = 10
|
| 352 |
+
while 1:
|
| 353 |
+
ctx.prec = orig + extra
|
| 354 |
+
#a = ctx.convert(_a)
|
| 355 |
+
#b = ctx.convert(_b)
|
| 356 |
+
#c = ctx.convert(_c)
|
| 357 |
+
z = ctx.convert(_z)
|
| 358 |
+
d = ctx.mpf(0)
|
| 359 |
+
e = ctx.mpf(1)
|
| 360 |
+
f = ctx.mpf(0)
|
| 361 |
+
k = 0
|
| 362 |
+
# Common subexpression elimination, unfortunately making
|
| 363 |
+
# things a bit unreadable. The formula is quite messy to begin
|
| 364 |
+
# with, though...
|
| 365 |
+
abz = a*b*z
|
| 366 |
+
ch = c * ctx.mpq_1_2
|
| 367 |
+
c1h = (c+1) * ctx.mpq_1_2
|
| 368 |
+
nz = 1-z
|
| 369 |
+
g = z/nz
|
| 370 |
+
abg = a*b*g
|
| 371 |
+
cba = c-b-a
|
| 372 |
+
z2 = z-2
|
| 373 |
+
tol = -ctx.prec - 10
|
| 374 |
+
nstr = ctx.nstr
|
| 375 |
+
nprint = ctx.nprint
|
| 376 |
+
mag = ctx.mag
|
| 377 |
+
maxmag = ctx.ninf
|
| 378 |
+
while 1:
|
| 379 |
+
kch = k+ch
|
| 380 |
+
kakbz = (k+a)*(k+b)*z / (4*(k+1)*kch*(k+c1h))
|
| 381 |
+
d1 = kakbz*(e-(k+cba)*d*g)
|
| 382 |
+
e1 = kakbz*(d*abg+(k+c)*e)
|
| 383 |
+
ft = d*(k*(cba*z+k*z2-c)-abz)/(2*kch*nz)
|
| 384 |
+
f1 = f + e - ft
|
| 385 |
+
maxmag = max(maxmag, mag(f1))
|
| 386 |
+
if mag(f1-f) < tol:
|
| 387 |
+
break
|
| 388 |
+
d, e, f = d1, e1, f1
|
| 389 |
+
k += 1
|
| 390 |
+
cancellation = maxmag - mag(f1)
|
| 391 |
+
if cancellation < extra:
|
| 392 |
+
break
|
| 393 |
+
else:
|
| 394 |
+
extra += cancellation
|
| 395 |
+
if extra > maxprec:
|
| 396 |
+
raise ctx.NoConvergence
|
| 397 |
+
return f1
|
| 398 |
+
|
| 399 |
+
@defun
|
| 400 |
+
def _hyp2f1(ctx, a_s, b_s, z, **kwargs):
|
| 401 |
+
(a, atype), (b, btype) = a_s
|
| 402 |
+
(c, ctype), = b_s
|
| 403 |
+
if z == 1:
|
| 404 |
+
# TODO: the following logic can be simplified
|
| 405 |
+
convergent = ctx.re(c-a-b) > 0
|
| 406 |
+
finite = (ctx.isint(a) and a <= 0) or (ctx.isint(b) and b <= 0)
|
| 407 |
+
zerodiv = ctx.isint(c) and c <= 0 and not \
|
| 408 |
+
((ctx.isint(a) and c <= a <= 0) or (ctx.isint(b) and c <= b <= 0))
|
| 409 |
+
#print "bz", a, b, c, z, convergent, finite, zerodiv
|
| 410 |
+
# Gauss's theorem gives the value if convergent
|
| 411 |
+
if (convergent or finite) and not zerodiv:
|
| 412 |
+
return ctx.gammaprod([c, c-a-b], [c-a, c-b], _infsign=True)
|
| 413 |
+
# Otherwise, there is a pole and we take the
|
| 414 |
+
# sign to be that when approaching from below
|
| 415 |
+
# XXX: this evaluation is not necessarily correct in all cases
|
| 416 |
+
return ctx.hyp2f1(a,b,c,1-ctx.eps*2) * ctx.inf
|
| 417 |
+
|
| 418 |
+
# Equal to 1 (first term), unless there is a subsequent
|
| 419 |
+
# division by zero
|
| 420 |
+
if not z:
|
| 421 |
+
# Division by zero but power of z is higher than
|
| 422 |
+
# first order so cancels
|
| 423 |
+
if c or a == 0 or b == 0:
|
| 424 |
+
return 1+z
|
| 425 |
+
# Indeterminate
|
| 426 |
+
return ctx.nan
|
| 427 |
+
|
| 428 |
+
# Hit zero denominator unless numerator goes to 0 first
|
| 429 |
+
if ctx.isint(c) and c <= 0:
|
| 430 |
+
if (ctx.isint(a) and c <= a <= 0) or \
|
| 431 |
+
(ctx.isint(b) and c <= b <= 0):
|
| 432 |
+
pass
|
| 433 |
+
else:
|
| 434 |
+
# Pole in series
|
| 435 |
+
return ctx.inf
|
| 436 |
+
|
| 437 |
+
absz = abs(z)
|
| 438 |
+
|
| 439 |
+
# Fast case: standard series converges rapidly,
|
| 440 |
+
# possibly in finitely many terms
|
| 441 |
+
if absz <= 0.8 or (ctx.isint(a) and a <= 0 and a >= -1000) or \
|
| 442 |
+
(ctx.isint(b) and b <= 0 and b >= -1000):
|
| 443 |
+
return ctx.hypsum(2, 1, (atype, btype, ctype), [a, b, c], z, **kwargs)
|
| 444 |
+
|
| 445 |
+
orig = ctx.prec
|
| 446 |
+
try:
|
| 447 |
+
ctx.prec += 10
|
| 448 |
+
|
| 449 |
+
# Use 1/z transformation
|
| 450 |
+
if absz >= 1.3:
|
| 451 |
+
def h(a,b):
|
| 452 |
+
t = ctx.mpq_1-c; ab = a-b; rz = 1/z
|
| 453 |
+
T1 = ([-z],[-a], [c,-ab],[b,c-a], [a,t+a],[ctx.mpq_1+ab], rz)
|
| 454 |
+
T2 = ([-z],[-b], [c,ab],[a,c-b], [b,t+b],[ctx.mpq_1-ab], rz)
|
| 455 |
+
return T1, T2
|
| 456 |
+
v = ctx.hypercomb(h, [a,b], **kwargs)
|
| 457 |
+
|
| 458 |
+
# Use 1-z transformation
|
| 459 |
+
elif abs(1-z) <= 0.75:
|
| 460 |
+
def h(a,b):
|
| 461 |
+
t = c-a-b; ca = c-a; cb = c-b; rz = 1-z
|
| 462 |
+
T1 = [], [], [c,t], [ca,cb], [a,b], [1-t], rz
|
| 463 |
+
T2 = [rz], [t], [c,a+b-c], [a,b], [ca,cb], [1+t], rz
|
| 464 |
+
return T1, T2
|
| 465 |
+
v = ctx.hypercomb(h, [a,b], **kwargs)
|
| 466 |
+
|
| 467 |
+
# Use z/(z-1) transformation
|
| 468 |
+
elif abs(z/(z-1)) <= 0.75:
|
| 469 |
+
v = ctx.hyp2f1(a, c-b, c, z/(z-1)) / (1-z)**a
|
| 470 |
+
|
| 471 |
+
# Remaining part of unit circle
|
| 472 |
+
else:
|
| 473 |
+
v = _hyp2f1_gosper(ctx,a,b,c,z,**kwargs)
|
| 474 |
+
|
| 475 |
+
finally:
|
| 476 |
+
ctx.prec = orig
|
| 477 |
+
return +v
|
| 478 |
+
|
| 479 |
+
@defun
|
| 480 |
+
def _hypq1fq(ctx, p, q, a_s, b_s, z, **kwargs):
|
| 481 |
+
r"""
|
| 482 |
+
Evaluates 3F2, 4F3, 5F4, ...
|
| 483 |
+
"""
|
| 484 |
+
a_s, a_types = zip(*a_s)
|
| 485 |
+
b_s, b_types = zip(*b_s)
|
| 486 |
+
a_s = list(a_s)
|
| 487 |
+
b_s = list(b_s)
|
| 488 |
+
absz = abs(z)
|
| 489 |
+
ispoly = False
|
| 490 |
+
for a in a_s:
|
| 491 |
+
if ctx.isint(a) and a <= 0:
|
| 492 |
+
ispoly = True
|
| 493 |
+
break
|
| 494 |
+
# Direct summation
|
| 495 |
+
if absz < 1 or ispoly:
|
| 496 |
+
try:
|
| 497 |
+
return ctx.hypsum(p, q, a_types+b_types, a_s+b_s, z, **kwargs)
|
| 498 |
+
except ctx.NoConvergence:
|
| 499 |
+
if absz > 1.1 or ispoly:
|
| 500 |
+
raise
|
| 501 |
+
# Use expansion at |z-1| -> 0.
|
| 502 |
+
# Reference: Wolfgang Buhring, "Generalized Hypergeometric Functions at
|
| 503 |
+
# Unit Argument", Proc. Amer. Math. Soc., Vol. 114, No. 1 (Jan. 1992),
|
| 504 |
+
# pp.145-153
|
| 505 |
+
# The current implementation has several problems:
|
| 506 |
+
# 1. We only implement it for 3F2. The expansion coefficients are
|
| 507 |
+
# given by extremely messy nested sums in the higher degree cases
|
| 508 |
+
# (see reference). Is efficient sequential generation of the coefficients
|
| 509 |
+
# possible in the > 3F2 case?
|
| 510 |
+
# 2. Although the series converges, it may do so slowly, so we need
|
| 511 |
+
# convergence acceleration. The acceleration implemented by
|
| 512 |
+
# nsum does not always help, so results returned are sometimes
|
| 513 |
+
# inaccurate! Can we do better?
|
| 514 |
+
# 3. We should check conditions for convergence, and possibly
|
| 515 |
+
# do a better job of cancelling out gamma poles if possible.
|
| 516 |
+
if z == 1:
|
| 517 |
+
# XXX: should also check for division by zero in the
|
| 518 |
+
# denominator of the series (cf. hyp2f1)
|
| 519 |
+
S = ctx.re(sum(b_s)-sum(a_s))
|
| 520 |
+
if S <= 0:
|
| 521 |
+
#return ctx.hyper(a_s, b_s, 1-ctx.eps*2, **kwargs) * ctx.inf
|
| 522 |
+
return ctx.hyper(a_s, b_s, 0.9, **kwargs) * ctx.inf
|
| 523 |
+
if (p,q) == (3,2) and abs(z-1) < 0.05: # and kwargs.get('sum1')
|
| 524 |
+
#print "Using alternate summation (experimental)"
|
| 525 |
+
a1,a2,a3 = a_s
|
| 526 |
+
b1,b2 = b_s
|
| 527 |
+
u = b1+b2-a3
|
| 528 |
+
initial = ctx.gammaprod([b2-a3,b1-a3,a1,a2],[b2-a3,b1-a3,1,u])
|
| 529 |
+
def term(k, _cache={0:initial}):
|
| 530 |
+
u = b1+b2-a3+k
|
| 531 |
+
if k in _cache:
|
| 532 |
+
t = _cache[k]
|
| 533 |
+
else:
|
| 534 |
+
t = _cache[k-1]
|
| 535 |
+
t *= (b1+k-a3-1)*(b2+k-a3-1)
|
| 536 |
+
t /= k*(u-1)
|
| 537 |
+
_cache[k] = t
|
| 538 |
+
return t * ctx.hyp2f1(a1,a2,u,z)
|
| 539 |
+
try:
|
| 540 |
+
S = ctx.nsum(term, [0,ctx.inf], verbose=kwargs.get('verbose'),
|
| 541 |
+
strict=kwargs.get('strict', True))
|
| 542 |
+
return S * ctx.gammaprod([b1,b2],[a1,a2,a3])
|
| 543 |
+
except ctx.NoConvergence:
|
| 544 |
+
pass
|
| 545 |
+
# Try to use convergence acceleration on and close to the unit circle.
|
| 546 |
+
# Problem: the convergence acceleration degenerates as |z-1| -> 0,
|
| 547 |
+
# except for special cases. Everywhere else, the Shanks transformation
|
| 548 |
+
# is very efficient.
|
| 549 |
+
if absz < 1.1 and ctx._re(z) <= 1:
|
| 550 |
+
|
| 551 |
+
def term(kk, _cache={0:ctx.one}):
|
| 552 |
+
k = int(kk)
|
| 553 |
+
if k != kk:
|
| 554 |
+
t = z ** ctx.mpf(kk) / ctx.fac(kk)
|
| 555 |
+
for a in a_s: t *= ctx.rf(a,kk)
|
| 556 |
+
for b in b_s: t /= ctx.rf(b,kk)
|
| 557 |
+
return t
|
| 558 |
+
if k in _cache:
|
| 559 |
+
return _cache[k]
|
| 560 |
+
t = term(k-1)
|
| 561 |
+
m = k-1
|
| 562 |
+
for j in xrange(p): t *= (a_s[j]+m)
|
| 563 |
+
for j in xrange(q): t /= (b_s[j]+m)
|
| 564 |
+
t *= z
|
| 565 |
+
t /= k
|
| 566 |
+
_cache[k] = t
|
| 567 |
+
return t
|
| 568 |
+
|
| 569 |
+
sum_method = kwargs.get('sum_method', 'r+s+e')
|
| 570 |
+
|
| 571 |
+
try:
|
| 572 |
+
return ctx.nsum(term, [0,ctx.inf], verbose=kwargs.get('verbose'),
|
| 573 |
+
strict=kwargs.get('strict', True),
|
| 574 |
+
method=sum_method.replace('e',''))
|
| 575 |
+
except ctx.NoConvergence:
|
| 576 |
+
if 'e' not in sum_method:
|
| 577 |
+
raise
|
| 578 |
+
pass
|
| 579 |
+
|
| 580 |
+
if kwargs.get('verbose'):
|
| 581 |
+
print("Attempting Euler-Maclaurin summation")
|
| 582 |
+
|
| 583 |
+
|
| 584 |
+
"""
|
| 585 |
+
Somewhat slower version (one diffs_exp for each factor).
|
| 586 |
+
However, this would be faster with fast direct derivatives
|
| 587 |
+
of the gamma function.
|
| 588 |
+
|
| 589 |
+
def power_diffs(k0):
|
| 590 |
+
r = 0
|
| 591 |
+
l = ctx.log(z)
|
| 592 |
+
while 1:
|
| 593 |
+
yield z**ctx.mpf(k0) * l**r
|
| 594 |
+
r += 1
|
| 595 |
+
|
| 596 |
+
def loggamma_diffs(x, reciprocal=False):
|
| 597 |
+
sign = (-1) ** reciprocal
|
| 598 |
+
yield sign * ctx.loggamma(x)
|
| 599 |
+
i = 0
|
| 600 |
+
while 1:
|
| 601 |
+
yield sign * ctx.psi(i,x)
|
| 602 |
+
i += 1
|
| 603 |
+
|
| 604 |
+
def hyper_diffs(k0):
|
| 605 |
+
b2 = b_s + [1]
|
| 606 |
+
A = [ctx.diffs_exp(loggamma_diffs(a+k0)) for a in a_s]
|
| 607 |
+
B = [ctx.diffs_exp(loggamma_diffs(b+k0,True)) for b in b2]
|
| 608 |
+
Z = [power_diffs(k0)]
|
| 609 |
+
C = ctx.gammaprod([b for b in b2], [a for a in a_s])
|
| 610 |
+
for d in ctx.diffs_prod(A + B + Z):
|
| 611 |
+
v = C * d
|
| 612 |
+
yield v
|
| 613 |
+
"""
|
| 614 |
+
|
| 615 |
+
def log_diffs(k0):
|
| 616 |
+
b2 = b_s + [1]
|
| 617 |
+
yield sum(ctx.loggamma(a+k0) for a in a_s) - \
|
| 618 |
+
sum(ctx.loggamma(b+k0) for b in b2) + k0*ctx.log(z)
|
| 619 |
+
i = 0
|
| 620 |
+
while 1:
|
| 621 |
+
v = sum(ctx.psi(i,a+k0) for a in a_s) - \
|
| 622 |
+
sum(ctx.psi(i,b+k0) for b in b2)
|
| 623 |
+
if i == 0:
|
| 624 |
+
v += ctx.log(z)
|
| 625 |
+
yield v
|
| 626 |
+
i += 1
|
| 627 |
+
|
| 628 |
+
def hyper_diffs(k0):
|
| 629 |
+
C = ctx.gammaprod([b for b in b_s], [a for a in a_s])
|
| 630 |
+
for d in ctx.diffs_exp(log_diffs(k0)):
|
| 631 |
+
v = C * d
|
| 632 |
+
yield v
|
| 633 |
+
|
| 634 |
+
tol = ctx.eps / 1024
|
| 635 |
+
prec = ctx.prec
|
| 636 |
+
try:
|
| 637 |
+
trunc = 50 * ctx.dps
|
| 638 |
+
ctx.prec += 20
|
| 639 |
+
for i in xrange(5):
|
| 640 |
+
head = ctx.fsum(term(k) for k in xrange(trunc))
|
| 641 |
+
tail, err = ctx.sumem(term, [trunc, ctx.inf], tol=tol,
|
| 642 |
+
adiffs=hyper_diffs(trunc),
|
| 643 |
+
verbose=kwargs.get('verbose'),
|
| 644 |
+
error=True,
|
| 645 |
+
_fast_abort=True)
|
| 646 |
+
if err < tol:
|
| 647 |
+
v = head + tail
|
| 648 |
+
break
|
| 649 |
+
trunc *= 2
|
| 650 |
+
# Need to increase precision because calculation of
|
| 651 |
+
# derivatives may be inaccurate
|
| 652 |
+
ctx.prec += ctx.prec//2
|
| 653 |
+
if i == 4:
|
| 654 |
+
raise ctx.NoConvergence(\
|
| 655 |
+
"Euler-Maclaurin summation did not converge")
|
| 656 |
+
finally:
|
| 657 |
+
ctx.prec = prec
|
| 658 |
+
return +v
|
| 659 |
+
|
| 660 |
+
# Use 1/z transformation
|
| 661 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 662 |
+
# HypergeometricPFQ/06/01/05/02/0004/
|
| 663 |
+
def h(*args):
|
| 664 |
+
a_s = list(args[:p])
|
| 665 |
+
b_s = list(args[p:])
|
| 666 |
+
Ts = []
|
| 667 |
+
recz = ctx.one/z
|
| 668 |
+
negz = ctx.fneg(z, exact=True)
|
| 669 |
+
for k in range(q+1):
|
| 670 |
+
ak = a_s[k]
|
| 671 |
+
C = [negz]
|
| 672 |
+
Cp = [-ak]
|
| 673 |
+
Gn = b_s + [ak] + [a_s[j]-ak for j in range(q+1) if j != k]
|
| 674 |
+
Gd = a_s + [b_s[j]-ak for j in range(q)]
|
| 675 |
+
Fn = [ak] + [ak-b_s[j]+1 for j in range(q)]
|
| 676 |
+
Fd = [1-a_s[j]+ak for j in range(q+1) if j != k]
|
| 677 |
+
Ts.append((C, Cp, Gn, Gd, Fn, Fd, recz))
|
| 678 |
+
return Ts
|
| 679 |
+
return ctx.hypercomb(h, a_s+b_s, **kwargs)
|
| 680 |
+
|
| 681 |
+
@defun
|
| 682 |
+
def _hyp_borel(ctx, p, q, a_s, b_s, z, **kwargs):
|
| 683 |
+
if a_s:
|
| 684 |
+
a_s, a_types = zip(*a_s)
|
| 685 |
+
a_s = list(a_s)
|
| 686 |
+
else:
|
| 687 |
+
a_s, a_types = [], ()
|
| 688 |
+
if b_s:
|
| 689 |
+
b_s, b_types = zip(*b_s)
|
| 690 |
+
b_s = list(b_s)
|
| 691 |
+
else:
|
| 692 |
+
b_s, b_types = [], ()
|
| 693 |
+
kwargs['maxterms'] = kwargs.get('maxterms', ctx.prec)
|
| 694 |
+
try:
|
| 695 |
+
return ctx.hypsum(p, q, a_types+b_types, a_s+b_s, z, **kwargs)
|
| 696 |
+
except ctx.NoConvergence:
|
| 697 |
+
pass
|
| 698 |
+
prec = ctx.prec
|
| 699 |
+
try:
|
| 700 |
+
tol = kwargs.get('asymp_tol', ctx.eps/4)
|
| 701 |
+
ctx.prec += 10
|
| 702 |
+
# hypsum is has a conservative tolerance. So we try again:
|
| 703 |
+
def term(k, cache={0:ctx.one}):
|
| 704 |
+
if k in cache:
|
| 705 |
+
return cache[k]
|
| 706 |
+
t = term(k-1)
|
| 707 |
+
for a in a_s: t *= (a+(k-1))
|
| 708 |
+
for b in b_s: t /= (b+(k-1))
|
| 709 |
+
t *= z
|
| 710 |
+
t /= k
|
| 711 |
+
cache[k] = t
|
| 712 |
+
return t
|
| 713 |
+
s = ctx.one
|
| 714 |
+
for k in xrange(1, ctx.prec):
|
| 715 |
+
t = term(k)
|
| 716 |
+
s += t
|
| 717 |
+
if abs(t) <= tol:
|
| 718 |
+
return s
|
| 719 |
+
finally:
|
| 720 |
+
ctx.prec = prec
|
| 721 |
+
if p <= q+3:
|
| 722 |
+
contour = kwargs.get('contour')
|
| 723 |
+
if not contour:
|
| 724 |
+
if ctx.arg(z) < 0.25:
|
| 725 |
+
u = z / max(1, abs(z))
|
| 726 |
+
if ctx.arg(z) >= 0:
|
| 727 |
+
contour = [0, 2j, (2j+2)/u, 2/u, ctx.inf]
|
| 728 |
+
else:
|
| 729 |
+
contour = [0, -2j, (-2j+2)/u, 2/u, ctx.inf]
|
| 730 |
+
#contour = [0, 2j/z, 2/z, ctx.inf]
|
| 731 |
+
#contour = [0, 2j, 2/z, ctx.inf]
|
| 732 |
+
#contour = [0, 2j, ctx.inf]
|
| 733 |
+
else:
|
| 734 |
+
contour = [0, ctx.inf]
|
| 735 |
+
quad_kwargs = kwargs.get('quad_kwargs', {})
|
| 736 |
+
def g(t):
|
| 737 |
+
return ctx.exp(-t)*ctx.hyper(a_s, b_s+[1], t*z)
|
| 738 |
+
I, err = ctx.quad(g, contour, error=True, **quad_kwargs)
|
| 739 |
+
if err <= abs(I)*ctx.eps*8:
|
| 740 |
+
return I
|
| 741 |
+
raise ctx.NoConvergence
|
| 742 |
+
|
| 743 |
+
|
| 744 |
+
@defun
|
| 745 |
+
def _hyp2f2(ctx, a_s, b_s, z, **kwargs):
|
| 746 |
+
(a1, a1type), (a2, a2type) = a_s
|
| 747 |
+
(b1, b1type), (b2, b2type) = b_s
|
| 748 |
+
|
| 749 |
+
absz = abs(z)
|
| 750 |
+
magz = ctx.mag(z)
|
| 751 |
+
orig = ctx.prec
|
| 752 |
+
|
| 753 |
+
# Asymptotic expansion is ~ exp(z)
|
| 754 |
+
asymp_extraprec = magz
|
| 755 |
+
|
| 756 |
+
# Asymptotic series is in terms of 3F1
|
| 757 |
+
can_use_asymptotic = (not kwargs.get('force_series')) and \
|
| 758 |
+
(ctx.mag(absz) > 3)
|
| 759 |
+
|
| 760 |
+
# TODO: much of the following could be shared with 2F3 instead of
|
| 761 |
+
# copypasted
|
| 762 |
+
if can_use_asymptotic:
|
| 763 |
+
#print "using asymp"
|
| 764 |
+
try:
|
| 765 |
+
try:
|
| 766 |
+
ctx.prec += asymp_extraprec
|
| 767 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 768 |
+
# Hypergeometric2F2/06/02/02/0002/
|
| 769 |
+
def h(a1,a2,b1,b2):
|
| 770 |
+
X = a1+a2-b1-b2
|
| 771 |
+
A2 = a1+a2
|
| 772 |
+
B2 = b1+b2
|
| 773 |
+
c = {}
|
| 774 |
+
c[0] = ctx.one
|
| 775 |
+
c[1] = (A2-1)*X+b1*b2-a1*a2
|
| 776 |
+
s1 = 0
|
| 777 |
+
k = 0
|
| 778 |
+
tprev = 0
|
| 779 |
+
while 1:
|
| 780 |
+
if k not in c:
|
| 781 |
+
uu1 = 1-B2+2*a1+a1**2+2*a2+a2**2-A2*B2+a1*a2+b1*b2+(2*B2-3*(A2+1))*k+2*k**2
|
| 782 |
+
uu2 = (k-A2+b1-1)*(k-A2+b2-1)*(k-X-2)
|
| 783 |
+
c[k] = ctx.one/k * (uu1*c[k-1]-uu2*c[k-2])
|
| 784 |
+
t1 = c[k] * z**(-k)
|
| 785 |
+
if abs(t1) < 0.1*ctx.eps:
|
| 786 |
+
#print "Convergence :)"
|
| 787 |
+
break
|
| 788 |
+
# Quit if the series doesn't converge quickly enough
|
| 789 |
+
if k > 5 and abs(tprev) / abs(t1) < 1.5:
|
| 790 |
+
#print "No convergence :("
|
| 791 |
+
raise ctx.NoConvergence
|
| 792 |
+
s1 += t1
|
| 793 |
+
tprev = t1
|
| 794 |
+
k += 1
|
| 795 |
+
S = ctx.exp(z)*s1
|
| 796 |
+
T1 = [z,S], [X,1], [b1,b2],[a1,a2],[],[],0
|
| 797 |
+
T2 = [-z],[-a1],[b1,b2,a2-a1],[a2,b1-a1,b2-a1],[a1,a1-b1+1,a1-b2+1],[a1-a2+1],-1/z
|
| 798 |
+
T3 = [-z],[-a2],[b1,b2,a1-a2],[a1,b1-a2,b2-a2],[a2,a2-b1+1,a2-b2+1],[-a1+a2+1],-1/z
|
| 799 |
+
return T1, T2, T3
|
| 800 |
+
v = ctx.hypercomb(h, [a1,a2,b1,b2], force_series=True, maxterms=4*ctx.prec)
|
| 801 |
+
if sum(ctx._is_real_type(u) for u in [a1,a2,b1,b2,z]) == 5:
|
| 802 |
+
v = ctx.re(v)
|
| 803 |
+
return v
|
| 804 |
+
except ctx.NoConvergence:
|
| 805 |
+
pass
|
| 806 |
+
finally:
|
| 807 |
+
ctx.prec = orig
|
| 808 |
+
|
| 809 |
+
return ctx.hypsum(2, 2, (a1type, a2type, b1type, b2type), [a1, a2, b1, b2], z, **kwargs)
|
| 810 |
+
|
| 811 |
+
|
| 812 |
+
|
| 813 |
+
@defun
|
| 814 |
+
def _hyp1f2(ctx, a_s, b_s, z, **kwargs):
|
| 815 |
+
(a1, a1type), = a_s
|
| 816 |
+
(b1, b1type), (b2, b2type) = b_s
|
| 817 |
+
|
| 818 |
+
absz = abs(z)
|
| 819 |
+
magz = ctx.mag(z)
|
| 820 |
+
orig = ctx.prec
|
| 821 |
+
|
| 822 |
+
# Asymptotic expansion is ~ exp(sqrt(z))
|
| 823 |
+
asymp_extraprec = z and magz//2
|
| 824 |
+
|
| 825 |
+
# Asymptotic series is in terms of 3F0
|
| 826 |
+
can_use_asymptotic = (not kwargs.get('force_series')) and \
|
| 827 |
+
(ctx.mag(absz) > 19) and \
|
| 828 |
+
(ctx.sqrt(absz) > 1.5*orig) # and \
|
| 829 |
+
# ctx._hyp_check_convergence([a1, a1-b1+1, a1-b2+1], [],
|
| 830 |
+
# 1/absz, orig+40+asymp_extraprec)
|
| 831 |
+
|
| 832 |
+
# TODO: much of the following could be shared with 2F3 instead of
|
| 833 |
+
# copypasted
|
| 834 |
+
if can_use_asymptotic:
|
| 835 |
+
#print "using asymp"
|
| 836 |
+
try:
|
| 837 |
+
try:
|
| 838 |
+
ctx.prec += asymp_extraprec
|
| 839 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 840 |
+
# Hypergeometric1F2/06/02/03/
|
| 841 |
+
def h(a1,b1,b2):
|
| 842 |
+
X = ctx.mpq_1_2*(a1-b1-b2+ctx.mpq_1_2)
|
| 843 |
+
c = {}
|
| 844 |
+
c[0] = ctx.one
|
| 845 |
+
c[1] = 2*(ctx.mpq_1_4*(3*a1+b1+b2-2)*(a1-b1-b2)+b1*b2-ctx.mpq_3_16)
|
| 846 |
+
c[2] = 2*(b1*b2+ctx.mpq_1_4*(a1-b1-b2)*(3*a1+b1+b2-2)-ctx.mpq_3_16)**2+\
|
| 847 |
+
ctx.mpq_1_16*(-16*(2*a1-3)*b1*b2 + \
|
| 848 |
+
4*(a1-b1-b2)*(-8*a1**2+11*a1+b1+b2-2)-3)
|
| 849 |
+
s1 = 0
|
| 850 |
+
s2 = 0
|
| 851 |
+
k = 0
|
| 852 |
+
tprev = 0
|
| 853 |
+
while 1:
|
| 854 |
+
if k not in c:
|
| 855 |
+
uu1 = (3*k**2+(-6*a1+2*b1+2*b2-4)*k + 3*a1**2 - \
|
| 856 |
+
(b1-b2)**2 - 2*a1*(b1+b2-2) + ctx.mpq_1_4)
|
| 857 |
+
uu2 = (k-a1+b1-b2-ctx.mpq_1_2)*(k-a1-b1+b2-ctx.mpq_1_2)*\
|
| 858 |
+
(k-a1+b1+b2-ctx.mpq_5_2)
|
| 859 |
+
c[k] = ctx.one/(2*k)*(uu1*c[k-1]-uu2*c[k-2])
|
| 860 |
+
w = c[k] * (-z)**(-0.5*k)
|
| 861 |
+
t1 = (-ctx.j)**k * ctx.mpf(2)**(-k) * w
|
| 862 |
+
t2 = ctx.j**k * ctx.mpf(2)**(-k) * w
|
| 863 |
+
if abs(t1) < 0.1*ctx.eps:
|
| 864 |
+
#print "Convergence :)"
|
| 865 |
+
break
|
| 866 |
+
# Quit if the series doesn't converge quickly enough
|
| 867 |
+
if k > 5 and abs(tprev) / abs(t1) < 1.5:
|
| 868 |
+
#print "No convergence :("
|
| 869 |
+
raise ctx.NoConvergence
|
| 870 |
+
s1 += t1
|
| 871 |
+
s2 += t2
|
| 872 |
+
tprev = t1
|
| 873 |
+
k += 1
|
| 874 |
+
S = ctx.expj(ctx.pi*X+2*ctx.sqrt(-z))*s1 + \
|
| 875 |
+
ctx.expj(-(ctx.pi*X+2*ctx.sqrt(-z)))*s2
|
| 876 |
+
T1 = [0.5*S, ctx.pi, -z], [1, -0.5, X], [b1, b2], [a1],\
|
| 877 |
+
[], [], 0
|
| 878 |
+
T2 = [-z], [-a1], [b1,b2],[b1-a1,b2-a1], \
|
| 879 |
+
[a1,a1-b1+1,a1-b2+1], [], 1/z
|
| 880 |
+
return T1, T2
|
| 881 |
+
v = ctx.hypercomb(h, [a1,b1,b2], force_series=True, maxterms=4*ctx.prec)
|
| 882 |
+
if sum(ctx._is_real_type(u) for u in [a1,b1,b2,z]) == 4:
|
| 883 |
+
v = ctx.re(v)
|
| 884 |
+
return v
|
| 885 |
+
except ctx.NoConvergence:
|
| 886 |
+
pass
|
| 887 |
+
finally:
|
| 888 |
+
ctx.prec = orig
|
| 889 |
+
|
| 890 |
+
#print "not using asymp"
|
| 891 |
+
return ctx.hypsum(1, 2, (a1type, b1type, b2type), [a1, b1, b2], z, **kwargs)
|
| 892 |
+
|
| 893 |
+
|
| 894 |
+
|
| 895 |
+
@defun
|
| 896 |
+
def _hyp2f3(ctx, a_s, b_s, z, **kwargs):
|
| 897 |
+
(a1, a1type), (a2, a2type) = a_s
|
| 898 |
+
(b1, b1type), (b2, b2type), (b3, b3type) = b_s
|
| 899 |
+
|
| 900 |
+
absz = abs(z)
|
| 901 |
+
magz = ctx.mag(z)
|
| 902 |
+
|
| 903 |
+
# Asymptotic expansion is ~ exp(sqrt(z))
|
| 904 |
+
asymp_extraprec = z and magz//2
|
| 905 |
+
orig = ctx.prec
|
| 906 |
+
|
| 907 |
+
# Asymptotic series is in terms of 4F1
|
| 908 |
+
# The square root below empirically provides a plausible criterion
|
| 909 |
+
# for the leading series to converge
|
| 910 |
+
can_use_asymptotic = (not kwargs.get('force_series')) and \
|
| 911 |
+
(ctx.mag(absz) > 19) and (ctx.sqrt(absz) > 1.5*orig)
|
| 912 |
+
|
| 913 |
+
if can_use_asymptotic:
|
| 914 |
+
#print "using asymp"
|
| 915 |
+
try:
|
| 916 |
+
try:
|
| 917 |
+
ctx.prec += asymp_extraprec
|
| 918 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 919 |
+
# Hypergeometric2F3/06/02/03/01/0002/
|
| 920 |
+
def h(a1,a2,b1,b2,b3):
|
| 921 |
+
X = ctx.mpq_1_2*(a1+a2-b1-b2-b3+ctx.mpq_1_2)
|
| 922 |
+
A2 = a1+a2
|
| 923 |
+
B3 = b1+b2+b3
|
| 924 |
+
A = a1*a2
|
| 925 |
+
B = b1*b2+b3*b2+b1*b3
|
| 926 |
+
R = b1*b2*b3
|
| 927 |
+
c = {}
|
| 928 |
+
c[0] = ctx.one
|
| 929 |
+
c[1] = 2*(B - A + ctx.mpq_1_4*(3*A2+B3-2)*(A2-B3) - ctx.mpq_3_16)
|
| 930 |
+
c[2] = ctx.mpq_1_2*c[1]**2 + ctx.mpq_1_16*(-16*(2*A2-3)*(B-A) + 32*R +\
|
| 931 |
+
4*(-8*A2**2 + 11*A2 + 8*A + B3 - 2)*(A2-B3)-3)
|
| 932 |
+
s1 = 0
|
| 933 |
+
s2 = 0
|
| 934 |
+
k = 0
|
| 935 |
+
tprev = 0
|
| 936 |
+
while 1:
|
| 937 |
+
if k not in c:
|
| 938 |
+
uu1 = (k-2*X-3)*(k-2*X-2*b1-1)*(k-2*X-2*b2-1)*\
|
| 939 |
+
(k-2*X-2*b3-1)
|
| 940 |
+
uu2 = (4*(k-1)**3 - 6*(4*X+B3)*(k-1)**2 + \
|
| 941 |
+
2*(24*X**2+12*B3*X+4*B+B3-1)*(k-1) - 32*X**3 - \
|
| 942 |
+
24*B3*X**2 - 4*B - 8*R - 4*(4*B+B3-1)*X + 2*B3-1)
|
| 943 |
+
uu3 = (5*(k-1)**2+2*(-10*X+A2-3*B3+3)*(k-1)+2*c[1])
|
| 944 |
+
c[k] = ctx.one/(2*k)*(uu1*c[k-3]-uu2*c[k-2]+uu3*c[k-1])
|
| 945 |
+
w = c[k] * ctx.power(-z, -0.5*k)
|
| 946 |
+
t1 = (-ctx.j)**k * ctx.mpf(2)**(-k) * w
|
| 947 |
+
t2 = ctx.j**k * ctx.mpf(2)**(-k) * w
|
| 948 |
+
if abs(t1) < 0.1*ctx.eps:
|
| 949 |
+
break
|
| 950 |
+
# Quit if the series doesn't converge quickly enough
|
| 951 |
+
if k > 5 and abs(tprev) / abs(t1) < 1.5:
|
| 952 |
+
raise ctx.NoConvergence
|
| 953 |
+
s1 += t1
|
| 954 |
+
s2 += t2
|
| 955 |
+
tprev = t1
|
| 956 |
+
k += 1
|
| 957 |
+
S = ctx.expj(ctx.pi*X+2*ctx.sqrt(-z))*s1 + \
|
| 958 |
+
ctx.expj(-(ctx.pi*X+2*ctx.sqrt(-z)))*s2
|
| 959 |
+
T1 = [0.5*S, ctx.pi, -z], [1, -0.5, X], [b1, b2, b3], [a1, a2],\
|
| 960 |
+
[], [], 0
|
| 961 |
+
T2 = [-z], [-a1], [b1,b2,b3,a2-a1],[a2,b1-a1,b2-a1,b3-a1], \
|
| 962 |
+
[a1,a1-b1+1,a1-b2+1,a1-b3+1], [a1-a2+1], 1/z
|
| 963 |
+
T3 = [-z], [-a2], [b1,b2,b3,a1-a2],[a1,b1-a2,b2-a2,b3-a2], \
|
| 964 |
+
[a2,a2-b1+1,a2-b2+1,a2-b3+1],[-a1+a2+1], 1/z
|
| 965 |
+
return T1, T2, T3
|
| 966 |
+
v = ctx.hypercomb(h, [a1,a2,b1,b2,b3], force_series=True, maxterms=4*ctx.prec)
|
| 967 |
+
if sum(ctx._is_real_type(u) for u in [a1,a2,b1,b2,b3,z]) == 6:
|
| 968 |
+
v = ctx.re(v)
|
| 969 |
+
return v
|
| 970 |
+
except ctx.NoConvergence:
|
| 971 |
+
pass
|
| 972 |
+
finally:
|
| 973 |
+
ctx.prec = orig
|
| 974 |
+
|
| 975 |
+
return ctx.hypsum(2, 3, (a1type, a2type, b1type, b2type, b3type), [a1, a2, b1, b2, b3], z, **kwargs)
|
| 976 |
+
|
| 977 |
+
@defun
|
| 978 |
+
def _hyp2f0(ctx, a_s, b_s, z, **kwargs):
|
| 979 |
+
(a, atype), (b, btype) = a_s
|
| 980 |
+
# We want to try aggressively to use the asymptotic expansion,
|
| 981 |
+
# and fall back only when absolutely necessary
|
| 982 |
+
try:
|
| 983 |
+
kwargsb = kwargs.copy()
|
| 984 |
+
kwargsb['maxterms'] = kwargsb.get('maxterms', ctx.prec)
|
| 985 |
+
return ctx.hypsum(2, 0, (atype,btype), [a,b], z, **kwargsb)
|
| 986 |
+
except ctx.NoConvergence:
|
| 987 |
+
if kwargs.get('force_series'):
|
| 988 |
+
raise
|
| 989 |
+
pass
|
| 990 |
+
def h(a, b):
|
| 991 |
+
w = ctx.sinpi(b)
|
| 992 |
+
rz = -1/z
|
| 993 |
+
T1 = ([ctx.pi,w,rz],[1,-1,a],[],[a-b+1,b],[a],[b],rz)
|
| 994 |
+
T2 = ([-ctx.pi,w,rz],[1,-1,1+a-b],[],[a,2-b],[a-b+1],[2-b],rz)
|
| 995 |
+
return T1, T2
|
| 996 |
+
return ctx.hypercomb(h, [a, 1+a-b], **kwargs)
|
| 997 |
+
|
| 998 |
+
@defun
|
| 999 |
+
def meijerg(ctx, a_s, b_s, z, r=1, series=None, **kwargs):
|
| 1000 |
+
an, ap = a_s
|
| 1001 |
+
bm, bq = b_s
|
| 1002 |
+
n = len(an)
|
| 1003 |
+
p = n + len(ap)
|
| 1004 |
+
m = len(bm)
|
| 1005 |
+
q = m + len(bq)
|
| 1006 |
+
a = an+ap
|
| 1007 |
+
b = bm+bq
|
| 1008 |
+
a = [ctx.convert(_) for _ in a]
|
| 1009 |
+
b = [ctx.convert(_) for _ in b]
|
| 1010 |
+
z = ctx.convert(z)
|
| 1011 |
+
if series is None:
|
| 1012 |
+
if p < q: series = 1
|
| 1013 |
+
if p > q: series = 2
|
| 1014 |
+
if p == q:
|
| 1015 |
+
if m+n == p and abs(z) > 1:
|
| 1016 |
+
series = 2
|
| 1017 |
+
else:
|
| 1018 |
+
series = 1
|
| 1019 |
+
if kwargs.get('verbose'):
|
| 1020 |
+
print("Meijer G m,n,p,q,series =", m,n,p,q,series)
|
| 1021 |
+
if series == 1:
|
| 1022 |
+
def h(*args):
|
| 1023 |
+
a = args[:p]
|
| 1024 |
+
b = args[p:]
|
| 1025 |
+
terms = []
|
| 1026 |
+
for k in range(m):
|
| 1027 |
+
bases = [z]
|
| 1028 |
+
expts = [b[k]/r]
|
| 1029 |
+
gn = [b[j]-b[k] for j in range(m) if j != k]
|
| 1030 |
+
gn += [1-a[j]+b[k] for j in range(n)]
|
| 1031 |
+
gd = [a[j]-b[k] for j in range(n,p)]
|
| 1032 |
+
gd += [1-b[j]+b[k] for j in range(m,q)]
|
| 1033 |
+
hn = [1-a[j]+b[k] for j in range(p)]
|
| 1034 |
+
hd = [1-b[j]+b[k] for j in range(q) if j != k]
|
| 1035 |
+
hz = (-ctx.one)**(p-m-n) * z**(ctx.one/r)
|
| 1036 |
+
terms.append((bases, expts, gn, gd, hn, hd, hz))
|
| 1037 |
+
return terms
|
| 1038 |
+
else:
|
| 1039 |
+
def h(*args):
|
| 1040 |
+
a = args[:p]
|
| 1041 |
+
b = args[p:]
|
| 1042 |
+
terms = []
|
| 1043 |
+
for k in range(n):
|
| 1044 |
+
bases = [z]
|
| 1045 |
+
if r == 1:
|
| 1046 |
+
expts = [a[k]-1]
|
| 1047 |
+
else:
|
| 1048 |
+
expts = [(a[k]-1)/ctx.convert(r)]
|
| 1049 |
+
gn = [a[k]-a[j] for j in range(n) if j != k]
|
| 1050 |
+
gn += [1-a[k]+b[j] for j in range(m)]
|
| 1051 |
+
gd = [a[k]-b[j] for j in range(m,q)]
|
| 1052 |
+
gd += [1-a[k]+a[j] for j in range(n,p)]
|
| 1053 |
+
hn = [1-a[k]+b[j] for j in range(q)]
|
| 1054 |
+
hd = [1+a[j]-a[k] for j in range(p) if j != k]
|
| 1055 |
+
hz = (-ctx.one)**(q-m-n) / z**(ctx.one/r)
|
| 1056 |
+
terms.append((bases, expts, gn, gd, hn, hd, hz))
|
| 1057 |
+
return terms
|
| 1058 |
+
return ctx.hypercomb(h, a+b, **kwargs)
|
| 1059 |
+
|
| 1060 |
+
@defun_wrapped
|
| 1061 |
+
def appellf1(ctx,a,b1,b2,c,x,y,**kwargs):
|
| 1062 |
+
# Assume x smaller
|
| 1063 |
+
# We will use x for the outer loop
|
| 1064 |
+
if abs(x) > abs(y):
|
| 1065 |
+
x, y = y, x
|
| 1066 |
+
b1, b2 = b2, b1
|
| 1067 |
+
def ok(x):
|
| 1068 |
+
return abs(x) < 0.99
|
| 1069 |
+
# Finite cases
|
| 1070 |
+
if ctx.isnpint(a):
|
| 1071 |
+
pass
|
| 1072 |
+
elif ctx.isnpint(b1):
|
| 1073 |
+
pass
|
| 1074 |
+
elif ctx.isnpint(b2):
|
| 1075 |
+
x, y, b1, b2 = y, x, b2, b1
|
| 1076 |
+
else:
|
| 1077 |
+
#print x, y
|
| 1078 |
+
# Note: ok if |y| > 1, because
|
| 1079 |
+
# 2F1 implements analytic continuation
|
| 1080 |
+
if not ok(x):
|
| 1081 |
+
u1 = (x-y)/(x-1)
|
| 1082 |
+
if not ok(u1):
|
| 1083 |
+
raise ValueError("Analytic continuation not implemented")
|
| 1084 |
+
#print "Using analytic continuation"
|
| 1085 |
+
return (1-x)**(-b1)*(1-y)**(c-a-b2)*\
|
| 1086 |
+
ctx.appellf1(c-a,b1,c-b1-b2,c,u1,y,**kwargs)
|
| 1087 |
+
return ctx.hyper2d({'m+n':[a],'m':[b1],'n':[b2]}, {'m+n':[c]}, x,y, **kwargs)
|
| 1088 |
+
|
| 1089 |
+
@defun
|
| 1090 |
+
def appellf2(ctx,a,b1,b2,c1,c2,x,y,**kwargs):
|
| 1091 |
+
# TODO: continuation
|
| 1092 |
+
return ctx.hyper2d({'m+n':[a],'m':[b1],'n':[b2]},
|
| 1093 |
+
{'m':[c1],'n':[c2]}, x,y, **kwargs)
|
| 1094 |
+
|
| 1095 |
+
@defun
|
| 1096 |
+
def appellf3(ctx,a1,a2,b1,b2,c,x,y,**kwargs):
|
| 1097 |
+
outer_polynomial = ctx.isnpint(a1) or ctx.isnpint(b1)
|
| 1098 |
+
inner_polynomial = ctx.isnpint(a2) or ctx.isnpint(b2)
|
| 1099 |
+
if not outer_polynomial:
|
| 1100 |
+
if inner_polynomial or abs(x) > abs(y):
|
| 1101 |
+
x, y = y, x
|
| 1102 |
+
a1,a2,b1,b2 = a2,a1,b2,b1
|
| 1103 |
+
return ctx.hyper2d({'m':[a1,b1],'n':[a2,b2]}, {'m+n':[c]},x,y,**kwargs)
|
| 1104 |
+
|
| 1105 |
+
@defun
|
| 1106 |
+
def appellf4(ctx,a,b,c1,c2,x,y,**kwargs):
|
| 1107 |
+
# TODO: continuation
|
| 1108 |
+
return ctx.hyper2d({'m+n':[a,b]}, {'m':[c1],'n':[c2]},x,y,**kwargs)
|
| 1109 |
+
|
| 1110 |
+
@defun
|
| 1111 |
+
def hyper2d(ctx, a, b, x, y, **kwargs):
|
| 1112 |
+
r"""
|
| 1113 |
+
Sums the generalized 2D hypergeometric series
|
| 1114 |
+
|
| 1115 |
+
.. math ::
|
| 1116 |
+
|
| 1117 |
+
\sum_{m=0}^{\infty} \sum_{n=0}^{\infty}
|
| 1118 |
+
\frac{P((a),m,n)}{Q((b),m,n)}
|
| 1119 |
+
\frac{x^m y^n} {m! n!}
|
| 1120 |
+
|
| 1121 |
+
where `(a) = (a_1,\ldots,a_r)`, `(b) = (b_1,\ldots,b_s)` and where
|
| 1122 |
+
`P` and `Q` are products of rising factorials such as `(a_j)_n` or
|
| 1123 |
+
`(a_j)_{m+n}`. `P` and `Q` are specified in the form of dicts, with
|
| 1124 |
+
the `m` and `n` dependence as keys and parameter lists as values.
|
| 1125 |
+
The supported rising factorials are given in the following table
|
| 1126 |
+
(note that only a few are supported in `Q`):
|
| 1127 |
+
|
| 1128 |
+
+------------+-------------------+--------+
|
| 1129 |
+
| Key | Rising factorial | `Q` |
|
| 1130 |
+
+============+===================+========+
|
| 1131 |
+
| ``'m'`` | `(a_j)_m` | Yes |
|
| 1132 |
+
+------------+-------------------+--------+
|
| 1133 |
+
| ``'n'`` | `(a_j)_n` | Yes |
|
| 1134 |
+
+------------+-------------------+--------+
|
| 1135 |
+
| ``'m+n'`` | `(a_j)_{m+n}` | Yes |
|
| 1136 |
+
+------------+-------------------+--------+
|
| 1137 |
+
| ``'m-n'`` | `(a_j)_{m-n}` | No |
|
| 1138 |
+
+------------+-------------------+--------+
|
| 1139 |
+
| ``'n-m'`` | `(a_j)_{n-m}` | No |
|
| 1140 |
+
+------------+-------------------+--------+
|
| 1141 |
+
| ``'2m+n'`` | `(a_j)_{2m+n}` | No |
|
| 1142 |
+
+------------+-------------------+--------+
|
| 1143 |
+
| ``'2m-n'`` | `(a_j)_{2m-n}` | No |
|
| 1144 |
+
+------------+-------------------+--------+
|
| 1145 |
+
| ``'2n-m'`` | `(a_j)_{2n-m}` | No |
|
| 1146 |
+
+------------+-------------------+--------+
|
| 1147 |
+
|
| 1148 |
+
For example, the Appell F1 and F4 functions
|
| 1149 |
+
|
| 1150 |
+
.. math ::
|
| 1151 |
+
|
| 1152 |
+
F_1 = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty}
|
| 1153 |
+
\frac{(a)_{m+n} (b)_m (c)_n}{(d)_{m+n}}
|
| 1154 |
+
\frac{x^m y^n}{m! n!}
|
| 1155 |
+
|
| 1156 |
+
F_4 = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty}
|
| 1157 |
+
\frac{(a)_{m+n} (b)_{m+n}}{(c)_m (d)_{n}}
|
| 1158 |
+
\frac{x^m y^n}{m! n!}
|
| 1159 |
+
|
| 1160 |
+
can be represented respectively as
|
| 1161 |
+
|
| 1162 |
+
``hyper2d({'m+n':[a], 'm':[b], 'n':[c]}, {'m+n':[d]}, x, y)``
|
| 1163 |
+
|
| 1164 |
+
``hyper2d({'m+n':[a,b]}, {'m':[c], 'n':[d]}, x, y)``
|
| 1165 |
+
|
| 1166 |
+
More generally, :func:`~mpmath.hyper2d` can evaluate any of the 34 distinct
|
| 1167 |
+
convergent second-order (generalized Gaussian) hypergeometric
|
| 1168 |
+
series enumerated by Horn, as well as the Kampe de Feriet
|
| 1169 |
+
function.
|
| 1170 |
+
|
| 1171 |
+
The series is computed by rewriting it so that the inner
|
| 1172 |
+
series (i.e. the series containing `n` and `y`) has the form of an
|
| 1173 |
+
ordinary generalized hypergeometric series and thereby can be
|
| 1174 |
+
evaluated efficiently using :func:`~mpmath.hyper`. If possible,
|
| 1175 |
+
manually swapping `x` and `y` and the corresponding parameters
|
| 1176 |
+
can sometimes give better results.
|
| 1177 |
+
|
| 1178 |
+
**Examples**
|
| 1179 |
+
|
| 1180 |
+
Two separable cases: a product of two geometric series, and a
|
| 1181 |
+
product of two Gaussian hypergeometric functions::
|
| 1182 |
+
|
| 1183 |
+
>>> from mpmath import *
|
| 1184 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1185 |
+
>>> x, y = mpf(0.25), mpf(0.5)
|
| 1186 |
+
>>> hyper2d({'m':1,'n':1}, {}, x,y)
|
| 1187 |
+
2.666666666666666666666667
|
| 1188 |
+
>>> 1/(1-x)/(1-y)
|
| 1189 |
+
2.666666666666666666666667
|
| 1190 |
+
>>> hyper2d({'m':[1,2],'n':[3,4]}, {'m':[5],'n':[6]}, x,y)
|
| 1191 |
+
4.164358531238938319669856
|
| 1192 |
+
>>> hyp2f1(1,2,5,x)*hyp2f1(3,4,6,y)
|
| 1193 |
+
4.164358531238938319669856
|
| 1194 |
+
|
| 1195 |
+
Some more series that can be done in closed form::
|
| 1196 |
+
|
| 1197 |
+
>>> hyper2d({'m':1,'n':1},{'m+n':1},x,y)
|
| 1198 |
+
2.013417124712514809623881
|
| 1199 |
+
>>> (exp(x)*x-exp(y)*y)/(x-y)
|
| 1200 |
+
2.013417124712514809623881
|
| 1201 |
+
|
| 1202 |
+
Six of the 34 Horn functions, G1-G3 and H1-H3::
|
| 1203 |
+
|
| 1204 |
+
>>> from mpmath import *
|
| 1205 |
+
>>> mp.dps = 10; mp.pretty = True
|
| 1206 |
+
>>> x, y = 0.0625, 0.125
|
| 1207 |
+
>>> a1,a2,b1,b2,c1,c2,d = 1.1,-1.2,-1.3,-1.4,1.5,-1.6,1.7
|
| 1208 |
+
>>> hyper2d({'m+n':a1,'n-m':b1,'m-n':b2},{},x,y) # G1
|
| 1209 |
+
1.139090746
|
| 1210 |
+
>>> nsum(lambda m,n: rf(a1,m+n)*rf(b1,n-m)*rf(b2,m-n)*\
|
| 1211 |
+
... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf])
|
| 1212 |
+
1.139090746
|
| 1213 |
+
>>> hyper2d({'m':a1,'n':a2,'n-m':b1,'m-n':b2},{},x,y) # G2
|
| 1214 |
+
0.9503682696
|
| 1215 |
+
>>> nsum(lambda m,n: rf(a1,m)*rf(a2,n)*rf(b1,n-m)*rf(b2,m-n)*\
|
| 1216 |
+
... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf])
|
| 1217 |
+
0.9503682696
|
| 1218 |
+
>>> hyper2d({'2n-m':a1,'2m-n':a2},{},x,y) # G3
|
| 1219 |
+
1.029372029
|
| 1220 |
+
>>> nsum(lambda m,n: rf(a1,2*n-m)*rf(a2,2*m-n)*\
|
| 1221 |
+
... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf])
|
| 1222 |
+
1.029372029
|
| 1223 |
+
>>> hyper2d({'m-n':a1,'m+n':b1,'n':c1},{'m':d},x,y) # H1
|
| 1224 |
+
-1.605331256
|
| 1225 |
+
>>> nsum(lambda m,n: rf(a1,m-n)*rf(b1,m+n)*rf(c1,n)/rf(d,m)*\
|
| 1226 |
+
... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf])
|
| 1227 |
+
-1.605331256
|
| 1228 |
+
>>> hyper2d({'m-n':a1,'m':b1,'n':[c1,c2]},{'m':d},x,y) # H2
|
| 1229 |
+
-2.35405404
|
| 1230 |
+
>>> nsum(lambda m,n: rf(a1,m-n)*rf(b1,m)*rf(c1,n)*rf(c2,n)/rf(d,m)*\
|
| 1231 |
+
... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf])
|
| 1232 |
+
-2.35405404
|
| 1233 |
+
>>> hyper2d({'2m+n':a1,'n':b1},{'m+n':c1},x,y) # H3
|
| 1234 |
+
0.974479074
|
| 1235 |
+
>>> nsum(lambda m,n: rf(a1,2*m+n)*rf(b1,n)/rf(c1,m+n)*\
|
| 1236 |
+
... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf])
|
| 1237 |
+
0.974479074
|
| 1238 |
+
|
| 1239 |
+
**References**
|
| 1240 |
+
|
| 1241 |
+
1. [SrivastavaKarlsson]_
|
| 1242 |
+
2. [Weisstein]_ http://mathworld.wolfram.com/HornFunction.html
|
| 1243 |
+
3. [Weisstein]_ http://mathworld.wolfram.com/AppellHypergeometricFunction.html
|
| 1244 |
+
|
| 1245 |
+
"""
|
| 1246 |
+
x = ctx.convert(x)
|
| 1247 |
+
y = ctx.convert(y)
|
| 1248 |
+
def parse(dct, key):
|
| 1249 |
+
args = dct.pop(key, [])
|
| 1250 |
+
try:
|
| 1251 |
+
args = list(args)
|
| 1252 |
+
except TypeError:
|
| 1253 |
+
args = [args]
|
| 1254 |
+
return [ctx.convert(arg) for arg in args]
|
| 1255 |
+
a_s = dict(a)
|
| 1256 |
+
b_s = dict(b)
|
| 1257 |
+
a_m = parse(a, 'm')
|
| 1258 |
+
a_n = parse(a, 'n')
|
| 1259 |
+
a_m_add_n = parse(a, 'm+n')
|
| 1260 |
+
a_m_sub_n = parse(a, 'm-n')
|
| 1261 |
+
a_n_sub_m = parse(a, 'n-m')
|
| 1262 |
+
a_2m_add_n = parse(a, '2m+n')
|
| 1263 |
+
a_2m_sub_n = parse(a, '2m-n')
|
| 1264 |
+
a_2n_sub_m = parse(a, '2n-m')
|
| 1265 |
+
b_m = parse(b, 'm')
|
| 1266 |
+
b_n = parse(b, 'n')
|
| 1267 |
+
b_m_add_n = parse(b, 'm+n')
|
| 1268 |
+
if a: raise ValueError("unsupported key: %r" % a.keys()[0])
|
| 1269 |
+
if b: raise ValueError("unsupported key: %r" % b.keys()[0])
|
| 1270 |
+
s = 0
|
| 1271 |
+
outer = ctx.one
|
| 1272 |
+
m = ctx.mpf(0)
|
| 1273 |
+
ok_count = 0
|
| 1274 |
+
prec = ctx.prec
|
| 1275 |
+
maxterms = kwargs.get('maxterms', 20*prec)
|
| 1276 |
+
try:
|
| 1277 |
+
ctx.prec += 10
|
| 1278 |
+
tol = +ctx.eps
|
| 1279 |
+
while 1:
|
| 1280 |
+
inner_sign = 1
|
| 1281 |
+
outer_sign = 1
|
| 1282 |
+
inner_a = list(a_n)
|
| 1283 |
+
inner_b = list(b_n)
|
| 1284 |
+
outer_a = [a+m for a in a_m]
|
| 1285 |
+
outer_b = [b+m for b in b_m]
|
| 1286 |
+
# (a)_{m+n} = (a)_m (a+m)_n
|
| 1287 |
+
for a in a_m_add_n:
|
| 1288 |
+
a = a+m
|
| 1289 |
+
inner_a.append(a)
|
| 1290 |
+
outer_a.append(a)
|
| 1291 |
+
# (b)_{m+n} = (b)_m (b+m)_n
|
| 1292 |
+
for b in b_m_add_n:
|
| 1293 |
+
b = b+m
|
| 1294 |
+
inner_b.append(b)
|
| 1295 |
+
outer_b.append(b)
|
| 1296 |
+
# (a)_{n-m} = (a-m)_n / (a-m)_m
|
| 1297 |
+
for a in a_n_sub_m:
|
| 1298 |
+
inner_a.append(a-m)
|
| 1299 |
+
outer_b.append(a-m-1)
|
| 1300 |
+
# (a)_{m-n} = (-1)^(m+n) (1-a-m)_m / (1-a-m)_n
|
| 1301 |
+
for a in a_m_sub_n:
|
| 1302 |
+
inner_sign *= (-1)
|
| 1303 |
+
outer_sign *= (-1)**(m)
|
| 1304 |
+
inner_b.append(1-a-m)
|
| 1305 |
+
outer_a.append(-a-m)
|
| 1306 |
+
# (a)_{2m+n} = (a)_{2m} (a+2m)_n
|
| 1307 |
+
for a in a_2m_add_n:
|
| 1308 |
+
inner_a.append(a+2*m)
|
| 1309 |
+
outer_a.append((a+2*m)*(1+a+2*m))
|
| 1310 |
+
# (a)_{2m-n} = (-1)^(2m+n) (1-a-2m)_{2m} / (1-a-2m)_n
|
| 1311 |
+
for a in a_2m_sub_n:
|
| 1312 |
+
inner_sign *= (-1)
|
| 1313 |
+
inner_b.append(1-a-2*m)
|
| 1314 |
+
outer_a.append((a+2*m)*(1+a+2*m))
|
| 1315 |
+
# (a)_{2n-m} = 4^n ((a-m)/2)_n ((a-m+1)/2)_n / (a-m)_m
|
| 1316 |
+
for a in a_2n_sub_m:
|
| 1317 |
+
inner_sign *= 4
|
| 1318 |
+
inner_a.append(0.5*(a-m))
|
| 1319 |
+
inner_a.append(0.5*(a-m+1))
|
| 1320 |
+
outer_b.append(a-m-1)
|
| 1321 |
+
inner = ctx.hyper(inner_a, inner_b, inner_sign*y,
|
| 1322 |
+
zeroprec=ctx.prec, **kwargs)
|
| 1323 |
+
term = outer * inner * outer_sign
|
| 1324 |
+
if abs(term) < tol:
|
| 1325 |
+
ok_count += 1
|
| 1326 |
+
else:
|
| 1327 |
+
ok_count = 0
|
| 1328 |
+
if ok_count >= 3 or not outer:
|
| 1329 |
+
break
|
| 1330 |
+
s += term
|
| 1331 |
+
for a in outer_a: outer *= a
|
| 1332 |
+
for b in outer_b: outer /= b
|
| 1333 |
+
m += 1
|
| 1334 |
+
outer = outer * x / m
|
| 1335 |
+
if m > maxterms:
|
| 1336 |
+
raise ctx.NoConvergence("maxterms exceeded in hyper2d")
|
| 1337 |
+
finally:
|
| 1338 |
+
ctx.prec = prec
|
| 1339 |
+
return +s
|
| 1340 |
+
|
| 1341 |
+
"""
|
| 1342 |
+
@defun
|
| 1343 |
+
def kampe_de_feriet(ctx,a,b,c,d,e,f,x,y,**kwargs):
|
| 1344 |
+
return ctx.hyper2d({'m+n':a,'m':b,'n':c},
|
| 1345 |
+
{'m+n':d,'m':e,'n':f}, x,y, **kwargs)
|
| 1346 |
+
"""
|
| 1347 |
+
|
| 1348 |
+
@defun
|
| 1349 |
+
def bihyper(ctx, a_s, b_s, z, **kwargs):
|
| 1350 |
+
r"""
|
| 1351 |
+
Evaluates the bilateral hypergeometric series
|
| 1352 |
+
|
| 1353 |
+
.. math ::
|
| 1354 |
+
|
| 1355 |
+
\,_AH_B(a_1, \ldots, a_k; b_1, \ldots, b_B; z) =
|
| 1356 |
+
\sum_{n=-\infty}^{\infty}
|
| 1357 |
+
\frac{(a_1)_n \ldots (a_A)_n}
|
| 1358 |
+
{(b_1)_n \ldots (b_B)_n} \, z^n
|
| 1359 |
+
|
| 1360 |
+
where, for direct convergence, `A = B` and `|z| = 1`, although a
|
| 1361 |
+
regularized sum exists more generally by considering the
|
| 1362 |
+
bilateral series as a sum of two ordinary hypergeometric
|
| 1363 |
+
functions. In order for the series to make sense, none of the
|
| 1364 |
+
parameters may be integers.
|
| 1365 |
+
|
| 1366 |
+
**Examples**
|
| 1367 |
+
|
| 1368 |
+
The value of `\,_2H_2` at `z = 1` is given by Dougall's formula::
|
| 1369 |
+
|
| 1370 |
+
>>> from mpmath import *
|
| 1371 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1372 |
+
>>> a,b,c,d = 0.5, 1.5, 2.25, 3.25
|
| 1373 |
+
>>> bihyper([a,b],[c,d],1)
|
| 1374 |
+
-14.49118026212345786148847
|
| 1375 |
+
>>> gammaprod([c,d,1-a,1-b,c+d-a-b-1],[c-a,d-a,c-b,d-b])
|
| 1376 |
+
-14.49118026212345786148847
|
| 1377 |
+
|
| 1378 |
+
The regularized function `\,_1H_0` can be expressed as the
|
| 1379 |
+
sum of one `\,_2F_0` function and one `\,_1F_1` function::
|
| 1380 |
+
|
| 1381 |
+
>>> a = mpf(0.25)
|
| 1382 |
+
>>> z = mpf(0.75)
|
| 1383 |
+
>>> bihyper([a], [], z)
|
| 1384 |
+
(0.2454393389657273841385582 + 0.2454393389657273841385582j)
|
| 1385 |
+
>>> hyper([a,1],[],z) + (hyper([1],[1-a],-1/z)-1)
|
| 1386 |
+
(0.2454393389657273841385582 + 0.2454393389657273841385582j)
|
| 1387 |
+
>>> hyper([a,1],[],z) + hyper([1],[2-a],-1/z)/z/(a-1)
|
| 1388 |
+
(0.2454393389657273841385582 + 0.2454393389657273841385582j)
|
| 1389 |
+
|
| 1390 |
+
**References**
|
| 1391 |
+
|
| 1392 |
+
1. [Slater]_ (chapter 6: "Bilateral Series", pp. 180-189)
|
| 1393 |
+
2. [Wikipedia]_ http://en.wikipedia.org/wiki/Bilateral_hypergeometric_series
|
| 1394 |
+
|
| 1395 |
+
"""
|
| 1396 |
+
z = ctx.convert(z)
|
| 1397 |
+
c_s = a_s + b_s
|
| 1398 |
+
p = len(a_s)
|
| 1399 |
+
q = len(b_s)
|
| 1400 |
+
if (p, q) == (0,0) or (p, q) == (1,1):
|
| 1401 |
+
return ctx.zero * z
|
| 1402 |
+
neg = (p-q) % 2
|
| 1403 |
+
def h(*c_s):
|
| 1404 |
+
a_s = list(c_s[:p])
|
| 1405 |
+
b_s = list(c_s[p:])
|
| 1406 |
+
aa_s = [2-b for b in b_s]
|
| 1407 |
+
bb_s = [2-a for a in a_s]
|
| 1408 |
+
rp = [(-1)**neg * z] + [1-b for b in b_s] + [1-a for a in a_s]
|
| 1409 |
+
rc = [-1] + [1]*len(b_s) + [-1]*len(a_s)
|
| 1410 |
+
T1 = [], [], [], [], a_s + [1], b_s, z
|
| 1411 |
+
T2 = rp, rc, [], [], aa_s + [1], bb_s, (-1)**neg / z
|
| 1412 |
+
return T1, T2
|
| 1413 |
+
return ctx.hypercomb(h, c_s, **kwargs)
|
.venv/lib/python3.11/site-packages/mpmath/functions/orthogonal.py
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .functions import defun, defun_wrapped
|
| 2 |
+
|
| 3 |
+
def _hermite_param(ctx, n, z, parabolic_cylinder):
|
| 4 |
+
"""
|
| 5 |
+
Combined calculation of the Hermite polynomial H_n(z) (and its
|
| 6 |
+
generalization to complex n) and the parabolic cylinder
|
| 7 |
+
function D.
|
| 8 |
+
"""
|
| 9 |
+
n, ntyp = ctx._convert_param(n)
|
| 10 |
+
z = ctx.convert(z)
|
| 11 |
+
q = -ctx.mpq_1_2
|
| 12 |
+
# For re(z) > 0, 2F0 -- http://functions.wolfram.com/
|
| 13 |
+
# HypergeometricFunctions/HermiteHGeneral/06/02/0009/
|
| 14 |
+
# Otherwise, there is a reflection formula
|
| 15 |
+
# 2F0 + http://functions.wolfram.com/HypergeometricFunctions/
|
| 16 |
+
# HermiteHGeneral/16/01/01/0006/
|
| 17 |
+
#
|
| 18 |
+
# TODO:
|
| 19 |
+
# An alternative would be to use
|
| 20 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 21 |
+
# HermiteHGeneral/06/02/0006/
|
| 22 |
+
#
|
| 23 |
+
# Also, the 1F1 expansion
|
| 24 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 25 |
+
# HermiteHGeneral/26/01/02/0001/
|
| 26 |
+
# should probably be used for tiny z
|
| 27 |
+
if not z:
|
| 28 |
+
T1 = [2, ctx.pi], [n, 0.5], [], [q*(n-1)], [], [], 0
|
| 29 |
+
if parabolic_cylinder:
|
| 30 |
+
T1[1][0] += q*n
|
| 31 |
+
return T1,
|
| 32 |
+
can_use_2f0 = ctx.isnpint(-n) or ctx.re(z) > 0 or \
|
| 33 |
+
(ctx.re(z) == 0 and ctx.im(z) > 0)
|
| 34 |
+
expprec = ctx.prec*4 + 20
|
| 35 |
+
if parabolic_cylinder:
|
| 36 |
+
u = ctx.fmul(ctx.fmul(z,z,prec=expprec), -0.25, exact=True)
|
| 37 |
+
w = ctx.fmul(z, ctx.sqrt(0.5,prec=expprec), prec=expprec)
|
| 38 |
+
else:
|
| 39 |
+
w = z
|
| 40 |
+
w2 = ctx.fmul(w, w, prec=expprec)
|
| 41 |
+
rw2 = ctx.fdiv(1, w2, prec=expprec)
|
| 42 |
+
nrw2 = ctx.fneg(rw2, exact=True)
|
| 43 |
+
nw = ctx.fneg(w, exact=True)
|
| 44 |
+
if can_use_2f0:
|
| 45 |
+
T1 = [2, w], [n, n], [], [], [q*n, q*(n-1)], [], nrw2
|
| 46 |
+
terms = [T1]
|
| 47 |
+
else:
|
| 48 |
+
T1 = [2, nw], [n, n], [], [], [q*n, q*(n-1)], [], nrw2
|
| 49 |
+
T2 = [2, ctx.pi, nw], [n+2, 0.5, 1], [], [q*n], [q*(n-1)], [1-q], w2
|
| 50 |
+
terms = [T1,T2]
|
| 51 |
+
# Multiply by prefactor for D_n
|
| 52 |
+
if parabolic_cylinder:
|
| 53 |
+
expu = ctx.exp(u)
|
| 54 |
+
for i in range(len(terms)):
|
| 55 |
+
terms[i][1][0] += q*n
|
| 56 |
+
terms[i][0].append(expu)
|
| 57 |
+
terms[i][1].append(1)
|
| 58 |
+
return tuple(terms)
|
| 59 |
+
|
| 60 |
+
@defun
|
| 61 |
+
def hermite(ctx, n, z, **kwargs):
|
| 62 |
+
return ctx.hypercomb(lambda: _hermite_param(ctx, n, z, 0), [], **kwargs)
|
| 63 |
+
|
| 64 |
+
@defun
|
| 65 |
+
def pcfd(ctx, n, z, **kwargs):
|
| 66 |
+
r"""
|
| 67 |
+
Gives the parabolic cylinder function in Whittaker's notation
|
| 68 |
+
`D_n(z) = U(-n-1/2, z)` (see :func:`~mpmath.pcfu`).
|
| 69 |
+
It solves the differential equation
|
| 70 |
+
|
| 71 |
+
.. math ::
|
| 72 |
+
|
| 73 |
+
y'' + \left(n + \frac{1}{2} - \frac{1}{4} z^2\right) y = 0.
|
| 74 |
+
|
| 75 |
+
and can be represented in terms of Hermite polynomials
|
| 76 |
+
(see :func:`~mpmath.hermite`) as
|
| 77 |
+
|
| 78 |
+
.. math ::
|
| 79 |
+
|
| 80 |
+
D_n(z) = 2^{-n/2} e^{-z^2/4} H_n\left(\frac{z}{\sqrt{2}}\right).
|
| 81 |
+
|
| 82 |
+
**Plots**
|
| 83 |
+
|
| 84 |
+
.. literalinclude :: /plots/pcfd.py
|
| 85 |
+
.. image :: /plots/pcfd.png
|
| 86 |
+
|
| 87 |
+
**Examples**
|
| 88 |
+
|
| 89 |
+
>>> from mpmath import *
|
| 90 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 91 |
+
>>> pcfd(0,0); pcfd(1,0); pcfd(2,0); pcfd(3,0)
|
| 92 |
+
1.0
|
| 93 |
+
0.0
|
| 94 |
+
-1.0
|
| 95 |
+
0.0
|
| 96 |
+
>>> pcfd(4,0); pcfd(-3,0)
|
| 97 |
+
3.0
|
| 98 |
+
0.6266570686577501256039413
|
| 99 |
+
>>> pcfd('1/2', 2+3j)
|
| 100 |
+
(-5.363331161232920734849056 - 3.858877821790010714163487j)
|
| 101 |
+
>>> pcfd(2, -10)
|
| 102 |
+
1.374906442631438038871515e-9
|
| 103 |
+
|
| 104 |
+
Verifying the differential equation::
|
| 105 |
+
|
| 106 |
+
>>> n = mpf(2.5)
|
| 107 |
+
>>> y = lambda z: pcfd(n,z)
|
| 108 |
+
>>> z = 1.75
|
| 109 |
+
>>> chop(diff(y,z,2) + (n+0.5-0.25*z**2)*y(z))
|
| 110 |
+
0.0
|
| 111 |
+
|
| 112 |
+
Rational Taylor series expansion when `n` is an integer::
|
| 113 |
+
|
| 114 |
+
>>> taylor(lambda z: pcfd(5,z), 0, 7)
|
| 115 |
+
[0.0, 15.0, 0.0, -13.75, 0.0, 3.96875, 0.0, -0.6015625]
|
| 116 |
+
|
| 117 |
+
"""
|
| 118 |
+
return ctx.hypercomb(lambda: _hermite_param(ctx, n, z, 1), [], **kwargs)
|
| 119 |
+
|
| 120 |
+
@defun
|
| 121 |
+
def pcfu(ctx, a, z, **kwargs):
|
| 122 |
+
r"""
|
| 123 |
+
Gives the parabolic cylinder function `U(a,z)`, which may be
|
| 124 |
+
defined for `\Re(z) > 0` in terms of the confluent
|
| 125 |
+
U-function (see :func:`~mpmath.hyperu`) by
|
| 126 |
+
|
| 127 |
+
.. math ::
|
| 128 |
+
|
| 129 |
+
U(a,z) = 2^{-\frac{1}{4}-\frac{a}{2}} e^{-\frac{1}{4} z^2}
|
| 130 |
+
U\left(\frac{a}{2}+\frac{1}{4},
|
| 131 |
+
\frac{1}{2}, \frac{1}{2}z^2\right)
|
| 132 |
+
|
| 133 |
+
or, for arbitrary `z`,
|
| 134 |
+
|
| 135 |
+
.. math ::
|
| 136 |
+
|
| 137 |
+
e^{-\frac{1}{4}z^2} U(a,z) =
|
| 138 |
+
U(a,0) \,_1F_1\left(-\tfrac{a}{2}+\tfrac{1}{4};
|
| 139 |
+
\tfrac{1}{2}; -\tfrac{1}{2}z^2\right) +
|
| 140 |
+
U'(a,0) z \,_1F_1\left(-\tfrac{a}{2}+\tfrac{3}{4};
|
| 141 |
+
\tfrac{3}{2}; -\tfrac{1}{2}z^2\right).
|
| 142 |
+
|
| 143 |
+
**Examples**
|
| 144 |
+
|
| 145 |
+
Connection to other functions::
|
| 146 |
+
|
| 147 |
+
>>> from mpmath import *
|
| 148 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 149 |
+
>>> z = mpf(3)
|
| 150 |
+
>>> pcfu(0.5,z)
|
| 151 |
+
0.03210358129311151450551963
|
| 152 |
+
>>> sqrt(pi/2)*exp(z**2/4)*erfc(z/sqrt(2))
|
| 153 |
+
0.03210358129311151450551963
|
| 154 |
+
>>> pcfu(0.5,-z)
|
| 155 |
+
23.75012332835297233711255
|
| 156 |
+
>>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2))
|
| 157 |
+
23.75012332835297233711255
|
| 158 |
+
>>> pcfu(0.5,-z)
|
| 159 |
+
23.75012332835297233711255
|
| 160 |
+
>>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2))
|
| 161 |
+
23.75012332835297233711255
|
| 162 |
+
|
| 163 |
+
"""
|
| 164 |
+
n, _ = ctx._convert_param(a)
|
| 165 |
+
return ctx.pcfd(-n-ctx.mpq_1_2, z)
|
| 166 |
+
|
| 167 |
+
@defun
|
| 168 |
+
def pcfv(ctx, a, z, **kwargs):
|
| 169 |
+
r"""
|
| 170 |
+
Gives the parabolic cylinder function `V(a,z)`, which can be
|
| 171 |
+
represented in terms of :func:`~mpmath.pcfu` as
|
| 172 |
+
|
| 173 |
+
.. math ::
|
| 174 |
+
|
| 175 |
+
V(a,z) = \frac{\Gamma(a+\tfrac{1}{2}) (U(a,-z)-\sin(\pi a) U(a,z)}{\pi}.
|
| 176 |
+
|
| 177 |
+
**Examples**
|
| 178 |
+
|
| 179 |
+
Wronskian relation between `U` and `V`::
|
| 180 |
+
|
| 181 |
+
>>> from mpmath import *
|
| 182 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 183 |
+
>>> a, z = 2, 3
|
| 184 |
+
>>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
|
| 185 |
+
0.7978845608028653558798921
|
| 186 |
+
>>> sqrt(2/pi)
|
| 187 |
+
0.7978845608028653558798921
|
| 188 |
+
>>> a, z = 2.5, 3
|
| 189 |
+
>>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
|
| 190 |
+
0.7978845608028653558798921
|
| 191 |
+
>>> a, z = 0.25, -1
|
| 192 |
+
>>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
|
| 193 |
+
0.7978845608028653558798921
|
| 194 |
+
>>> a, z = 2+1j, 2+3j
|
| 195 |
+
>>> chop(pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z))
|
| 196 |
+
0.7978845608028653558798921
|
| 197 |
+
|
| 198 |
+
"""
|
| 199 |
+
n, ntype = ctx._convert_param(a)
|
| 200 |
+
z = ctx.convert(z)
|
| 201 |
+
q = ctx.mpq_1_2
|
| 202 |
+
r = ctx.mpq_1_4
|
| 203 |
+
if ntype == 'Q' and ctx.isint(n*2):
|
| 204 |
+
# Faster for half-integers
|
| 205 |
+
def h():
|
| 206 |
+
jz = ctx.fmul(z, -1j, exact=True)
|
| 207 |
+
T1terms = _hermite_param(ctx, -n-q, z, 1)
|
| 208 |
+
T2terms = _hermite_param(ctx, n-q, jz, 1)
|
| 209 |
+
for T in T1terms:
|
| 210 |
+
T[0].append(1j)
|
| 211 |
+
T[1].append(1)
|
| 212 |
+
T[3].append(q-n)
|
| 213 |
+
u = ctx.expjpi((q*n-r)) * ctx.sqrt(2/ctx.pi)
|
| 214 |
+
for T in T2terms:
|
| 215 |
+
T[0].append(u)
|
| 216 |
+
T[1].append(1)
|
| 217 |
+
return T1terms + T2terms
|
| 218 |
+
v = ctx.hypercomb(h, [], **kwargs)
|
| 219 |
+
if ctx._is_real_type(n) and ctx._is_real_type(z):
|
| 220 |
+
v = ctx._re(v)
|
| 221 |
+
return v
|
| 222 |
+
else:
|
| 223 |
+
def h(n):
|
| 224 |
+
w = ctx.square_exp_arg(z, -0.25)
|
| 225 |
+
u = ctx.square_exp_arg(z, 0.5)
|
| 226 |
+
e = ctx.exp(w)
|
| 227 |
+
l = [ctx.pi, q, ctx.exp(w)]
|
| 228 |
+
Y1 = l, [-q, n*q+r, 1], [r-q*n], [], [q*n+r], [q], u
|
| 229 |
+
Y2 = l + [z], [-q, n*q-r, 1, 1], [1-r-q*n], [], [q*n+1-r], [1+q], u
|
| 230 |
+
c, s = ctx.cospi_sinpi(r+q*n)
|
| 231 |
+
Y1[0].append(s)
|
| 232 |
+
Y2[0].append(c)
|
| 233 |
+
for Y in (Y1, Y2):
|
| 234 |
+
Y[1].append(1)
|
| 235 |
+
Y[3].append(q-n)
|
| 236 |
+
return Y1, Y2
|
| 237 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
@defun
|
| 241 |
+
def pcfw(ctx, a, z, **kwargs):
|
| 242 |
+
r"""
|
| 243 |
+
Gives the parabolic cylinder function `W(a,z)` defined in (DLMF 12.14).
|
| 244 |
+
|
| 245 |
+
**Examples**
|
| 246 |
+
|
| 247 |
+
Value at the origin::
|
| 248 |
+
|
| 249 |
+
>>> from mpmath import *
|
| 250 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 251 |
+
>>> a = mpf(0.25)
|
| 252 |
+
>>> pcfw(a,0)
|
| 253 |
+
0.9722833245718180765617104
|
| 254 |
+
>>> power(2,-0.75)*sqrt(abs(gamma(0.25+0.5j*a)/gamma(0.75+0.5j*a)))
|
| 255 |
+
0.9722833245718180765617104
|
| 256 |
+
>>> diff(pcfw,(a,0),(0,1))
|
| 257 |
+
-0.5142533944210078966003624
|
| 258 |
+
>>> -power(2,-0.25)*sqrt(abs(gamma(0.75+0.5j*a)/gamma(0.25+0.5j*a)))
|
| 259 |
+
-0.5142533944210078966003624
|
| 260 |
+
|
| 261 |
+
"""
|
| 262 |
+
n, _ = ctx._convert_param(a)
|
| 263 |
+
z = ctx.convert(z)
|
| 264 |
+
def terms():
|
| 265 |
+
phi2 = ctx.arg(ctx.gamma(0.5 + ctx.j*n))
|
| 266 |
+
phi2 = (ctx.loggamma(0.5+ctx.j*n) - ctx.loggamma(0.5-ctx.j*n))/2j
|
| 267 |
+
rho = ctx.pi/8 + 0.5*phi2
|
| 268 |
+
# XXX: cancellation computing k
|
| 269 |
+
k = ctx.sqrt(1 + ctx.exp(2*ctx.pi*n)) - ctx.exp(ctx.pi*n)
|
| 270 |
+
C = ctx.sqrt(k/2) * ctx.exp(0.25*ctx.pi*n)
|
| 271 |
+
yield C * ctx.expj(rho) * ctx.pcfu(ctx.j*n, z*ctx.expjpi(-0.25))
|
| 272 |
+
yield C * ctx.expj(-rho) * ctx.pcfu(-ctx.j*n, z*ctx.expjpi(0.25))
|
| 273 |
+
v = ctx.sum_accurately(terms)
|
| 274 |
+
if ctx._is_real_type(n) and ctx._is_real_type(z):
|
| 275 |
+
v = ctx._re(v)
|
| 276 |
+
return v
|
| 277 |
+
|
| 278 |
+
"""
|
| 279 |
+
Even/odd PCFs. Useful?
|
| 280 |
+
|
| 281 |
+
@defun
|
| 282 |
+
def pcfy1(ctx, a, z, **kwargs):
|
| 283 |
+
a, _ = ctx._convert_param(n)
|
| 284 |
+
z = ctx.convert(z)
|
| 285 |
+
def h():
|
| 286 |
+
w = ctx.square_exp_arg(z)
|
| 287 |
+
w1 = ctx.fmul(w, -0.25, exact=True)
|
| 288 |
+
w2 = ctx.fmul(w, 0.5, exact=True)
|
| 289 |
+
e = ctx.exp(w1)
|
| 290 |
+
return [e], [1], [], [], [ctx.mpq_1_2*a+ctx.mpq_1_4], [ctx.mpq_1_2], w2
|
| 291 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 292 |
+
|
| 293 |
+
@defun
|
| 294 |
+
def pcfy2(ctx, a, z, **kwargs):
|
| 295 |
+
a, _ = ctx._convert_param(n)
|
| 296 |
+
z = ctx.convert(z)
|
| 297 |
+
def h():
|
| 298 |
+
w = ctx.square_exp_arg(z)
|
| 299 |
+
w1 = ctx.fmul(w, -0.25, exact=True)
|
| 300 |
+
w2 = ctx.fmul(w, 0.5, exact=True)
|
| 301 |
+
e = ctx.exp(w1)
|
| 302 |
+
return [e, z], [1, 1], [], [], [ctx.mpq_1_2*a+ctx.mpq_3_4], \
|
| 303 |
+
[ctx.mpq_3_2], w2
|
| 304 |
+
return ctx.hypercomb(h, [], **kwargs)
|
| 305 |
+
"""
|
| 306 |
+
|
| 307 |
+
@defun_wrapped
|
| 308 |
+
def gegenbauer(ctx, n, a, z, **kwargs):
|
| 309 |
+
# Special cases: a+0.5, a*2 poles
|
| 310 |
+
if ctx.isnpint(a):
|
| 311 |
+
return 0*(z+n)
|
| 312 |
+
if ctx.isnpint(a+0.5):
|
| 313 |
+
# TODO: something else is required here
|
| 314 |
+
# E.g.: gegenbauer(-2, -0.5, 3) == -12
|
| 315 |
+
if ctx.isnpint(n+1):
|
| 316 |
+
raise NotImplementedError("Gegenbauer function with two limits")
|
| 317 |
+
def h(a):
|
| 318 |
+
a2 = 2*a
|
| 319 |
+
T = [], [], [n+a2], [n+1, a2], [-n, n+a2], [a+0.5], 0.5*(1-z)
|
| 320 |
+
return [T]
|
| 321 |
+
return ctx.hypercomb(h, [a], **kwargs)
|
| 322 |
+
def h(n):
|
| 323 |
+
a2 = 2*a
|
| 324 |
+
T = [], [], [n+a2], [n+1, a2], [-n, n+a2], [a+0.5], 0.5*(1-z)
|
| 325 |
+
return [T]
|
| 326 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 327 |
+
|
| 328 |
+
@defun_wrapped
|
| 329 |
+
def jacobi(ctx, n, a, b, x, **kwargs):
|
| 330 |
+
if not ctx.isnpint(a):
|
| 331 |
+
def h(n):
|
| 332 |
+
return (([], [], [a+n+1], [n+1, a+1], [-n, a+b+n+1], [a+1], (1-x)*0.5),)
|
| 333 |
+
return ctx.hypercomb(h, [n], **kwargs)
|
| 334 |
+
if not ctx.isint(b):
|
| 335 |
+
def h(n, a):
|
| 336 |
+
return (([], [], [-b], [n+1, -b-n], [-n, a+b+n+1], [b+1], (x+1)*0.5),)
|
| 337 |
+
return ctx.hypercomb(h, [n, a], **kwargs)
|
| 338 |
+
# XXX: determine appropriate limit
|
| 339 |
+
return ctx.binomial(n+a,n) * ctx.hyp2f1(-n,1+n+a+b,a+1,(1-x)/2, **kwargs)
|
| 340 |
+
|
| 341 |
+
@defun_wrapped
|
| 342 |
+
def laguerre(ctx, n, a, z, **kwargs):
|
| 343 |
+
# XXX: limits, poles
|
| 344 |
+
#if ctx.isnpint(n):
|
| 345 |
+
# return 0*(a+z)
|
| 346 |
+
def h(a):
|
| 347 |
+
return (([], [], [a+n+1], [a+1, n+1], [-n], [a+1], z),)
|
| 348 |
+
return ctx.hypercomb(h, [a], **kwargs)
|
| 349 |
+
|
| 350 |
+
@defun_wrapped
|
| 351 |
+
def legendre(ctx, n, x, **kwargs):
|
| 352 |
+
if ctx.isint(n):
|
| 353 |
+
n = int(n)
|
| 354 |
+
# Accuracy near zeros
|
| 355 |
+
if (n + (n < 0)) & 1:
|
| 356 |
+
if not x:
|
| 357 |
+
return x
|
| 358 |
+
mag = ctx.mag(x)
|
| 359 |
+
if mag < -2*ctx.prec-10:
|
| 360 |
+
return x
|
| 361 |
+
if mag < -5:
|
| 362 |
+
ctx.prec += -mag
|
| 363 |
+
return ctx.hyp2f1(-n,n+1,1,(1-x)/2, **kwargs)
|
| 364 |
+
|
| 365 |
+
@defun
|
| 366 |
+
def legenp(ctx, n, m, z, type=2, **kwargs):
|
| 367 |
+
# Legendre function, 1st kind
|
| 368 |
+
n = ctx.convert(n)
|
| 369 |
+
m = ctx.convert(m)
|
| 370 |
+
# Faster
|
| 371 |
+
if not m:
|
| 372 |
+
return ctx.legendre(n, z, **kwargs)
|
| 373 |
+
# TODO: correct evaluation at singularities
|
| 374 |
+
if type == 2:
|
| 375 |
+
def h(n,m):
|
| 376 |
+
g = m*0.5
|
| 377 |
+
T = [1+z, 1-z], [g, -g], [], [1-m], [-n, n+1], [1-m], 0.5*(1-z)
|
| 378 |
+
return (T,)
|
| 379 |
+
return ctx.hypercomb(h, [n,m], **kwargs)
|
| 380 |
+
if type == 3:
|
| 381 |
+
def h(n,m):
|
| 382 |
+
g = m*0.5
|
| 383 |
+
T = [z+1, z-1], [g, -g], [], [1-m], [-n, n+1], [1-m], 0.5*(1-z)
|
| 384 |
+
return (T,)
|
| 385 |
+
return ctx.hypercomb(h, [n,m], **kwargs)
|
| 386 |
+
raise ValueError("requires type=2 or type=3")
|
| 387 |
+
|
| 388 |
+
@defun
|
| 389 |
+
def legenq(ctx, n, m, z, type=2, **kwargs):
|
| 390 |
+
# Legendre function, 2nd kind
|
| 391 |
+
n = ctx.convert(n)
|
| 392 |
+
m = ctx.convert(m)
|
| 393 |
+
z = ctx.convert(z)
|
| 394 |
+
if z in (1, -1):
|
| 395 |
+
#if ctx.isint(m):
|
| 396 |
+
# return ctx.nan
|
| 397 |
+
#return ctx.inf # unsigned
|
| 398 |
+
return ctx.nan
|
| 399 |
+
if type == 2:
|
| 400 |
+
def h(n, m):
|
| 401 |
+
cos, sin = ctx.cospi_sinpi(m)
|
| 402 |
+
s = 2 * sin / ctx.pi
|
| 403 |
+
c = cos
|
| 404 |
+
a = 1+z
|
| 405 |
+
b = 1-z
|
| 406 |
+
u = m/2
|
| 407 |
+
w = (1-z)/2
|
| 408 |
+
T1 = [s, c, a, b], [-1, 1, u, -u], [], [1-m], \
|
| 409 |
+
[-n, n+1], [1-m], w
|
| 410 |
+
T2 = [-s, a, b], [-1, -u, u], [n+m+1], [n-m+1, m+1], \
|
| 411 |
+
[-n, n+1], [m+1], w
|
| 412 |
+
return T1, T2
|
| 413 |
+
return ctx.hypercomb(h, [n, m], **kwargs)
|
| 414 |
+
if type == 3:
|
| 415 |
+
# The following is faster when there only is a single series
|
| 416 |
+
# Note: not valid for -1 < z < 0 (?)
|
| 417 |
+
if abs(z) > 1:
|
| 418 |
+
def h(n, m):
|
| 419 |
+
T1 = [ctx.expjpi(m), 2, ctx.pi, z, z-1, z+1], \
|
| 420 |
+
[1, -n-1, 0.5, -n-m-1, 0.5*m, 0.5*m], \
|
| 421 |
+
[n+m+1], [n+1.5], \
|
| 422 |
+
[0.5*(2+n+m), 0.5*(1+n+m)], [n+1.5], z**(-2)
|
| 423 |
+
return [T1]
|
| 424 |
+
return ctx.hypercomb(h, [n, m], **kwargs)
|
| 425 |
+
else:
|
| 426 |
+
# not valid for 1 < z < inf ?
|
| 427 |
+
def h(n, m):
|
| 428 |
+
s = 2 * ctx.sinpi(m) / ctx.pi
|
| 429 |
+
c = ctx.expjpi(m)
|
| 430 |
+
a = 1+z
|
| 431 |
+
b = z-1
|
| 432 |
+
u = m/2
|
| 433 |
+
w = (1-z)/2
|
| 434 |
+
T1 = [s, c, a, b], [-1, 1, u, -u], [], [1-m], \
|
| 435 |
+
[-n, n+1], [1-m], w
|
| 436 |
+
T2 = [-s, c, a, b], [-1, 1, -u, u], [n+m+1], [n-m+1, m+1], \
|
| 437 |
+
[-n, n+1], [m+1], w
|
| 438 |
+
return T1, T2
|
| 439 |
+
return ctx.hypercomb(h, [n, m], **kwargs)
|
| 440 |
+
raise ValueError("requires type=2 or type=3")
|
| 441 |
+
|
| 442 |
+
@defun_wrapped
|
| 443 |
+
def chebyt(ctx, n, x, **kwargs):
|
| 444 |
+
if (not x) and ctx.isint(n) and int(ctx._re(n)) % 2 == 1:
|
| 445 |
+
return x * 0
|
| 446 |
+
return ctx.hyp2f1(-n,n,(1,2),(1-x)/2, **kwargs)
|
| 447 |
+
|
| 448 |
+
@defun_wrapped
|
| 449 |
+
def chebyu(ctx, n, x, **kwargs):
|
| 450 |
+
if (not x) and ctx.isint(n) and int(ctx._re(n)) % 2 == 1:
|
| 451 |
+
return x * 0
|
| 452 |
+
return (n+1) * ctx.hyp2f1(-n, n+2, (3,2), (1-x)/2, **kwargs)
|
| 453 |
+
|
| 454 |
+
@defun
|
| 455 |
+
def spherharm(ctx, l, m, theta, phi, **kwargs):
|
| 456 |
+
l = ctx.convert(l)
|
| 457 |
+
m = ctx.convert(m)
|
| 458 |
+
theta = ctx.convert(theta)
|
| 459 |
+
phi = ctx.convert(phi)
|
| 460 |
+
l_isint = ctx.isint(l)
|
| 461 |
+
l_natural = l_isint and l >= 0
|
| 462 |
+
m_isint = ctx.isint(m)
|
| 463 |
+
if l_isint and l < 0 and m_isint:
|
| 464 |
+
return ctx.spherharm(-(l+1), m, theta, phi, **kwargs)
|
| 465 |
+
if theta == 0 and m_isint and m < 0:
|
| 466 |
+
return ctx.zero * 1j
|
| 467 |
+
if l_natural and m_isint:
|
| 468 |
+
if abs(m) > l:
|
| 469 |
+
return ctx.zero * 1j
|
| 470 |
+
# http://functions.wolfram.com/Polynomials/
|
| 471 |
+
# SphericalHarmonicY/26/01/02/0004/
|
| 472 |
+
def h(l,m):
|
| 473 |
+
absm = abs(m)
|
| 474 |
+
C = [-1, ctx.expj(m*phi),
|
| 475 |
+
(2*l+1)*ctx.fac(l+absm)/ctx.pi/ctx.fac(l-absm),
|
| 476 |
+
ctx.sin(theta)**2,
|
| 477 |
+
ctx.fac(absm), 2]
|
| 478 |
+
P = [0.5*m*(ctx.sign(m)+1), 1, 0.5, 0.5*absm, -1, -absm-1]
|
| 479 |
+
return ((C, P, [], [], [absm-l, l+absm+1], [absm+1],
|
| 480 |
+
ctx.sin(0.5*theta)**2),)
|
| 481 |
+
else:
|
| 482 |
+
# http://functions.wolfram.com/HypergeometricFunctions/
|
| 483 |
+
# SphericalHarmonicYGeneral/26/01/02/0001/
|
| 484 |
+
def h(l,m):
|
| 485 |
+
if ctx.isnpint(l-m+1) or ctx.isnpint(l+m+1) or ctx.isnpint(1-m):
|
| 486 |
+
return (([0], [-1], [], [], [], [], 0),)
|
| 487 |
+
cos, sin = ctx.cos_sin(0.5*theta)
|
| 488 |
+
C = [0.5*ctx.expj(m*phi), (2*l+1)/ctx.pi,
|
| 489 |
+
ctx.gamma(l-m+1), ctx.gamma(l+m+1),
|
| 490 |
+
cos**2, sin**2]
|
| 491 |
+
P = [1, 0.5, 0.5, -0.5, 0.5*m, -0.5*m]
|
| 492 |
+
return ((C, P, [], [1-m], [-l,l+1], [1-m], sin**2),)
|
| 493 |
+
return ctx.hypercomb(h, [l,m], **kwargs)
|
.venv/lib/python3.11/site-packages/mpmath/functions/qfunctions.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .functions import defun, defun_wrapped
|
| 2 |
+
|
| 3 |
+
@defun
|
| 4 |
+
def qp(ctx, a, q=None, n=None, **kwargs):
|
| 5 |
+
r"""
|
| 6 |
+
Evaluates the q-Pochhammer symbol (or q-rising factorial)
|
| 7 |
+
|
| 8 |
+
.. math ::
|
| 9 |
+
|
| 10 |
+
(a; q)_n = \prod_{k=0}^{n-1} (1-a q^k)
|
| 11 |
+
|
| 12 |
+
where `n = \infty` is permitted if `|q| < 1`. Called with two arguments,
|
| 13 |
+
``qp(a,q)`` computes `(a;q)_{\infty}`; with a single argument, ``qp(q)``
|
| 14 |
+
computes `(q;q)_{\infty}`. The special case
|
| 15 |
+
|
| 16 |
+
.. math ::
|
| 17 |
+
|
| 18 |
+
\phi(q) = (q; q)_{\infty} = \prod_{k=1}^{\infty} (1-q^k) =
|
| 19 |
+
\sum_{k=-\infty}^{\infty} (-1)^k q^{(3k^2-k)/2}
|
| 20 |
+
|
| 21 |
+
is also known as the Euler function, or (up to a factor `q^{-1/24}`)
|
| 22 |
+
the Dedekind eta function.
|
| 23 |
+
|
| 24 |
+
**Examples**
|
| 25 |
+
|
| 26 |
+
If `n` is a positive integer, the function amounts to a finite product::
|
| 27 |
+
|
| 28 |
+
>>> from mpmath import *
|
| 29 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 30 |
+
>>> qp(2,3,5)
|
| 31 |
+
-725305.0
|
| 32 |
+
>>> fprod(1-2*3**k for k in range(5))
|
| 33 |
+
-725305.0
|
| 34 |
+
>>> qp(2,3,0)
|
| 35 |
+
1.0
|
| 36 |
+
|
| 37 |
+
Complex arguments are allowed::
|
| 38 |
+
|
| 39 |
+
>>> qp(2-1j, 0.75j)
|
| 40 |
+
(0.4628842231660149089976379 + 4.481821753552703090628793j)
|
| 41 |
+
|
| 42 |
+
The regular Pochhammer symbol `(a)_n` is obtained in the
|
| 43 |
+
following limit as `q \to 1`::
|
| 44 |
+
|
| 45 |
+
>>> a, n = 4, 7
|
| 46 |
+
>>> limit(lambda q: qp(q**a,q,n) / (1-q)**n, 1)
|
| 47 |
+
604800.0
|
| 48 |
+
>>> rf(a,n)
|
| 49 |
+
604800.0
|
| 50 |
+
|
| 51 |
+
The Taylor series of the reciprocal Euler function gives
|
| 52 |
+
the partition function `P(n)`, i.e. the number of ways of writing
|
| 53 |
+
`n` as a sum of positive integers::
|
| 54 |
+
|
| 55 |
+
>>> taylor(lambda q: 1/qp(q), 0, 10)
|
| 56 |
+
[1.0, 1.0, 2.0, 3.0, 5.0, 7.0, 11.0, 15.0, 22.0, 30.0, 42.0]
|
| 57 |
+
|
| 58 |
+
Special values include::
|
| 59 |
+
|
| 60 |
+
>>> qp(0)
|
| 61 |
+
1.0
|
| 62 |
+
>>> findroot(diffun(qp), -0.4) # location of maximum
|
| 63 |
+
-0.4112484791779547734440257
|
| 64 |
+
>>> qp(_)
|
| 65 |
+
1.228348867038575112586878
|
| 66 |
+
|
| 67 |
+
The q-Pochhammer symbol is related to the Jacobi theta functions.
|
| 68 |
+
For example, the following identity holds::
|
| 69 |
+
|
| 70 |
+
>>> q = mpf(0.5) # arbitrary
|
| 71 |
+
>>> qp(q)
|
| 72 |
+
0.2887880950866024212788997
|
| 73 |
+
>>> root(3,-2)*root(q,-24)*jtheta(2,pi/6,root(q,6))
|
| 74 |
+
0.2887880950866024212788997
|
| 75 |
+
|
| 76 |
+
"""
|
| 77 |
+
a = ctx.convert(a)
|
| 78 |
+
if n is None:
|
| 79 |
+
n = ctx.inf
|
| 80 |
+
else:
|
| 81 |
+
n = ctx.convert(n)
|
| 82 |
+
if n < 0:
|
| 83 |
+
raise ValueError("n cannot be negative")
|
| 84 |
+
if q is None:
|
| 85 |
+
q = a
|
| 86 |
+
else:
|
| 87 |
+
q = ctx.convert(q)
|
| 88 |
+
if n == 0:
|
| 89 |
+
return ctx.one + 0*(a+q)
|
| 90 |
+
infinite = (n == ctx.inf)
|
| 91 |
+
same = (a == q)
|
| 92 |
+
if infinite:
|
| 93 |
+
if abs(q) >= 1:
|
| 94 |
+
if same and (q == -1 or q == 1):
|
| 95 |
+
return ctx.zero * q
|
| 96 |
+
raise ValueError("q-function only defined for |q| < 1")
|
| 97 |
+
elif q == 0:
|
| 98 |
+
return ctx.one - a
|
| 99 |
+
maxterms = kwargs.get('maxterms', 50*ctx.prec)
|
| 100 |
+
if infinite and same:
|
| 101 |
+
# Euler's pentagonal theorem
|
| 102 |
+
def terms():
|
| 103 |
+
t = 1
|
| 104 |
+
yield t
|
| 105 |
+
k = 1
|
| 106 |
+
x1 = q
|
| 107 |
+
x2 = q**2
|
| 108 |
+
while 1:
|
| 109 |
+
yield (-1)**k * x1
|
| 110 |
+
yield (-1)**k * x2
|
| 111 |
+
x1 *= q**(3*k+1)
|
| 112 |
+
x2 *= q**(3*k+2)
|
| 113 |
+
k += 1
|
| 114 |
+
if k > maxterms:
|
| 115 |
+
raise ctx.NoConvergence
|
| 116 |
+
return ctx.sum_accurately(terms)
|
| 117 |
+
# return ctx.nprod(lambda k: 1-a*q**k, [0,n-1])
|
| 118 |
+
def factors():
|
| 119 |
+
k = 0
|
| 120 |
+
r = ctx.one
|
| 121 |
+
while 1:
|
| 122 |
+
yield 1 - a*r
|
| 123 |
+
r *= q
|
| 124 |
+
k += 1
|
| 125 |
+
if k >= n:
|
| 126 |
+
return
|
| 127 |
+
if k > maxterms:
|
| 128 |
+
raise ctx.NoConvergence
|
| 129 |
+
return ctx.mul_accurately(factors)
|
| 130 |
+
|
| 131 |
+
@defun_wrapped
|
| 132 |
+
def qgamma(ctx, z, q, **kwargs):
|
| 133 |
+
r"""
|
| 134 |
+
Evaluates the q-gamma function
|
| 135 |
+
|
| 136 |
+
.. math ::
|
| 137 |
+
|
| 138 |
+
\Gamma_q(z) = \frac{(q; q)_{\infty}}{(q^z; q)_{\infty}} (1-q)^{1-z}.
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
**Examples**
|
| 142 |
+
|
| 143 |
+
Evaluation for real and complex arguments::
|
| 144 |
+
|
| 145 |
+
>>> from mpmath import *
|
| 146 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 147 |
+
>>> qgamma(4,0.75)
|
| 148 |
+
4.046875
|
| 149 |
+
>>> qgamma(6,6)
|
| 150 |
+
121226245.0
|
| 151 |
+
>>> qgamma(3+4j, 0.5j)
|
| 152 |
+
(0.1663082382255199834630088 + 0.01952474576025952984418217j)
|
| 153 |
+
|
| 154 |
+
The q-gamma function satisfies a functional equation similar
|
| 155 |
+
to that of the ordinary gamma function::
|
| 156 |
+
|
| 157 |
+
>>> q = mpf(0.25)
|
| 158 |
+
>>> z = mpf(2.5)
|
| 159 |
+
>>> qgamma(z+1,q)
|
| 160 |
+
1.428277424823760954685912
|
| 161 |
+
>>> (1-q**z)/(1-q)*qgamma(z,q)
|
| 162 |
+
1.428277424823760954685912
|
| 163 |
+
|
| 164 |
+
"""
|
| 165 |
+
if abs(q) > 1:
|
| 166 |
+
return ctx.qgamma(z,1/q)*q**((z-2)*(z-1)*0.5)
|
| 167 |
+
return ctx.qp(q, q, None, **kwargs) / \
|
| 168 |
+
ctx.qp(q**z, q, None, **kwargs) * (1-q)**(1-z)
|
| 169 |
+
|
| 170 |
+
@defun_wrapped
|
| 171 |
+
def qfac(ctx, z, q, **kwargs):
|
| 172 |
+
r"""
|
| 173 |
+
Evaluates the q-factorial,
|
| 174 |
+
|
| 175 |
+
.. math ::
|
| 176 |
+
|
| 177 |
+
[n]_q! = (1+q)(1+q+q^2)\cdots(1+q+\cdots+q^{n-1})
|
| 178 |
+
|
| 179 |
+
or more generally
|
| 180 |
+
|
| 181 |
+
.. math ::
|
| 182 |
+
|
| 183 |
+
[z]_q! = \frac{(q;q)_z}{(1-q)^z}.
|
| 184 |
+
|
| 185 |
+
**Examples**
|
| 186 |
+
|
| 187 |
+
>>> from mpmath import *
|
| 188 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 189 |
+
>>> qfac(0,0)
|
| 190 |
+
1.0
|
| 191 |
+
>>> qfac(4,3)
|
| 192 |
+
2080.0
|
| 193 |
+
>>> qfac(5,6)
|
| 194 |
+
121226245.0
|
| 195 |
+
>>> qfac(1+1j, 2+1j)
|
| 196 |
+
(0.4370556551322672478613695 + 0.2609739839216039203708921j)
|
| 197 |
+
|
| 198 |
+
"""
|
| 199 |
+
if ctx.isint(z) and ctx._re(z) > 0:
|
| 200 |
+
n = int(ctx._re(z))
|
| 201 |
+
return ctx.qp(q, q, n, **kwargs) / (1-q)**n
|
| 202 |
+
return ctx.qgamma(z+1, q, **kwargs)
|
| 203 |
+
|
| 204 |
+
@defun
|
| 205 |
+
def qhyper(ctx, a_s, b_s, q, z, **kwargs):
|
| 206 |
+
r"""
|
| 207 |
+
Evaluates the basic hypergeometric series or hypergeometric q-series
|
| 208 |
+
|
| 209 |
+
.. math ::
|
| 210 |
+
|
| 211 |
+
\,_r\phi_s \left[\begin{matrix}
|
| 212 |
+
a_1 & a_2 & \ldots & a_r \\
|
| 213 |
+
b_1 & b_2 & \ldots & b_s
|
| 214 |
+
\end{matrix} ; q,z \right] =
|
| 215 |
+
\sum_{n=0}^\infty
|
| 216 |
+
\frac{(a_1;q)_n, \ldots, (a_r;q)_n}
|
| 217 |
+
{(b_1;q)_n, \ldots, (b_s;q)_n}
|
| 218 |
+
\left((-1)^n q^{n\choose 2}\right)^{1+s-r}
|
| 219 |
+
\frac{z^n}{(q;q)_n}
|
| 220 |
+
|
| 221 |
+
where `(a;q)_n` denotes the q-Pochhammer symbol (see :func:`~mpmath.qp`).
|
| 222 |
+
|
| 223 |
+
**Examples**
|
| 224 |
+
|
| 225 |
+
Evaluation works for real and complex arguments::
|
| 226 |
+
|
| 227 |
+
>>> from mpmath import *
|
| 228 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 229 |
+
>>> qhyper([0.5], [2.25], 0.25, 4)
|
| 230 |
+
-0.1975849091263356009534385
|
| 231 |
+
>>> qhyper([0.5], [2.25], 0.25-0.25j, 4)
|
| 232 |
+
(2.806330244925716649839237 + 3.568997623337943121769938j)
|
| 233 |
+
>>> qhyper([1+j], [2,3+0.5j], 0.25, 3+4j)
|
| 234 |
+
(9.112885171773400017270226 - 1.272756997166375050700388j)
|
| 235 |
+
|
| 236 |
+
Comparing with a summation of the defining series, using
|
| 237 |
+
:func:`~mpmath.nsum`::
|
| 238 |
+
|
| 239 |
+
>>> b, q, z = 3, 0.25, 0.5
|
| 240 |
+
>>> qhyper([], [b], q, z)
|
| 241 |
+
0.6221136748254495583228324
|
| 242 |
+
>>> nsum(lambda n: z**n / qp(q,q,n)/qp(b,q,n) * q**(n*(n-1)), [0,inf])
|
| 243 |
+
0.6221136748254495583228324
|
| 244 |
+
|
| 245 |
+
"""
|
| 246 |
+
#a_s = [ctx._convert_param(a)[0] for a in a_s]
|
| 247 |
+
#b_s = [ctx._convert_param(b)[0] for b in b_s]
|
| 248 |
+
#q = ctx._convert_param(q)[0]
|
| 249 |
+
a_s = [ctx.convert(a) for a in a_s]
|
| 250 |
+
b_s = [ctx.convert(b) for b in b_s]
|
| 251 |
+
q = ctx.convert(q)
|
| 252 |
+
z = ctx.convert(z)
|
| 253 |
+
r = len(a_s)
|
| 254 |
+
s = len(b_s)
|
| 255 |
+
d = 1+s-r
|
| 256 |
+
maxterms = kwargs.get('maxterms', 50*ctx.prec)
|
| 257 |
+
def terms():
|
| 258 |
+
t = ctx.one
|
| 259 |
+
yield t
|
| 260 |
+
qk = 1
|
| 261 |
+
k = 0
|
| 262 |
+
x = 1
|
| 263 |
+
while 1:
|
| 264 |
+
for a in a_s:
|
| 265 |
+
p = 1 - a*qk
|
| 266 |
+
t *= p
|
| 267 |
+
for b in b_s:
|
| 268 |
+
p = 1 - b*qk
|
| 269 |
+
if not p:
|
| 270 |
+
raise ValueError
|
| 271 |
+
t /= p
|
| 272 |
+
t *= z
|
| 273 |
+
x *= (-1)**d * qk ** d
|
| 274 |
+
qk *= q
|
| 275 |
+
t /= (1 - qk)
|
| 276 |
+
k += 1
|
| 277 |
+
yield t * x
|
| 278 |
+
if k > maxterms:
|
| 279 |
+
raise ctx.NoConvergence
|
| 280 |
+
return ctx.sum_accurately(terms)
|
.venv/lib/python3.11/site-packages/mpmath/functions/rszeta.py
ADDED
|
@@ -0,0 +1,1403 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
---------------------------------------------------------------------
|
| 3 |
+
.. sectionauthor:: Juan Arias de Reyna <arias@us.es>
|
| 4 |
+
|
| 5 |
+
This module implements zeta-related functions using the Riemann-Siegel
|
| 6 |
+
expansion: zeta_offline(s,k=0)
|
| 7 |
+
|
| 8 |
+
* coef(J, eps): Need in the computation of Rzeta(s,k)
|
| 9 |
+
|
| 10 |
+
* Rzeta_simul(s, der=0) computes Rzeta^(k)(s) and Rzeta^(k)(1-s) simultaneously
|
| 11 |
+
for 0 <= k <= der. Used by zeta_offline and z_offline
|
| 12 |
+
|
| 13 |
+
* Rzeta_set(s, derivatives) computes Rzeta^(k)(s) for given derivatives, used by
|
| 14 |
+
z_half(t,k) and zeta_half
|
| 15 |
+
|
| 16 |
+
* z_offline(w,k): Z(w) and its derivatives of order k <= 4
|
| 17 |
+
* z_half(t,k): Z(t) (Riemann Siegel function) and its derivatives of order k <= 4
|
| 18 |
+
* zeta_offline(s): zeta(s) and its derivatives of order k<= 4
|
| 19 |
+
* zeta_half(1/2+it,k): zeta(s) and its derivatives of order k<= 4
|
| 20 |
+
|
| 21 |
+
* rs_zeta(s,k=0) Computes zeta^(k)(s) Unifies zeta_half and zeta_offline
|
| 22 |
+
* rs_z(w,k=0) Computes Z^(k)(w) Unifies z_offline and z_half
|
| 23 |
+
----------------------------------------------------------------------
|
| 24 |
+
|
| 25 |
+
This program uses Riemann-Siegel expansion even to compute
|
| 26 |
+
zeta(s) on points s = sigma + i t with sigma arbitrary not
|
| 27 |
+
necessarily equal to 1/2.
|
| 28 |
+
|
| 29 |
+
It is founded on a new deduction of the formula, with rigorous
|
| 30 |
+
and sharp bounds for the terms and rest of this expansion.
|
| 31 |
+
|
| 32 |
+
More information on the papers:
|
| 33 |
+
|
| 34 |
+
J. Arias de Reyna, High Precision Computation of Riemann's
|
| 35 |
+
Zeta Function by the Riemann-Siegel Formula I, II
|
| 36 |
+
|
| 37 |
+
We refer to them as I, II.
|
| 38 |
+
|
| 39 |
+
In them we shall find detailed explanation of all the
|
| 40 |
+
procedure.
|
| 41 |
+
|
| 42 |
+
The program uses Riemann-Siegel expansion.
|
| 43 |
+
This is useful when t is big, ( say t > 10000 ).
|
| 44 |
+
The precision is limited, roughly it can compute zeta(sigma+it)
|
| 45 |
+
with an error less than exp(-c t) for some constant c depending
|
| 46 |
+
on sigma. The program gives an error when the Riemann-Siegel
|
| 47 |
+
formula can not compute to the wanted precision.
|
| 48 |
+
|
| 49 |
+
"""
|
| 50 |
+
|
| 51 |
+
import math
|
| 52 |
+
|
| 53 |
+
class RSCache(object):
|
| 54 |
+
def __init__(ctx):
|
| 55 |
+
ctx._rs_cache = [0, 10, {}, {}]
|
| 56 |
+
|
| 57 |
+
from .functions import defun
|
| 58 |
+
|
| 59 |
+
#-------------------------------------------------------------------------------#
|
| 60 |
+
# #
|
| 61 |
+
# coef(ctx, J, eps, _cache=[0, 10, {} ] ) #
|
| 62 |
+
# #
|
| 63 |
+
#-------------------------------------------------------------------------------#
|
| 64 |
+
|
| 65 |
+
# This function computes the coefficients c[n] defined on (I, equation (47))
|
| 66 |
+
# but see also (II, section 3.14).
|
| 67 |
+
#
|
| 68 |
+
# Since these coefficients are very difficult to compute we save the values
|
| 69 |
+
# in a cache. So if we compute several values of the functions Rzeta(s) for
|
| 70 |
+
# near values of s, we do not recompute these coefficients.
|
| 71 |
+
#
|
| 72 |
+
# c[n] are the Taylor coefficients of the function:
|
| 73 |
+
#
|
| 74 |
+
# F(z):= (exp(pi*j*(z*z/2+3/8))-j* sqrt(2) cos(pi*z/2))/(2*cos(pi *z))
|
| 75 |
+
#
|
| 76 |
+
#
|
| 77 |
+
|
| 78 |
+
def _coef(ctx, J, eps):
|
| 79 |
+
r"""
|
| 80 |
+
Computes the coefficients `c_n` for `0\le n\le 2J` with error less than eps
|
| 81 |
+
|
| 82 |
+
**Definition**
|
| 83 |
+
|
| 84 |
+
The coefficients c_n are defined by
|
| 85 |
+
|
| 86 |
+
.. math ::
|
| 87 |
+
|
| 88 |
+
\begin{equation}
|
| 89 |
+
F(z)=\frac{e^{\pi i
|
| 90 |
+
\bigl(\frac{z^2}{2}+\frac38\bigr)}-i\sqrt{2}\cos\frac{\pi}{2}z}{2\cos\pi
|
| 91 |
+
z}=\sum_{n=0}^\infty c_{2n} z^{2n}
|
| 92 |
+
\end{equation}
|
| 93 |
+
|
| 94 |
+
they are computed applying the relation
|
| 95 |
+
|
| 96 |
+
.. math ::
|
| 97 |
+
|
| 98 |
+
\begin{multline}
|
| 99 |
+
c_{2n}=-\frac{i}{\sqrt{2}}\Bigl(\frac{\pi}{2}\Bigr)^{2n}
|
| 100 |
+
\sum_{k=0}^n\frac{(-1)^k}{(2k)!}
|
| 101 |
+
2^{2n-2k}\frac{(-1)^{n-k}E_{2n-2k}}{(2n-2k)!}+\\
|
| 102 |
+
+e^{3\pi i/8}\sum_{j=0}^n(-1)^j\frac{
|
| 103 |
+
E_{2j}}{(2j)!}\frac{i^{n-j}\pi^{n+j}}{(n-j)!2^{n-j+1}}.
|
| 104 |
+
\end{multline}
|
| 105 |
+
"""
|
| 106 |
+
|
| 107 |
+
newJ = J+2 # compute more coefficients that are needed
|
| 108 |
+
neweps6 = eps/2. # compute with a slight more precision that are needed
|
| 109 |
+
|
| 110 |
+
# PREPARATION FOR THE COMPUTATION OF V(N) AND W(N)
|
| 111 |
+
# See II Section 3.16
|
| 112 |
+
#
|
| 113 |
+
# Computing the exponent wpvw of the error II equation (81)
|
| 114 |
+
wpvw = max(ctx.mag(10*(newJ+3)), 4*newJ+5-ctx.mag(neweps6))
|
| 115 |
+
|
| 116 |
+
# Preparation of Euler numbers (we need until the 2*RS_NEWJ)
|
| 117 |
+
E = ctx._eulernum(2*newJ)
|
| 118 |
+
|
| 119 |
+
# Now we have in the cache all the needed Euler numbers.
|
| 120 |
+
#
|
| 121 |
+
# Computing the powers of pi
|
| 122 |
+
#
|
| 123 |
+
# We need to compute the powers pi**n for 1<= n <= 2*J
|
| 124 |
+
# with relative error less than 2**(-wpvw)
|
| 125 |
+
# it is easy to show that this is obtained
|
| 126 |
+
# taking wppi as the least d with
|
| 127 |
+
# 2**d>40*J and 2**d> 4.24 *newJ + 2**wpvw
|
| 128 |
+
# In II Section 3.9 we need also that
|
| 129 |
+
# wppi > wptcoef[0], and that the powers
|
| 130 |
+
# here computed 0<= k <= 2*newJ are more
|
| 131 |
+
# than those needed there that are 2*L-2.
|
| 132 |
+
# so we need J >= L this will be checked
|
| 133 |
+
# before computing tcoef[]
|
| 134 |
+
wppi = max(ctx.mag(40*newJ), ctx.mag(newJ)+3 +wpvw)
|
| 135 |
+
ctx.prec = wppi
|
| 136 |
+
pipower = {}
|
| 137 |
+
pipower[0] = ctx.one
|
| 138 |
+
pipower[1] = ctx.pi
|
| 139 |
+
for n in range(2,2*newJ+1):
|
| 140 |
+
pipower[n] = pipower[n-1]*ctx.pi
|
| 141 |
+
|
| 142 |
+
# COMPUTING THE COEFFICIENTS v(n) AND w(n)
|
| 143 |
+
# see II equation (61) and equations (81) and (82)
|
| 144 |
+
ctx.prec = wpvw+2
|
| 145 |
+
v={}
|
| 146 |
+
w={}
|
| 147 |
+
for n in range(0,newJ+1):
|
| 148 |
+
va = (-1)**n * ctx._eulernum(2*n)
|
| 149 |
+
va = ctx.mpf(va)/ctx.fac(2*n)
|
| 150 |
+
v[n]=va*pipower[2*n]
|
| 151 |
+
for n in range(0,2*newJ+1):
|
| 152 |
+
wa = ctx.one/ctx.fac(n)
|
| 153 |
+
wa=wa/(2**n)
|
| 154 |
+
w[n]=wa*pipower[n]
|
| 155 |
+
|
| 156 |
+
# COMPUTATION OF THE CONVOLUTIONS RS_P1 AND RS_P2
|
| 157 |
+
# See II Section 3.16
|
| 158 |
+
ctx.prec = 15
|
| 159 |
+
wpp1a = 9 - ctx.mag(neweps6)
|
| 160 |
+
P1 = {}
|
| 161 |
+
for n in range(0,newJ+1):
|
| 162 |
+
ctx.prec = 15
|
| 163 |
+
wpp1 = max(ctx.mag(10*(n+4)),4*n+wpp1a)
|
| 164 |
+
ctx.prec = wpp1
|
| 165 |
+
sump = 0
|
| 166 |
+
for k in range(0,n+1):
|
| 167 |
+
sump += ((-1)**k) * v[k]*w[2*n-2*k]
|
| 168 |
+
P1[n]=((-1)**(n+1))*ctx.j*sump
|
| 169 |
+
P2={}
|
| 170 |
+
for n in range(0,newJ+1):
|
| 171 |
+
ctx.prec = 15
|
| 172 |
+
wpp2 = max(ctx.mag(10*(n+4)),4*n+wpp1a)
|
| 173 |
+
ctx.prec = wpp2
|
| 174 |
+
sump = 0
|
| 175 |
+
for k in range(0,n+1):
|
| 176 |
+
sump += (ctx.j**(n-k)) * v[k]*w[n-k]
|
| 177 |
+
P2[n]=sump
|
| 178 |
+
# COMPUTING THE COEFFICIENTS c[2n]
|
| 179 |
+
# See II Section 3.14
|
| 180 |
+
ctx.prec = 15
|
| 181 |
+
wpc0 = 5 - ctx.mag(neweps6)
|
| 182 |
+
wpc = max(6,4*newJ+wpc0)
|
| 183 |
+
ctx.prec = wpc
|
| 184 |
+
mu = ctx.sqrt(ctx.mpf('2'))/2
|
| 185 |
+
nu = ctx.expjpi(3./8)/2
|
| 186 |
+
c={}
|
| 187 |
+
for n in range(0,newJ):
|
| 188 |
+
ctx.prec = 15
|
| 189 |
+
wpc = max(6,4*n+wpc0)
|
| 190 |
+
ctx.prec = wpc
|
| 191 |
+
c[2*n] = mu*P1[n]+nu*P2[n]
|
| 192 |
+
for n in range(1,2*newJ,2):
|
| 193 |
+
c[n] = 0
|
| 194 |
+
return [newJ, neweps6, c, pipower]
|
| 195 |
+
|
| 196 |
+
def coef(ctx, J, eps):
|
| 197 |
+
_cache = ctx._rs_cache
|
| 198 |
+
if J <= _cache[0] and eps >= _cache[1]:
|
| 199 |
+
return _cache[2], _cache[3]
|
| 200 |
+
orig = ctx._mp.prec
|
| 201 |
+
try:
|
| 202 |
+
data = _coef(ctx._mp, J, eps)
|
| 203 |
+
finally:
|
| 204 |
+
ctx._mp.prec = orig
|
| 205 |
+
if ctx is not ctx._mp:
|
| 206 |
+
data[2] = dict((k,ctx.convert(v)) for (k,v) in data[2].items())
|
| 207 |
+
data[3] = dict((k,ctx.convert(v)) for (k,v) in data[3].items())
|
| 208 |
+
ctx._rs_cache[:] = data
|
| 209 |
+
return ctx._rs_cache[2], ctx._rs_cache[3]
|
| 210 |
+
|
| 211 |
+
#-------------------------------------------------------------------------------#
|
| 212 |
+
# #
|
| 213 |
+
# Rzeta_simul(s,k=0) #
|
| 214 |
+
# #
|
| 215 |
+
#-------------------------------------------------------------------------------#
|
| 216 |
+
# This function return a list with the values:
|
| 217 |
+
# Rzeta(sigma+it), conj(Rzeta(1-sigma+it)),Rzeta'(sigma+it), conj(Rzeta'(1-sigma+it)),
|
| 218 |
+
# .... , Rzeta^{(k)}(sigma+it), conj(Rzeta^{(k)}(1-sigma+it))
|
| 219 |
+
#
|
| 220 |
+
# Useful to compute the function zeta(s) and Z(w) or its derivatives.
|
| 221 |
+
#
|
| 222 |
+
|
| 223 |
+
def aux_M_Fp(ctx, xA, xeps4, a, xB1, xL):
|
| 224 |
+
# COMPUTING M NUMBER OF DERIVATIVES Fp[m] TO COMPUTE
|
| 225 |
+
# See II Section 3.11 equations (47) and (48)
|
| 226 |
+
aux1 = 126.0657606*xA/xeps4 # 126.06.. = 316/sqrt(2*pi)
|
| 227 |
+
aux1 = ctx.ln(aux1)
|
| 228 |
+
aux2 = (2*ctx.ln(ctx.pi)+ctx.ln(xB1)+ctx.ln(a))/3 -ctx.ln(2*ctx.pi)/2
|
| 229 |
+
m = 3*xL-3
|
| 230 |
+
aux3= (ctx.loggamma(m+1)-ctx.loggamma(m/3.0+2))/2 -ctx.loggamma((m+1)/2.)
|
| 231 |
+
while((aux1 < m*aux2+ aux3)and (m>1)):
|
| 232 |
+
m = m - 1
|
| 233 |
+
aux3 = (ctx.loggamma(m+1)-ctx.loggamma(m/3.0+2))/2 -ctx.loggamma((m+1)/2.)
|
| 234 |
+
xM = m
|
| 235 |
+
return xM
|
| 236 |
+
|
| 237 |
+
def aux_J_needed(ctx, xA, xeps4, a, xB1, xM):
|
| 238 |
+
# DETERMINATION OF J THE NUMBER OF TERMS NEEDED
|
| 239 |
+
# IN THE TAYLOR SERIES OF F.
|
| 240 |
+
# See II Section 3.11 equation (49))
|
| 241 |
+
# Only determine one
|
| 242 |
+
h1 = xeps4/(632*xA)
|
| 243 |
+
h2 = xB1*a * 126.31337419529260248 # = pi^2*e^2*sqrt(3)
|
| 244 |
+
h2 = h1 * ctx.power((h2/xM**2),(xM-1)/3) / xM
|
| 245 |
+
h3 = min(h1,h2)
|
| 246 |
+
return h3
|
| 247 |
+
|
| 248 |
+
def Rzeta_simul(ctx, s, der=0):
|
| 249 |
+
# First we take the value of ctx.prec
|
| 250 |
+
wpinitial = ctx.prec
|
| 251 |
+
|
| 252 |
+
# INITIALIZATION
|
| 253 |
+
# Take the real and imaginary part of s
|
| 254 |
+
t = ctx._im(s)
|
| 255 |
+
xsigma = ctx._re(s)
|
| 256 |
+
ysigma = 1 - xsigma
|
| 257 |
+
|
| 258 |
+
# Now compute several parameter that appear on the program
|
| 259 |
+
ctx.prec = 15
|
| 260 |
+
a = ctx.sqrt(t/(2*ctx.pi))
|
| 261 |
+
xasigma = a ** xsigma
|
| 262 |
+
yasigma = a ** ysigma
|
| 263 |
+
|
| 264 |
+
# We need a simple bound A1 < asigma (see II Section 3.1 and 3.3)
|
| 265 |
+
xA1=ctx.power(2, ctx.mag(xasigma)-1)
|
| 266 |
+
yA1=ctx.power(2, ctx.mag(yasigma)-1)
|
| 267 |
+
|
| 268 |
+
# We compute various epsilon's (see II end of Section 3.1)
|
| 269 |
+
eps = ctx.power(2, -wpinitial)
|
| 270 |
+
eps1 = eps/6.
|
| 271 |
+
xeps2 = eps * xA1/3.
|
| 272 |
+
yeps2 = eps * yA1/3.
|
| 273 |
+
|
| 274 |
+
# COMPUTING SOME COEFFICIENTS THAT DEPENDS
|
| 275 |
+
# ON sigma
|
| 276 |
+
# constant b and c (see I Theorem 2 formula (26) )
|
| 277 |
+
# coefficients A and B1 (see I Section 6.1 equation (50))
|
| 278 |
+
#
|
| 279 |
+
# here we not need high precision
|
| 280 |
+
ctx.prec = 15
|
| 281 |
+
if xsigma > 0:
|
| 282 |
+
xb = 2.
|
| 283 |
+
xc = math.pow(9,xsigma)/4.44288
|
| 284 |
+
# 4.44288 =(math.sqrt(2)*math.pi)
|
| 285 |
+
xA = math.pow(9,xsigma)
|
| 286 |
+
xB1 = 1
|
| 287 |
+
else:
|
| 288 |
+
xb = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi )
|
| 289 |
+
xc = math.pow(2,-xsigma)/4.44288
|
| 290 |
+
xA = math.pow(2,-xsigma)
|
| 291 |
+
xB1 = 1.10789 # = 2*sqrt(1-log(2))
|
| 292 |
+
|
| 293 |
+
if(ysigma > 0):
|
| 294 |
+
yb = 2.
|
| 295 |
+
yc = math.pow(9,ysigma)/4.44288
|
| 296 |
+
# 4.44288 =(math.sqrt(2)*math.pi)
|
| 297 |
+
yA = math.pow(9,ysigma)
|
| 298 |
+
yB1 = 1
|
| 299 |
+
else:
|
| 300 |
+
yb = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi )
|
| 301 |
+
yc = math.pow(2,-ysigma)/4.44288
|
| 302 |
+
yA = math.pow(2,-ysigma)
|
| 303 |
+
yB1 = 1.10789 # = 2*sqrt(1-log(2))
|
| 304 |
+
|
| 305 |
+
# COMPUTING L THE NUMBER OF TERMS NEEDED IN THE RIEMANN-SIEGEL
|
| 306 |
+
# CORRECTION
|
| 307 |
+
# See II Section 3.2
|
| 308 |
+
ctx.prec = 15
|
| 309 |
+
xL = 1
|
| 310 |
+
while 3*xc*ctx.gamma(xL*0.5) * ctx.power(xb*a,-xL) >= xeps2:
|
| 311 |
+
xL = xL+1
|
| 312 |
+
xL = max(2,xL)
|
| 313 |
+
yL = 1
|
| 314 |
+
while 3*yc*ctx.gamma(yL*0.5) * ctx.power(yb*a,-yL) >= yeps2:
|
| 315 |
+
yL = yL+1
|
| 316 |
+
yL = max(2,yL)
|
| 317 |
+
|
| 318 |
+
# The number L has to satify some conditions.
|
| 319 |
+
# If not RS can not compute Rzeta(s) with the prescribed precision
|
| 320 |
+
# (see II, Section 3.2 condition (20) ) and
|
| 321 |
+
# (II, Section 3.3 condition (22) ). Also we have added
|
| 322 |
+
# an additional technical condition in Section 3.17 Proposition 17
|
| 323 |
+
if ((3*xL >= 2*a*a/25.) or (3*xL+2+xsigma<0) or (abs(xsigma) > a/2.) or \
|
| 324 |
+
(3*yL >= 2*a*a/25.) or (3*yL+2+ysigma<0) or (abs(ysigma) > a/2.)):
|
| 325 |
+
ctx.prec = wpinitial
|
| 326 |
+
raise NotImplementedError("Riemann-Siegel can not compute with such precision")
|
| 327 |
+
|
| 328 |
+
# We take the maximum of the two values
|
| 329 |
+
L = max(xL, yL)
|
| 330 |
+
|
| 331 |
+
# INITIALIZATION (CONTINUATION)
|
| 332 |
+
#
|
| 333 |
+
# eps3 is the constant defined on (II, Section 3.5 equation (27) )
|
| 334 |
+
# each term of the RS correction must be computed with error <= eps3
|
| 335 |
+
xeps3 = xeps2/(4*xL)
|
| 336 |
+
yeps3 = yeps2/(4*yL)
|
| 337 |
+
|
| 338 |
+
# eps4 is defined on (II Section 3.6 equation (30) )
|
| 339 |
+
# each component of the formula (II Section 3.6 equation (29) )
|
| 340 |
+
# must be computed with error <= eps4
|
| 341 |
+
xeps4 = xeps3/(3*xL)
|
| 342 |
+
yeps4 = yeps3/(3*yL)
|
| 343 |
+
|
| 344 |
+
# COMPUTING M NUMBER OF DERIVATIVES Fp[m] TO COMPUTE
|
| 345 |
+
xM = aux_M_Fp(ctx, xA, xeps4, a, xB1, xL)
|
| 346 |
+
yM = aux_M_Fp(ctx, yA, yeps4, a, yB1, yL)
|
| 347 |
+
M = max(xM, yM)
|
| 348 |
+
|
| 349 |
+
# COMPUTING NUMBER OF TERMS J NEEDED
|
| 350 |
+
h3 = aux_J_needed(ctx, xA, xeps4, a, xB1, xM)
|
| 351 |
+
h4 = aux_J_needed(ctx, yA, yeps4, a, yB1, yM)
|
| 352 |
+
h3 = min(h3,h4)
|
| 353 |
+
J = 12
|
| 354 |
+
jvalue = (2*ctx.pi)**J / ctx.gamma(J+1)
|
| 355 |
+
while jvalue > h3:
|
| 356 |
+
J = J+1
|
| 357 |
+
jvalue = (2*ctx.pi)*jvalue/J
|
| 358 |
+
|
| 359 |
+
# COMPUTING eps5[m] for 1 <= m <= 21
|
| 360 |
+
# See II Section 10 equation (43)
|
| 361 |
+
# We choose the minimum of the two possibilities
|
| 362 |
+
eps5={}
|
| 363 |
+
xforeps5 = math.pi*math.pi*xB1*a
|
| 364 |
+
yforeps5 = math.pi*math.pi*yB1*a
|
| 365 |
+
for m in range(0,22):
|
| 366 |
+
xaux1 = math.pow(xforeps5, m/3)/(316.*xA)
|
| 367 |
+
yaux1 = math.pow(yforeps5, m/3)/(316.*yA)
|
| 368 |
+
aux1 = min(xaux1, yaux1)
|
| 369 |
+
aux2 = ctx.gamma(m+1)/ctx.gamma(m/3.0+0.5)
|
| 370 |
+
aux2 = math.sqrt(aux2)
|
| 371 |
+
eps5[m] = (aux1*aux2*min(xeps4,yeps4))
|
| 372 |
+
|
| 373 |
+
# COMPUTING wpfp
|
| 374 |
+
# See II Section 3.13 equation (59)
|
| 375 |
+
twenty = min(3*L-3, 21)+1
|
| 376 |
+
aux = 6812*J
|
| 377 |
+
wpfp = ctx.mag(44*J)
|
| 378 |
+
for m in range(0,twenty):
|
| 379 |
+
wpfp = max(wpfp, ctx.mag(aux*ctx.gamma(m+1)/eps5[m]))
|
| 380 |
+
|
| 381 |
+
# COMPUTING N AND p
|
| 382 |
+
# See II Section
|
| 383 |
+
ctx.prec = wpfp + ctx.mag(t)+20
|
| 384 |
+
a = ctx.sqrt(t/(2*ctx.pi))
|
| 385 |
+
N = ctx.floor(a)
|
| 386 |
+
p = 1-2*(a-N)
|
| 387 |
+
|
| 388 |
+
# now we get a rounded version of p
|
| 389 |
+
# to the precision wpfp
|
| 390 |
+
# this possibly is not necessary
|
| 391 |
+
num=ctx.floor(p*(ctx.mpf('2')**wpfp))
|
| 392 |
+
difference = p * (ctx.mpf('2')**wpfp)-num
|
| 393 |
+
if (difference < 0.5):
|
| 394 |
+
num = num
|
| 395 |
+
else:
|
| 396 |
+
num = num+1
|
| 397 |
+
p = ctx.convert(num * (ctx.mpf('2')**(-wpfp)))
|
| 398 |
+
|
| 399 |
+
# COMPUTING THE COEFFICIENTS c[n] = cc[n]
|
| 400 |
+
# We shall use the notation cc[n], since there is
|
| 401 |
+
# a constant that is called c
|
| 402 |
+
# See II Section 3.14
|
| 403 |
+
# We compute the coefficients and also save then in a
|
| 404 |
+
# cache. The bulk of the computation is passed to
|
| 405 |
+
# the function coef()
|
| 406 |
+
#
|
| 407 |
+
# eps6 is defined in II Section 3.13 equation (58)
|
| 408 |
+
eps6 = ctx.power(ctx.convert(2*ctx.pi), J)/(ctx.gamma(J+1)*3*J)
|
| 409 |
+
|
| 410 |
+
# Now we compute the coefficients
|
| 411 |
+
cc = {}
|
| 412 |
+
cont = {}
|
| 413 |
+
cont, pipowers = coef(ctx, J, eps6)
|
| 414 |
+
cc=cont.copy() # we need a copy since we have to change his values.
|
| 415 |
+
Fp={} # this is the adequate locus of this
|
| 416 |
+
for n in range(M, 3*L-2):
|
| 417 |
+
Fp[n] = 0
|
| 418 |
+
Fp={}
|
| 419 |
+
ctx.prec = wpfp
|
| 420 |
+
for m in range(0,M+1):
|
| 421 |
+
sumP = 0
|
| 422 |
+
for k in range(2*J-m-1,-1,-1):
|
| 423 |
+
sumP = (sumP * p)+ cc[k]
|
| 424 |
+
Fp[m] = sumP
|
| 425 |
+
# preparation of the new coefficients
|
| 426 |
+
for k in range(0,2*J-m-1):
|
| 427 |
+
cc[k] = (k+1)* cc[k+1]
|
| 428 |
+
|
| 429 |
+
# COMPUTING THE NUMBERS xd[u,n,k], yd[u,n,k]
|
| 430 |
+
# See II Section 3.17
|
| 431 |
+
#
|
| 432 |
+
# First we compute the working precisions xwpd[k]
|
| 433 |
+
# Se II equation (92)
|
| 434 |
+
xwpd={}
|
| 435 |
+
d1 = max(6,ctx.mag(40*L*L))
|
| 436 |
+
xd2 = 13+ctx.mag((1+abs(xsigma))*xA)-ctx.mag(xeps4)-1
|
| 437 |
+
xconst = ctx.ln(8/(ctx.pi*ctx.pi*a*a*xB1*xB1)) /2
|
| 438 |
+
for n in range(0,L):
|
| 439 |
+
xd3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*xconst)+xd2
|
| 440 |
+
xwpd[n]=max(xd3,d1)
|
| 441 |
+
|
| 442 |
+
# procedure of II Section 3.17
|
| 443 |
+
ctx.prec = xwpd[1]+10
|
| 444 |
+
xpsigma = 1-(2*xsigma)
|
| 445 |
+
xd = {}
|
| 446 |
+
xd[0,0,-2]=0; xd[0,0,-1]=0; xd[0,0,0]=1; xd[0,0,1]=0
|
| 447 |
+
xd[0,-1,-2]=0; xd[0,-1,-1]=0; xd[0,-1,0]=1; xd[0,-1,1]=0
|
| 448 |
+
for n in range(1,L):
|
| 449 |
+
ctx.prec = xwpd[n]+10
|
| 450 |
+
for k in range(0,3*n//2+1):
|
| 451 |
+
m = 3*n-2*k
|
| 452 |
+
if(m!=0):
|
| 453 |
+
m1 = ctx.one/m
|
| 454 |
+
c1= m1/4
|
| 455 |
+
c2=(xpsigma*m1)/2
|
| 456 |
+
c3=-(m+1)
|
| 457 |
+
xd[0,n,k]=c3*xd[0,n-1,k-2]+c1*xd[0,n-1,k]+c2*xd[0,n-1,k-1]
|
| 458 |
+
else:
|
| 459 |
+
xd[0,n,k]=0
|
| 460 |
+
for r in range(0,k):
|
| 461 |
+
add=xd[0,n,r]*(ctx.mpf('1.0')*ctx.fac(2*k-2*r)/ctx.fac(k-r))
|
| 462 |
+
xd[0,n,k] -= ((-1)**(k-r))*add
|
| 463 |
+
xd[0,n,-2]=0; xd[0,n,-1]=0; xd[0,n,3*n//2+1]=0
|
| 464 |
+
for mu in range(-2,der+1):
|
| 465 |
+
for n in range(-2,L):
|
| 466 |
+
for k in range(-3,max(1,3*n//2+2)):
|
| 467 |
+
if( (mu<0)or (n<0) or(k<0)or (k>3*n//2)):
|
| 468 |
+
xd[mu,n,k] = 0
|
| 469 |
+
for mu in range(1,der+1):
|
| 470 |
+
for n in range(0,L):
|
| 471 |
+
ctx.prec = xwpd[n]+10
|
| 472 |
+
for k in range(0,3*n//2+1):
|
| 473 |
+
aux=(2*mu-2)*xd[mu-2,n-2,k-3]+2*(xsigma+n-2)*xd[mu-1,n-2,k-3]
|
| 474 |
+
xd[mu,n,k] = aux - xd[mu-1,n-1,k-1]
|
| 475 |
+
|
| 476 |
+
# Now we compute the working precisions ywpd[k]
|
| 477 |
+
# Se II equation (92)
|
| 478 |
+
ywpd={}
|
| 479 |
+
d1 = max(6,ctx.mag(40*L*L))
|
| 480 |
+
yd2 = 13+ctx.mag((1+abs(ysigma))*yA)-ctx.mag(yeps4)-1
|
| 481 |
+
yconst = ctx.ln(8/(ctx.pi*ctx.pi*a*a*yB1*yB1)) /2
|
| 482 |
+
for n in range(0,L):
|
| 483 |
+
yd3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*yconst)+yd2
|
| 484 |
+
ywpd[n]=max(yd3,d1)
|
| 485 |
+
|
| 486 |
+
# procedure of II Section 3.17
|
| 487 |
+
ctx.prec = ywpd[1]+10
|
| 488 |
+
ypsigma = 1-(2*ysigma)
|
| 489 |
+
yd = {}
|
| 490 |
+
yd[0,0,-2]=0; yd[0,0,-1]=0; yd[0,0,0]=1; yd[0,0,1]=0
|
| 491 |
+
yd[0,-1,-2]=0; yd[0,-1,-1]=0; yd[0,-1,0]=1; yd[0,-1,1]=0
|
| 492 |
+
for n in range(1,L):
|
| 493 |
+
ctx.prec = ywpd[n]+10
|
| 494 |
+
for k in range(0,3*n//2+1):
|
| 495 |
+
m = 3*n-2*k
|
| 496 |
+
if(m!=0):
|
| 497 |
+
m1 = ctx.one/m
|
| 498 |
+
c1= m1/4
|
| 499 |
+
c2=(ypsigma*m1)/2
|
| 500 |
+
c3=-(m+1)
|
| 501 |
+
yd[0,n,k]=c3*yd[0,n-1,k-2]+c1*yd[0,n-1,k]+c2*yd[0,n-1,k-1]
|
| 502 |
+
else:
|
| 503 |
+
yd[0,n,k]=0
|
| 504 |
+
for r in range(0,k):
|
| 505 |
+
add=yd[0,n,r]*(ctx.mpf('1.0')*ctx.fac(2*k-2*r)/ctx.fac(k-r))
|
| 506 |
+
yd[0,n,k] -= ((-1)**(k-r))*add
|
| 507 |
+
yd[0,n,-2]=0; yd[0,n,-1]=0; yd[0,n,3*n//2+1]=0
|
| 508 |
+
|
| 509 |
+
for mu in range(-2,der+1):
|
| 510 |
+
for n in range(-2,L):
|
| 511 |
+
for k in range(-3,max(1,3*n//2+2)):
|
| 512 |
+
if( (mu<0)or (n<0) or(k<0)or (k>3*n//2)):
|
| 513 |
+
yd[mu,n,k] = 0
|
| 514 |
+
for mu in range(1,der+1):
|
| 515 |
+
for n in range(0,L):
|
| 516 |
+
ctx.prec = ywpd[n]+10
|
| 517 |
+
for k in range(0,3*n//2+1):
|
| 518 |
+
aux=(2*mu-2)*yd[mu-2,n-2,k-3]+2*(ysigma+n-2)*yd[mu-1,n-2,k-3]
|
| 519 |
+
yd[mu,n,k] = aux - yd[mu-1,n-1,k-1]
|
| 520 |
+
|
| 521 |
+
# COMPUTING THE COEFFICIENTS xtcoef[k,l]
|
| 522 |
+
# See II Section 3.9
|
| 523 |
+
#
|
| 524 |
+
# computing the needed wp
|
| 525 |
+
xwptcoef={}
|
| 526 |
+
xwpterm={}
|
| 527 |
+
ctx.prec = 15
|
| 528 |
+
c1 = ctx.mag(40*(L+2))
|
| 529 |
+
xc2 = ctx.mag(68*(L+2)*xA)
|
| 530 |
+
xc4 = ctx.mag(xB1*a*math.sqrt(ctx.pi))-1
|
| 531 |
+
for k in range(0,L):
|
| 532 |
+
xc3 = xc2 - k*xc4+ctx.mag(ctx.fac(k+0.5))/2.
|
| 533 |
+
xwptcoef[k] = (max(c1,xc3-ctx.mag(xeps4)+1)+1 +20)*1.5
|
| 534 |
+
xwpterm[k] = (max(c1,ctx.mag(L+2)+xc3-ctx.mag(xeps3)+1)+1 +20)
|
| 535 |
+
ywptcoef={}
|
| 536 |
+
ywpterm={}
|
| 537 |
+
ctx.prec = 15
|
| 538 |
+
c1 = ctx.mag(40*(L+2))
|
| 539 |
+
yc2 = ctx.mag(68*(L+2)*yA)
|
| 540 |
+
yc4 = ctx.mag(yB1*a*math.sqrt(ctx.pi))-1
|
| 541 |
+
for k in range(0,L):
|
| 542 |
+
yc3 = yc2 - k*yc4+ctx.mag(ctx.fac(k+0.5))/2.
|
| 543 |
+
ywptcoef[k] = ((max(c1,yc3-ctx.mag(yeps4)+1))+10)*1.5
|
| 544 |
+
ywpterm[k] = (max(c1,ctx.mag(L+2)+yc3-ctx.mag(yeps3)+1)+1)+10
|
| 545 |
+
|
| 546 |
+
# check of power of pi
|
| 547 |
+
# computing the fortcoef[mu,k,ell]
|
| 548 |
+
xfortcoef={}
|
| 549 |
+
for mu in range(0,der+1):
|
| 550 |
+
for k in range(0,L):
|
| 551 |
+
for ell in range(-2,3*k//2+1):
|
| 552 |
+
xfortcoef[mu,k,ell]=0
|
| 553 |
+
for mu in range(0,der+1):
|
| 554 |
+
for k in range(0,L):
|
| 555 |
+
ctx.prec = xwptcoef[k]
|
| 556 |
+
for ell in range(0,3*k//2+1):
|
| 557 |
+
xfortcoef[mu,k,ell]=xd[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell]
|
| 558 |
+
xfortcoef[mu,k,ell]=xfortcoef[mu,k,ell]/((2*ctx.j)**ell)
|
| 559 |
+
|
| 560 |
+
def trunc_a(t):
|
| 561 |
+
wp = ctx.prec
|
| 562 |
+
ctx.prec = wp + 2
|
| 563 |
+
aa = ctx.sqrt(t/(2*ctx.pi))
|
| 564 |
+
ctx.prec = wp
|
| 565 |
+
return aa
|
| 566 |
+
|
| 567 |
+
# computing the tcoef[k,ell]
|
| 568 |
+
xtcoef={}
|
| 569 |
+
for mu in range(0,der+1):
|
| 570 |
+
for k in range(0,L):
|
| 571 |
+
for ell in range(-2,3*k//2+1):
|
| 572 |
+
xtcoef[mu,k,ell]=0
|
| 573 |
+
ctx.prec = max(xwptcoef[0],ywptcoef[0])+3
|
| 574 |
+
aa= trunc_a(t)
|
| 575 |
+
la = -ctx.ln(aa)
|
| 576 |
+
|
| 577 |
+
for chi in range(0,der+1):
|
| 578 |
+
for k in range(0,L):
|
| 579 |
+
ctx.prec = xwptcoef[k]
|
| 580 |
+
for ell in range(0,3*k//2+1):
|
| 581 |
+
xtcoef[chi,k,ell] =0
|
| 582 |
+
for mu in range(0, chi+1):
|
| 583 |
+
tcoefter=ctx.binomial(chi,mu)*ctx.power(la,mu)*xfortcoef[chi-mu,k,ell]
|
| 584 |
+
xtcoef[chi,k,ell] += tcoefter
|
| 585 |
+
|
| 586 |
+
# COMPUTING THE COEFFICIENTS ytcoef[k,l]
|
| 587 |
+
# See II Section 3.9
|
| 588 |
+
#
|
| 589 |
+
# computing the needed wp
|
| 590 |
+
# check of power of pi
|
| 591 |
+
# computing the fortcoef[mu,k,ell]
|
| 592 |
+
yfortcoef={}
|
| 593 |
+
for mu in range(0,der+1):
|
| 594 |
+
for k in range(0,L):
|
| 595 |
+
for ell in range(-2,3*k//2+1):
|
| 596 |
+
yfortcoef[mu,k,ell]=0
|
| 597 |
+
for mu in range(0,der+1):
|
| 598 |
+
for k in range(0,L):
|
| 599 |
+
ctx.prec = ywptcoef[k]
|
| 600 |
+
for ell in range(0,3*k//2+1):
|
| 601 |
+
yfortcoef[mu,k,ell]=yd[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell]
|
| 602 |
+
yfortcoef[mu,k,ell]=yfortcoef[mu,k,ell]/((2*ctx.j)**ell)
|
| 603 |
+
# computing the tcoef[k,ell]
|
| 604 |
+
ytcoef={}
|
| 605 |
+
for chi in range(0,der+1):
|
| 606 |
+
for k in range(0,L):
|
| 607 |
+
for ell in range(-2,3*k//2+1):
|
| 608 |
+
ytcoef[chi,k,ell]=0
|
| 609 |
+
for chi in range(0,der+1):
|
| 610 |
+
for k in range(0,L):
|
| 611 |
+
ctx.prec = ywptcoef[k]
|
| 612 |
+
for ell in range(0,3*k//2+1):
|
| 613 |
+
ytcoef[chi,k,ell] =0
|
| 614 |
+
for mu in range(0, chi+1):
|
| 615 |
+
tcoefter=ctx.binomial(chi,mu)*ctx.power(la,mu)*yfortcoef[chi-mu,k,ell]
|
| 616 |
+
ytcoef[chi,k,ell] += tcoefter
|
| 617 |
+
|
| 618 |
+
# COMPUTING tv[k,ell]
|
| 619 |
+
# See II Section 3.8
|
| 620 |
+
#
|
| 621 |
+
# a has a good value
|
| 622 |
+
ctx.prec = max(xwptcoef[0], ywptcoef[0])+2
|
| 623 |
+
av = {}
|
| 624 |
+
av[0] = 1
|
| 625 |
+
av[1] = av[0]/a
|
| 626 |
+
|
| 627 |
+
ctx.prec = max(xwptcoef[0],ywptcoef[0])
|
| 628 |
+
for k in range(2,L):
|
| 629 |
+
av[k] = av[k-1] * av[1]
|
| 630 |
+
|
| 631 |
+
# Computing the quotients
|
| 632 |
+
xtv = {}
|
| 633 |
+
for chi in range(0,der+1):
|
| 634 |
+
for k in range(0,L):
|
| 635 |
+
ctx.prec = xwptcoef[k]
|
| 636 |
+
for ell in range(0,3*k//2+1):
|
| 637 |
+
xtv[chi,k,ell] = xtcoef[chi,k,ell]* av[k]
|
| 638 |
+
# Computing the quotients
|
| 639 |
+
ytv = {}
|
| 640 |
+
for chi in range(0,der+1):
|
| 641 |
+
for k in range(0,L):
|
| 642 |
+
ctx.prec = ywptcoef[k]
|
| 643 |
+
for ell in range(0,3*k//2+1):
|
| 644 |
+
ytv[chi,k,ell] = ytcoef[chi,k,ell]* av[k]
|
| 645 |
+
|
| 646 |
+
# COMPUTING THE TERMS xterm[k]
|
| 647 |
+
# See II Section 3.6
|
| 648 |
+
xterm = {}
|
| 649 |
+
for chi in range(0,der+1):
|
| 650 |
+
for n in range(0,L):
|
| 651 |
+
ctx.prec = xwpterm[n]
|
| 652 |
+
te = 0
|
| 653 |
+
for k in range(0, 3*n//2+1):
|
| 654 |
+
te += xtv[chi,n,k]
|
| 655 |
+
xterm[chi,n] = te
|
| 656 |
+
|
| 657 |
+
# COMPUTING THE TERMS yterm[k]
|
| 658 |
+
# See II Section 3.6
|
| 659 |
+
yterm = {}
|
| 660 |
+
for chi in range(0,der+1):
|
| 661 |
+
for n in range(0,L):
|
| 662 |
+
ctx.prec = ywpterm[n]
|
| 663 |
+
te = 0
|
| 664 |
+
for k in range(0, 3*n//2+1):
|
| 665 |
+
te += ytv[chi,n,k]
|
| 666 |
+
yterm[chi,n] = te
|
| 667 |
+
|
| 668 |
+
# COMPUTING rssum
|
| 669 |
+
# See II Section 3.5
|
| 670 |
+
xrssum={}
|
| 671 |
+
ctx.prec=15
|
| 672 |
+
xrsbound = math.sqrt(ctx.pi) * xc /(xb*a)
|
| 673 |
+
ctx.prec=15
|
| 674 |
+
xwprssum = ctx.mag(4.4*((L+3)**2)*xrsbound / xeps2)
|
| 675 |
+
xwprssum = max(xwprssum, ctx.mag(10*(L+1)))
|
| 676 |
+
ctx.prec = xwprssum
|
| 677 |
+
for chi in range(0,der+1):
|
| 678 |
+
xrssum[chi] = 0
|
| 679 |
+
for k in range(1,L+1):
|
| 680 |
+
xrssum[chi] += xterm[chi,L-k]
|
| 681 |
+
yrssum={}
|
| 682 |
+
ctx.prec=15
|
| 683 |
+
yrsbound = math.sqrt(ctx.pi) * yc /(yb*a)
|
| 684 |
+
ctx.prec=15
|
| 685 |
+
ywprssum = ctx.mag(4.4*((L+3)**2)*yrsbound / yeps2)
|
| 686 |
+
ywprssum = max(ywprssum, ctx.mag(10*(L+1)))
|
| 687 |
+
ctx.prec = ywprssum
|
| 688 |
+
for chi in range(0,der+1):
|
| 689 |
+
yrssum[chi] = 0
|
| 690 |
+
for k in range(1,L+1):
|
| 691 |
+
yrssum[chi] += yterm[chi,L-k]
|
| 692 |
+
|
| 693 |
+
# COMPUTING S3
|
| 694 |
+
# See II Section 3.19
|
| 695 |
+
ctx.prec = 15
|
| 696 |
+
A2 = 2**(max(ctx.mag(abs(xrssum[0])), ctx.mag(abs(yrssum[0]))))
|
| 697 |
+
eps8 = eps/(3*A2)
|
| 698 |
+
T = t *ctx.ln(t/(2*ctx.pi))
|
| 699 |
+
xwps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-xsigma))*T)
|
| 700 |
+
ywps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-ysigma))*T)
|
| 701 |
+
|
| 702 |
+
ctx.prec = max(xwps3, ywps3)
|
| 703 |
+
|
| 704 |
+
tpi = t/(2*ctx.pi)
|
| 705 |
+
arg = (t/2)*ctx.ln(tpi)-(t/2)-ctx.pi/8
|
| 706 |
+
U = ctx.expj(-arg)
|
| 707 |
+
a = trunc_a(t)
|
| 708 |
+
xasigma = ctx.power(a, -xsigma)
|
| 709 |
+
yasigma = ctx.power(a, -ysigma)
|
| 710 |
+
xS3 = ((-1)**(N-1)) * xasigma * U
|
| 711 |
+
yS3 = ((-1)**(N-1)) * yasigma * U
|
| 712 |
+
|
| 713 |
+
# COMPUTING S1 the zetasum
|
| 714 |
+
# See II Section 3.18
|
| 715 |
+
ctx.prec = 15
|
| 716 |
+
xwpsum = 4+ ctx.mag((N+ctx.power(N,1-xsigma))*ctx.ln(N) /eps1)
|
| 717 |
+
ywpsum = 4+ ctx.mag((N+ctx.power(N,1-ysigma))*ctx.ln(N) /eps1)
|
| 718 |
+
wpsum = max(xwpsum, ywpsum)
|
| 719 |
+
|
| 720 |
+
ctx.prec = wpsum +10
|
| 721 |
+
'''
|
| 722 |
+
# This can be improved
|
| 723 |
+
xS1={}
|
| 724 |
+
yS1={}
|
| 725 |
+
for chi in range(0,der+1):
|
| 726 |
+
xS1[chi] = 0
|
| 727 |
+
yS1[chi] = 0
|
| 728 |
+
for n in range(1,int(N)+1):
|
| 729 |
+
ln = ctx.ln(n)
|
| 730 |
+
xexpn = ctx.exp(-ln*(xsigma+ctx.j*t))
|
| 731 |
+
yexpn = ctx.conj(1/(n*xexpn))
|
| 732 |
+
for chi in range(0,der+1):
|
| 733 |
+
pown = ctx.power(-ln, chi)
|
| 734 |
+
xterm = pown*xexpn
|
| 735 |
+
yterm = pown*yexpn
|
| 736 |
+
xS1[chi] += xterm
|
| 737 |
+
yS1[chi] += yterm
|
| 738 |
+
'''
|
| 739 |
+
xS1, yS1 = ctx._zetasum(s, 1, int(N)-1, range(0,der+1), True)
|
| 740 |
+
|
| 741 |
+
# END OF COMPUTATION of xrz, yrz
|
| 742 |
+
# See II Section 3.1
|
| 743 |
+
ctx.prec = 15
|
| 744 |
+
xabsS1 = abs(xS1[der])
|
| 745 |
+
xabsS2 = abs(xrssum[der] * xS3)
|
| 746 |
+
xwpend = max(6, wpinitial+ctx.mag(6*(3*xabsS1+7*xabsS2) ) )
|
| 747 |
+
|
| 748 |
+
ctx.prec = xwpend
|
| 749 |
+
xrz={}
|
| 750 |
+
for chi in range(0,der+1):
|
| 751 |
+
xrz[chi] = xS1[chi]+xrssum[chi]*xS3
|
| 752 |
+
|
| 753 |
+
ctx.prec = 15
|
| 754 |
+
yabsS1 = abs(yS1[der])
|
| 755 |
+
yabsS2 = abs(yrssum[der] * yS3)
|
| 756 |
+
ywpend = max(6, wpinitial+ctx.mag(6*(3*yabsS1+7*yabsS2) ) )
|
| 757 |
+
|
| 758 |
+
ctx.prec = ywpend
|
| 759 |
+
yrz={}
|
| 760 |
+
for chi in range(0,der+1):
|
| 761 |
+
yrz[chi] = yS1[chi]+yrssum[chi]*yS3
|
| 762 |
+
yrz[chi] = ctx.conj(yrz[chi])
|
| 763 |
+
ctx.prec = wpinitial
|
| 764 |
+
return xrz, yrz
|
| 765 |
+
|
| 766 |
+
def Rzeta_set(ctx, s, derivatives=[0]):
|
| 767 |
+
r"""
|
| 768 |
+
Computes several derivatives of the auxiliary function of Riemann `R(s)`.
|
| 769 |
+
|
| 770 |
+
**Definition**
|
| 771 |
+
|
| 772 |
+
The function is defined by
|
| 773 |
+
|
| 774 |
+
.. math ::
|
| 775 |
+
|
| 776 |
+
\begin{equation}
|
| 777 |
+
{\mathop{\mathcal R }\nolimits}(s)=
|
| 778 |
+
\int_{0\swarrow1}\frac{x^{-s} e^{\pi i x^2}}{e^{\pi i x}-
|
| 779 |
+
e^{-\pi i x}}\,dx
|
| 780 |
+
\end{equation}
|
| 781 |
+
|
| 782 |
+
To this function we apply the Riemann-Siegel expansion.
|
| 783 |
+
"""
|
| 784 |
+
der = max(derivatives)
|
| 785 |
+
# First we take the value of ctx.prec
|
| 786 |
+
# During the computation we will change ctx.prec, and finally we will
|
| 787 |
+
# restaurate the initial value
|
| 788 |
+
wpinitial = ctx.prec
|
| 789 |
+
# Take the real and imaginary part of s
|
| 790 |
+
t = ctx._im(s)
|
| 791 |
+
sigma = ctx._re(s)
|
| 792 |
+
# Now compute several parameter that appear on the program
|
| 793 |
+
ctx.prec = 15
|
| 794 |
+
a = ctx.sqrt(t/(2*ctx.pi)) # Careful
|
| 795 |
+
asigma = ctx.power(a, sigma) # Careful
|
| 796 |
+
# We need a simple bound A1 < asigma (see II Section 3.1 and 3.3)
|
| 797 |
+
A1 = ctx.power(2, ctx.mag(asigma)-1)
|
| 798 |
+
# We compute various epsilon's (see II end of Section 3.1)
|
| 799 |
+
eps = ctx.power(2, -wpinitial)
|
| 800 |
+
eps1 = eps/6.
|
| 801 |
+
eps2 = eps * A1/3.
|
| 802 |
+
# COMPUTING SOME COEFFICIENTS THAT DEPENDS
|
| 803 |
+
# ON sigma
|
| 804 |
+
# constant b and c (see I Theorem 2 formula (26) )
|
| 805 |
+
# coefficients A and B1 (see I Section 6.1 equation (50))
|
| 806 |
+
# here we not need high precision
|
| 807 |
+
ctx.prec = 15
|
| 808 |
+
if sigma > 0:
|
| 809 |
+
b = 2.
|
| 810 |
+
c = math.pow(9,sigma)/4.44288
|
| 811 |
+
# 4.44288 =(math.sqrt(2)*math.pi)
|
| 812 |
+
A = math.pow(9,sigma)
|
| 813 |
+
B1 = 1
|
| 814 |
+
else:
|
| 815 |
+
b = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi )
|
| 816 |
+
c = math.pow(2,-sigma)/4.44288
|
| 817 |
+
A = math.pow(2,-sigma)
|
| 818 |
+
B1 = 1.10789 # = 2*sqrt(1-log(2))
|
| 819 |
+
# COMPUTING L THE NUMBER OF TERMS NEEDED IN THE RIEMANN-SIEGEL
|
| 820 |
+
# CORRECTION
|
| 821 |
+
# See II Section 3.2
|
| 822 |
+
ctx.prec = 15
|
| 823 |
+
L = 1
|
| 824 |
+
while 3*c*ctx.gamma(L*0.5) * ctx.power(b*a,-L) >= eps2:
|
| 825 |
+
L = L+1
|
| 826 |
+
L = max(2,L)
|
| 827 |
+
# The number L has to satify some conditions.
|
| 828 |
+
# If not RS can not compute Rzeta(s) with the prescribed precision
|
| 829 |
+
# (see II, Section 3.2 condition (20) ) and
|
| 830 |
+
# (II, Section 3.3 condition (22) ). Also we have added
|
| 831 |
+
# an additional technical condition in Section 3.17 Proposition 17
|
| 832 |
+
if ((3*L >= 2*a*a/25.) or (3*L+2+sigma<0) or (abs(sigma)> a/2.)):
|
| 833 |
+
#print 'Error Riemann-Siegel can not compute with such precision'
|
| 834 |
+
ctx.prec = wpinitial
|
| 835 |
+
raise NotImplementedError("Riemann-Siegel can not compute with such precision")
|
| 836 |
+
|
| 837 |
+
# INITIALIZATION (CONTINUATION)
|
| 838 |
+
#
|
| 839 |
+
# eps3 is the constant defined on (II, Section 3.5 equation (27) )
|
| 840 |
+
# each term of the RS correction must be computed with error <= eps3
|
| 841 |
+
eps3 = eps2/(4*L)
|
| 842 |
+
|
| 843 |
+
# eps4 is defined on (II Section 3.6 equation (30) )
|
| 844 |
+
# each component of the formula (II Section 3.6 equation (29) )
|
| 845 |
+
# must be computed with error <= eps4
|
| 846 |
+
eps4 = eps3/(3*L)
|
| 847 |
+
|
| 848 |
+
# COMPUTING M. NUMBER OF DERIVATIVES Fp[m] TO COMPUTE
|
| 849 |
+
M = aux_M_Fp(ctx, A, eps4, a, B1, L)
|
| 850 |
+
Fp = {}
|
| 851 |
+
for n in range(M, 3*L-2):
|
| 852 |
+
Fp[n] = 0
|
| 853 |
+
|
| 854 |
+
# But I have not seen an instance of M != 3*L-3
|
| 855 |
+
#
|
| 856 |
+
# DETERMINATION OF J THE NUMBER OF TERMS NEEDED
|
| 857 |
+
# IN THE TAYLOR SERIES OF F.
|
| 858 |
+
# See II Section 3.11 equation (49))
|
| 859 |
+
h1 = eps4/(632*A)
|
| 860 |
+
h2 = ctx.pi*ctx.pi*B1*a *ctx.sqrt(3)*math.e*math.e
|
| 861 |
+
h2 = h1 * ctx.power((h2/M**2),(M-1)/3) / M
|
| 862 |
+
h3 = min(h1,h2)
|
| 863 |
+
J=12
|
| 864 |
+
jvalue = (2*ctx.pi)**J / ctx.gamma(J+1)
|
| 865 |
+
while jvalue > h3:
|
| 866 |
+
J = J+1
|
| 867 |
+
jvalue = (2*ctx.pi)*jvalue/J
|
| 868 |
+
|
| 869 |
+
# COMPUTING eps5[m] for 1 <= m <= 21
|
| 870 |
+
# See II Section 10 equation (43)
|
| 871 |
+
eps5={}
|
| 872 |
+
foreps5 = math.pi*math.pi*B1*a
|
| 873 |
+
for m in range(0,22):
|
| 874 |
+
aux1 = math.pow(foreps5, m/3)/(316.*A)
|
| 875 |
+
aux2 = ctx.gamma(m+1)/ctx.gamma(m/3.0+0.5)
|
| 876 |
+
aux2 = math.sqrt(aux2)
|
| 877 |
+
eps5[m] = aux1*aux2*eps4
|
| 878 |
+
|
| 879 |
+
# COMPUTING wpfp
|
| 880 |
+
# See II Section 3.13 equation (59)
|
| 881 |
+
twenty = min(3*L-3, 21)+1
|
| 882 |
+
aux = 6812*J
|
| 883 |
+
wpfp = ctx.mag(44*J)
|
| 884 |
+
for m in range(0, twenty):
|
| 885 |
+
wpfp = max(wpfp, ctx.mag(aux*ctx.gamma(m+1)/eps5[m]))
|
| 886 |
+
# COMPUTING N AND p
|
| 887 |
+
# See II Section
|
| 888 |
+
ctx.prec = wpfp + ctx.mag(t) + 20
|
| 889 |
+
a = ctx.sqrt(t/(2*ctx.pi))
|
| 890 |
+
N = ctx.floor(a)
|
| 891 |
+
p = 1-2*(a-N)
|
| 892 |
+
|
| 893 |
+
# now we get a rounded version of p to the precision wpfp
|
| 894 |
+
# this possibly is not necessary
|
| 895 |
+
num = ctx.floor(p*(ctx.mpf(2)**wpfp))
|
| 896 |
+
difference = p * (ctx.mpf(2)**wpfp)-num
|
| 897 |
+
if difference < 0.5:
|
| 898 |
+
num = num
|
| 899 |
+
else:
|
| 900 |
+
num = num+1
|
| 901 |
+
p = ctx.convert(num * (ctx.mpf(2)**(-wpfp)))
|
| 902 |
+
|
| 903 |
+
# COMPUTING THE COEFFICIENTS c[n] = cc[n]
|
| 904 |
+
# We shall use the notation cc[n], since there is
|
| 905 |
+
# a constant that is called c
|
| 906 |
+
# See II Section 3.14
|
| 907 |
+
# We compute the coefficients and also save then in a
|
| 908 |
+
# cache. The bulk of the computation is passed to
|
| 909 |
+
# the function coef()
|
| 910 |
+
#
|
| 911 |
+
# eps6 is defined in II Section 3.13 equation (58)
|
| 912 |
+
eps6 = ctx.power(2*ctx.pi, J)/(ctx.gamma(J+1)*3*J)
|
| 913 |
+
|
| 914 |
+
# Now we compute the coefficients
|
| 915 |
+
cc={}
|
| 916 |
+
cont={}
|
| 917 |
+
cont, pipowers = coef(ctx, J, eps6)
|
| 918 |
+
cc = cont.copy() # we need a copy since we have
|
| 919 |
+
Fp={}
|
| 920 |
+
for n in range(M, 3*L-2):
|
| 921 |
+
Fp[n] = 0
|
| 922 |
+
ctx.prec = wpfp
|
| 923 |
+
for m in range(0,M+1):
|
| 924 |
+
sumP = 0
|
| 925 |
+
for k in range(2*J-m-1,-1,-1):
|
| 926 |
+
sumP = (sumP * p) + cc[k]
|
| 927 |
+
Fp[m] = sumP
|
| 928 |
+
# preparation of the new coefficients
|
| 929 |
+
for k in range(0, 2*J-m-1):
|
| 930 |
+
cc[k] = (k+1) * cc[k+1]
|
| 931 |
+
|
| 932 |
+
# COMPUTING THE NUMBERS d[n,k]
|
| 933 |
+
# See II Section 3.17
|
| 934 |
+
|
| 935 |
+
# First we compute the working precisions wpd[k]
|
| 936 |
+
# Se II equation (92)
|
| 937 |
+
wpd = {}
|
| 938 |
+
d1 = max(6, ctx.mag(40*L*L))
|
| 939 |
+
d2 = 13+ctx.mag((1+abs(sigma))*A)-ctx.mag(eps4)-1
|
| 940 |
+
const = ctx.ln(8/(ctx.pi*ctx.pi*a*a*B1*B1)) /2
|
| 941 |
+
for n in range(0,L):
|
| 942 |
+
d3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*const)+d2
|
| 943 |
+
wpd[n] = max(d3,d1)
|
| 944 |
+
|
| 945 |
+
# procedure of II Section 3.17
|
| 946 |
+
ctx.prec = wpd[1]+10
|
| 947 |
+
psigma = 1-(2*sigma)
|
| 948 |
+
d = {}
|
| 949 |
+
d[0,0,-2]=0; d[0,0,-1]=0; d[0,0,0]=1; d[0,0,1]=0
|
| 950 |
+
d[0,-1,-2]=0; d[0,-1,-1]=0; d[0,-1,0]=1; d[0,-1,1]=0
|
| 951 |
+
for n in range(1,L):
|
| 952 |
+
ctx.prec = wpd[n]+10
|
| 953 |
+
for k in range(0,3*n//2+1):
|
| 954 |
+
m = 3*n-2*k
|
| 955 |
+
if (m!=0):
|
| 956 |
+
m1 = ctx.one/m
|
| 957 |
+
c1 = m1/4
|
| 958 |
+
c2 = (psigma*m1)/2
|
| 959 |
+
c3 = -(m+1)
|
| 960 |
+
d[0,n,k] = c3*d[0,n-1,k-2]+c1*d[0,n-1,k]+c2*d[0,n-1,k-1]
|
| 961 |
+
else:
|
| 962 |
+
d[0,n,k]=0
|
| 963 |
+
for r in range(0,k):
|
| 964 |
+
add = d[0,n,r]*(ctx.one*ctx.fac(2*k-2*r)/ctx.fac(k-r))
|
| 965 |
+
d[0,n,k] -= ((-1)**(k-r))*add
|
| 966 |
+
d[0,n,-2]=0; d[0,n,-1]=0; d[0,n,3*n//2+1]=0
|
| 967 |
+
|
| 968 |
+
for mu in range(-2,der+1):
|
| 969 |
+
for n in range(-2,L):
|
| 970 |
+
for k in range(-3,max(1,3*n//2+2)):
|
| 971 |
+
if ((mu<0)or (n<0) or(k<0)or (k>3*n//2)):
|
| 972 |
+
d[mu,n,k] = 0
|
| 973 |
+
|
| 974 |
+
for mu in range(1,der+1):
|
| 975 |
+
for n in range(0,L):
|
| 976 |
+
ctx.prec = wpd[n]+10
|
| 977 |
+
for k in range(0,3*n//2+1):
|
| 978 |
+
aux=(2*mu-2)*d[mu-2,n-2,k-3]+2*(sigma+n-2)*d[mu-1,n-2,k-3]
|
| 979 |
+
d[mu,n,k] = aux - d[mu-1,n-1,k-1]
|
| 980 |
+
|
| 981 |
+
# COMPUTING THE COEFFICIENTS t[k,l]
|
| 982 |
+
# See II Section 3.9
|
| 983 |
+
#
|
| 984 |
+
# computing the needed wp
|
| 985 |
+
wptcoef = {}
|
| 986 |
+
wpterm = {}
|
| 987 |
+
ctx.prec = 15
|
| 988 |
+
c1 = ctx.mag(40*(L+2))
|
| 989 |
+
c2 = ctx.mag(68*(L+2)*A)
|
| 990 |
+
c4 = ctx.mag(B1*a*math.sqrt(ctx.pi))-1
|
| 991 |
+
for k in range(0,L):
|
| 992 |
+
c3 = c2 - k*c4+ctx.mag(ctx.fac(k+0.5))/2.
|
| 993 |
+
wptcoef[k] = max(c1,c3-ctx.mag(eps4)+1)+1 +10
|
| 994 |
+
wpterm[k] = max(c1,ctx.mag(L+2)+c3-ctx.mag(eps3)+1)+1 +10
|
| 995 |
+
|
| 996 |
+
# check of power of pi
|
| 997 |
+
|
| 998 |
+
# computing the fortcoef[mu,k,ell]
|
| 999 |
+
fortcoef={}
|
| 1000 |
+
for mu in derivatives:
|
| 1001 |
+
for k in range(0,L):
|
| 1002 |
+
for ell in range(-2,3*k//2+1):
|
| 1003 |
+
fortcoef[mu,k,ell]=0
|
| 1004 |
+
|
| 1005 |
+
for mu in derivatives:
|
| 1006 |
+
for k in range(0,L):
|
| 1007 |
+
ctx.prec = wptcoef[k]
|
| 1008 |
+
for ell in range(0,3*k//2+1):
|
| 1009 |
+
fortcoef[mu,k,ell]=d[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell]
|
| 1010 |
+
fortcoef[mu,k,ell]=fortcoef[mu,k,ell]/((2*ctx.j)**ell)
|
| 1011 |
+
|
| 1012 |
+
def trunc_a(t):
|
| 1013 |
+
wp = ctx.prec
|
| 1014 |
+
ctx.prec = wp + 2
|
| 1015 |
+
aa = ctx.sqrt(t/(2*ctx.pi))
|
| 1016 |
+
ctx.prec = wp
|
| 1017 |
+
return aa
|
| 1018 |
+
|
| 1019 |
+
# computing the tcoef[chi,k,ell]
|
| 1020 |
+
tcoef={}
|
| 1021 |
+
for chi in derivatives:
|
| 1022 |
+
for k in range(0,L):
|
| 1023 |
+
for ell in range(-2,3*k//2+1):
|
| 1024 |
+
tcoef[chi,k,ell]=0
|
| 1025 |
+
ctx.prec = wptcoef[0]+3
|
| 1026 |
+
aa = trunc_a(t)
|
| 1027 |
+
la = -ctx.ln(aa)
|
| 1028 |
+
|
| 1029 |
+
for chi in derivatives:
|
| 1030 |
+
for k in range(0,L):
|
| 1031 |
+
ctx.prec = wptcoef[k]
|
| 1032 |
+
for ell in range(0,3*k//2+1):
|
| 1033 |
+
tcoef[chi,k,ell] = 0
|
| 1034 |
+
for mu in range(0, chi+1):
|
| 1035 |
+
tcoefter = ctx.binomial(chi,mu) * la**mu * \
|
| 1036 |
+
fortcoef[chi-mu,k,ell]
|
| 1037 |
+
tcoef[chi,k,ell] += tcoefter
|
| 1038 |
+
|
| 1039 |
+
# COMPUTING tv[k,ell]
|
| 1040 |
+
# See II Section 3.8
|
| 1041 |
+
|
| 1042 |
+
# Computing the powers av[k] = a**(-k)
|
| 1043 |
+
ctx.prec = wptcoef[0] + 2
|
| 1044 |
+
|
| 1045 |
+
# a has a good value of a.
|
| 1046 |
+
# See II Section 3.6
|
| 1047 |
+
av = {}
|
| 1048 |
+
av[0] = 1
|
| 1049 |
+
av[1] = av[0]/a
|
| 1050 |
+
|
| 1051 |
+
ctx.prec = wptcoef[0]
|
| 1052 |
+
for k in range(2,L):
|
| 1053 |
+
av[k] = av[k-1] * av[1]
|
| 1054 |
+
|
| 1055 |
+
# Computing the quotients
|
| 1056 |
+
tv = {}
|
| 1057 |
+
for chi in derivatives:
|
| 1058 |
+
for k in range(0,L):
|
| 1059 |
+
ctx.prec = wptcoef[k]
|
| 1060 |
+
for ell in range(0,3*k//2+1):
|
| 1061 |
+
tv[chi,k,ell] = tcoef[chi,k,ell]* av[k]
|
| 1062 |
+
|
| 1063 |
+
# COMPUTING THE TERMS term[k]
|
| 1064 |
+
# See II Section 3.6
|
| 1065 |
+
term = {}
|
| 1066 |
+
for chi in derivatives:
|
| 1067 |
+
for n in range(0,L):
|
| 1068 |
+
ctx.prec = wpterm[n]
|
| 1069 |
+
te = 0
|
| 1070 |
+
for k in range(0, 3*n//2+1):
|
| 1071 |
+
te += tv[chi,n,k]
|
| 1072 |
+
term[chi,n] = te
|
| 1073 |
+
|
| 1074 |
+
# COMPUTING rssum
|
| 1075 |
+
# See II Section 3.5
|
| 1076 |
+
rssum={}
|
| 1077 |
+
ctx.prec=15
|
| 1078 |
+
rsbound = math.sqrt(ctx.pi) * c /(b*a)
|
| 1079 |
+
ctx.prec=15
|
| 1080 |
+
wprssum = ctx.mag(4.4*((L+3)**2)*rsbound / eps2)
|
| 1081 |
+
wprssum = max(wprssum, ctx.mag(10*(L+1)))
|
| 1082 |
+
ctx.prec = wprssum
|
| 1083 |
+
for chi in derivatives:
|
| 1084 |
+
rssum[chi] = 0
|
| 1085 |
+
for k in range(1,L+1):
|
| 1086 |
+
rssum[chi] += term[chi,L-k]
|
| 1087 |
+
|
| 1088 |
+
# COMPUTING S3
|
| 1089 |
+
# See II Section 3.19
|
| 1090 |
+
ctx.prec = 15
|
| 1091 |
+
A2 = 2**(ctx.mag(rssum[0]))
|
| 1092 |
+
eps8 = eps/(3* A2)
|
| 1093 |
+
T = t * ctx.ln(t/(2*ctx.pi))
|
| 1094 |
+
wps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-sigma))*T)
|
| 1095 |
+
|
| 1096 |
+
ctx.prec = wps3
|
| 1097 |
+
tpi = t/(2*ctx.pi)
|
| 1098 |
+
arg = (t/2)*ctx.ln(tpi)-(t/2)-ctx.pi/8
|
| 1099 |
+
U = ctx.expj(-arg)
|
| 1100 |
+
a = trunc_a(t)
|
| 1101 |
+
asigma = ctx.power(a, -sigma)
|
| 1102 |
+
S3 = ((-1)**(N-1)) * asigma * U
|
| 1103 |
+
|
| 1104 |
+
# COMPUTING S1 the zetasum
|
| 1105 |
+
# See II Section 3.18
|
| 1106 |
+
ctx.prec = 15
|
| 1107 |
+
wpsum = 4 + ctx.mag((N+ctx.power(N,1-sigma))*ctx.ln(N)/eps1)
|
| 1108 |
+
|
| 1109 |
+
ctx.prec = wpsum + 10
|
| 1110 |
+
'''
|
| 1111 |
+
# This can be improved
|
| 1112 |
+
S1 = {}
|
| 1113 |
+
for chi in derivatives:
|
| 1114 |
+
S1[chi] = 0
|
| 1115 |
+
for n in range(1,int(N)+1):
|
| 1116 |
+
ln = ctx.ln(n)
|
| 1117 |
+
expn = ctx.exp(-ln*(sigma+ctx.j*t))
|
| 1118 |
+
for chi in derivatives:
|
| 1119 |
+
term = ctx.power(-ln, chi)*expn
|
| 1120 |
+
S1[chi] += term
|
| 1121 |
+
'''
|
| 1122 |
+
S1 = ctx._zetasum(s, 1, int(N)-1, derivatives)[0]
|
| 1123 |
+
|
| 1124 |
+
# END OF COMPUTATION
|
| 1125 |
+
# See II Section 3.1
|
| 1126 |
+
ctx.prec = 15
|
| 1127 |
+
absS1 = abs(S1[der])
|
| 1128 |
+
absS2 = abs(rssum[der] * S3)
|
| 1129 |
+
wpend = max(6, wpinitial + ctx.mag(6*(3*absS1+7*absS2)))
|
| 1130 |
+
ctx.prec = wpend
|
| 1131 |
+
rz = {}
|
| 1132 |
+
for chi in derivatives:
|
| 1133 |
+
rz[chi] = S1[chi]+rssum[chi]*S3
|
| 1134 |
+
ctx.prec = wpinitial
|
| 1135 |
+
return rz
|
| 1136 |
+
|
| 1137 |
+
|
| 1138 |
+
def z_half(ctx,t,der=0):
|
| 1139 |
+
r"""
|
| 1140 |
+
z_half(t,der=0) Computes Z^(der)(t)
|
| 1141 |
+
"""
|
| 1142 |
+
s=ctx.mpf('0.5')+ctx.j*t
|
| 1143 |
+
wpinitial = ctx.prec
|
| 1144 |
+
ctx.prec = 15
|
| 1145 |
+
tt = t/(2*ctx.pi)
|
| 1146 |
+
wptheta = wpinitial +1 + ctx.mag(3*(tt**1.5)*ctx.ln(tt))
|
| 1147 |
+
wpz = wpinitial + 1 + ctx.mag(12*tt*ctx.ln(tt))
|
| 1148 |
+
ctx.prec = wptheta
|
| 1149 |
+
theta = ctx.siegeltheta(t)
|
| 1150 |
+
ctx.prec = wpz
|
| 1151 |
+
rz = Rzeta_set(ctx,s, range(der+1))
|
| 1152 |
+
if der > 0: ps1 = ctx._re(ctx.psi(0,s/2)/2 - ctx.ln(ctx.pi)/2)
|
| 1153 |
+
if der > 1: ps2 = ctx._re(ctx.j*ctx.psi(1,s/2)/4)
|
| 1154 |
+
if der > 2: ps3 = ctx._re(-ctx.psi(2,s/2)/8)
|
| 1155 |
+
if der > 3: ps4 = ctx._re(-ctx.j*ctx.psi(3,s/2)/16)
|
| 1156 |
+
exptheta = ctx.expj(theta)
|
| 1157 |
+
if der == 0:
|
| 1158 |
+
z = 2*exptheta*rz[0]
|
| 1159 |
+
if der == 1:
|
| 1160 |
+
zf = 2j*exptheta
|
| 1161 |
+
z = zf*(ps1*rz[0]+rz[1])
|
| 1162 |
+
if der == 2:
|
| 1163 |
+
zf = 2 * exptheta
|
| 1164 |
+
z = -zf*(2*rz[1]*ps1+rz[0]*ps1**2+rz[2]-ctx.j*rz[0]*ps2)
|
| 1165 |
+
if der == 3:
|
| 1166 |
+
zf = -2j*exptheta
|
| 1167 |
+
z = 3*rz[1]*ps1**2+rz[0]*ps1**3+3*ps1*rz[2]
|
| 1168 |
+
z = zf*(z-3j*rz[1]*ps2-3j*rz[0]*ps1*ps2+rz[3]-rz[0]*ps3)
|
| 1169 |
+
if der == 4:
|
| 1170 |
+
zf = 2*exptheta
|
| 1171 |
+
z = 4*rz[1]*ps1**3+rz[0]*ps1**4+6*ps1**2*rz[2]
|
| 1172 |
+
z = z-12j*rz[1]*ps1*ps2-6j*rz[0]*ps1**2*ps2-6j*rz[2]*ps2-3*rz[0]*ps2*ps2
|
| 1173 |
+
z = z + 4*ps1*rz[3]-4*rz[1]*ps3-4*rz[0]*ps1*ps3+rz[4]+ctx.j*rz[0]*ps4
|
| 1174 |
+
z = zf*z
|
| 1175 |
+
ctx.prec = wpinitial
|
| 1176 |
+
return ctx._re(z)
|
| 1177 |
+
|
| 1178 |
+
def zeta_half(ctx, s, k=0):
|
| 1179 |
+
"""
|
| 1180 |
+
zeta_half(s,k=0) Computes zeta^(k)(s) when Re s = 0.5
|
| 1181 |
+
"""
|
| 1182 |
+
wpinitial = ctx.prec
|
| 1183 |
+
sigma = ctx._re(s)
|
| 1184 |
+
t = ctx._im(s)
|
| 1185 |
+
#--- compute wptheta, wpR, wpbasic ---
|
| 1186 |
+
ctx.prec = 53
|
| 1187 |
+
# X see II Section 3.21 (109) and (110)
|
| 1188 |
+
if sigma > 0:
|
| 1189 |
+
X = ctx.sqrt(abs(s))
|
| 1190 |
+
else:
|
| 1191 |
+
X = (2*ctx.pi)**(sigma-1) * abs(1-s)**(0.5-sigma)
|
| 1192 |
+
# M1 see II Section 3.21 (111) and (112)
|
| 1193 |
+
if sigma > 0:
|
| 1194 |
+
M1 = 2*ctx.sqrt(t/(2*ctx.pi))
|
| 1195 |
+
else:
|
| 1196 |
+
M1 = 4 * t * X
|
| 1197 |
+
# T see II Section 3.21 (113)
|
| 1198 |
+
abst = abs(0.5-s)
|
| 1199 |
+
T = 2* abst*math.log(abst)
|
| 1200 |
+
# computing wpbasic, wptheta, wpR see II Section 3.21
|
| 1201 |
+
wpbasic = max(6,3+ctx.mag(t))
|
| 1202 |
+
wpbasic2 = 2+ctx.mag(2.12*M1+21.2*M1*X+1.3*M1*X*T)+wpinitial+1
|
| 1203 |
+
wpbasic = max(wpbasic, wpbasic2)
|
| 1204 |
+
wptheta = max(4, 3+ctx.mag(2.7*M1*X)+wpinitial+1)
|
| 1205 |
+
wpR = 3+ctx.mag(1.1+2*X)+wpinitial+1
|
| 1206 |
+
ctx.prec = wptheta
|
| 1207 |
+
theta = ctx.siegeltheta(t-ctx.j*(sigma-ctx.mpf('0.5')))
|
| 1208 |
+
if k > 0: ps1 = (ctx._re(ctx.psi(0,s/2)))/2 - ctx.ln(ctx.pi)/2
|
| 1209 |
+
if k > 1: ps2 = -(ctx._im(ctx.psi(1,s/2)))/4
|
| 1210 |
+
if k > 2: ps3 = -(ctx._re(ctx.psi(2,s/2)))/8
|
| 1211 |
+
if k > 3: ps4 = (ctx._im(ctx.psi(3,s/2)))/16
|
| 1212 |
+
ctx.prec = wpR
|
| 1213 |
+
xrz = Rzeta_set(ctx,s,range(k+1))
|
| 1214 |
+
yrz={}
|
| 1215 |
+
for chi in range(0,k+1):
|
| 1216 |
+
yrz[chi] = ctx.conj(xrz[chi])
|
| 1217 |
+
ctx.prec = wpbasic
|
| 1218 |
+
exptheta = ctx.expj(-2*theta)
|
| 1219 |
+
if k==0:
|
| 1220 |
+
zv = xrz[0]+exptheta*yrz[0]
|
| 1221 |
+
if k==1:
|
| 1222 |
+
zv1 = -yrz[1] - 2*yrz[0]*ps1
|
| 1223 |
+
zv = xrz[1] + exptheta*zv1
|
| 1224 |
+
if k==2:
|
| 1225 |
+
zv1 = 4*yrz[1]*ps1+4*yrz[0]*(ps1**2)+yrz[2]+2j*yrz[0]*ps2
|
| 1226 |
+
zv = xrz[2]+exptheta*zv1
|
| 1227 |
+
if k==3:
|
| 1228 |
+
zv1 = -12*yrz[1]*ps1**2-8*yrz[0]*ps1**3-6*yrz[2]*ps1-6j*yrz[1]*ps2
|
| 1229 |
+
zv1 = zv1 - 12j*yrz[0]*ps1*ps2-yrz[3]+2*yrz[0]*ps3
|
| 1230 |
+
zv = xrz[3]+exptheta*zv1
|
| 1231 |
+
if k == 4:
|
| 1232 |
+
zv1 = 32*yrz[1]*ps1**3 +16*yrz[0]*ps1**4+24*yrz[2]*ps1**2
|
| 1233 |
+
zv1 = zv1 +48j*yrz[1]*ps1*ps2+48j*yrz[0]*(ps1**2)*ps2
|
| 1234 |
+
zv1 = zv1+12j*yrz[2]*ps2-12*yrz[0]*ps2**2+8*yrz[3]*ps1-8*yrz[1]*ps3
|
| 1235 |
+
zv1 = zv1-16*yrz[0]*ps1*ps3+yrz[4]-2j*yrz[0]*ps4
|
| 1236 |
+
zv = xrz[4]+exptheta*zv1
|
| 1237 |
+
ctx.prec = wpinitial
|
| 1238 |
+
return zv
|
| 1239 |
+
|
| 1240 |
+
def zeta_offline(ctx, s, k=0):
|
| 1241 |
+
"""
|
| 1242 |
+
Computes zeta^(k)(s) off the line
|
| 1243 |
+
"""
|
| 1244 |
+
wpinitial = ctx.prec
|
| 1245 |
+
sigma = ctx._re(s)
|
| 1246 |
+
t = ctx._im(s)
|
| 1247 |
+
#--- compute wptheta, wpR, wpbasic ---
|
| 1248 |
+
ctx.prec = 53
|
| 1249 |
+
# X see II Section 3.21 (109) and (110)
|
| 1250 |
+
if sigma > 0:
|
| 1251 |
+
X = ctx.power(abs(s), 0.5)
|
| 1252 |
+
else:
|
| 1253 |
+
X = ctx.power(2*ctx.pi, sigma-1)*ctx.power(abs(1-s),0.5-sigma)
|
| 1254 |
+
# M1 see II Section 3.21 (111) and (112)
|
| 1255 |
+
if (sigma > 0):
|
| 1256 |
+
M1 = 2*ctx.sqrt(t/(2*ctx.pi))
|
| 1257 |
+
else:
|
| 1258 |
+
M1 = 4 * t * X
|
| 1259 |
+
# M2 see II Section 3.21 (111) and (112)
|
| 1260 |
+
if (1-sigma > 0):
|
| 1261 |
+
M2 = 2*ctx.sqrt(t/(2*ctx.pi))
|
| 1262 |
+
else:
|
| 1263 |
+
M2 = 4*t*ctx.power(2*ctx.pi, -sigma)*ctx.power(abs(s),sigma-0.5)
|
| 1264 |
+
# T see II Section 3.21 (113)
|
| 1265 |
+
abst = abs(0.5-s)
|
| 1266 |
+
T = 2* abst*math.log(abst)
|
| 1267 |
+
# computing wpbasic, wptheta, wpR see II Section 3.21
|
| 1268 |
+
wpbasic = max(6,3+ctx.mag(t))
|
| 1269 |
+
wpbasic2 = 2+ctx.mag(2.12*M1+21.2*M2*X+1.3*M2*X*T)+wpinitial+1
|
| 1270 |
+
wpbasic = max(wpbasic, wpbasic2)
|
| 1271 |
+
wptheta = max(4, 3+ctx.mag(2.7*M2*X)+wpinitial+1)
|
| 1272 |
+
wpR = 3+ctx.mag(1.1+2*X)+wpinitial+1
|
| 1273 |
+
ctx.prec = wptheta
|
| 1274 |
+
theta = ctx.siegeltheta(t-ctx.j*(sigma-ctx.mpf('0.5')))
|
| 1275 |
+
s1 = s
|
| 1276 |
+
s2 = ctx.conj(1-s1)
|
| 1277 |
+
ctx.prec = wpR
|
| 1278 |
+
xrz, yrz = Rzeta_simul(ctx, s, k)
|
| 1279 |
+
if k > 0: ps1 = (ctx.psi(0,s1/2)+ctx.psi(0,(1-s1)/2))/4 - ctx.ln(ctx.pi)/2
|
| 1280 |
+
if k > 1: ps2 = ctx.j*(ctx.psi(1,s1/2)-ctx.psi(1,(1-s1)/2))/8
|
| 1281 |
+
if k > 2: ps3 = -(ctx.psi(2,s1/2)+ctx.psi(2,(1-s1)/2))/16
|
| 1282 |
+
if k > 3: ps4 = -ctx.j*(ctx.psi(3,s1/2)-ctx.psi(3,(1-s1)/2))/32
|
| 1283 |
+
ctx.prec = wpbasic
|
| 1284 |
+
exptheta = ctx.expj(-2*theta)
|
| 1285 |
+
if k == 0:
|
| 1286 |
+
zv = xrz[0]+exptheta*yrz[0]
|
| 1287 |
+
if k == 1:
|
| 1288 |
+
zv1 = -yrz[1]-2*yrz[0]*ps1
|
| 1289 |
+
zv = xrz[1]+exptheta*zv1
|
| 1290 |
+
if k == 2:
|
| 1291 |
+
zv1 = 4*yrz[1]*ps1+4*yrz[0]*(ps1**2) +yrz[2]+2j*yrz[0]*ps2
|
| 1292 |
+
zv = xrz[2]+exptheta*zv1
|
| 1293 |
+
if k == 3:
|
| 1294 |
+
zv1 = -12*yrz[1]*ps1**2 -8*yrz[0]*ps1**3-6*yrz[2]*ps1-6j*yrz[1]*ps2
|
| 1295 |
+
zv1 = zv1 - 12j*yrz[0]*ps1*ps2-yrz[3]+2*yrz[0]*ps3
|
| 1296 |
+
zv = xrz[3]+exptheta*zv1
|
| 1297 |
+
if k == 4:
|
| 1298 |
+
zv1 = 32*yrz[1]*ps1**3 +16*yrz[0]*ps1**4+24*yrz[2]*ps1**2
|
| 1299 |
+
zv1 = zv1 +48j*yrz[1]*ps1*ps2+48j*yrz[0]*(ps1**2)*ps2
|
| 1300 |
+
zv1 = zv1+12j*yrz[2]*ps2-12*yrz[0]*ps2**2+8*yrz[3]*ps1-8*yrz[1]*ps3
|
| 1301 |
+
zv1 = zv1-16*yrz[0]*ps1*ps3+yrz[4]-2j*yrz[0]*ps4
|
| 1302 |
+
zv = xrz[4]+exptheta*zv1
|
| 1303 |
+
ctx.prec = wpinitial
|
| 1304 |
+
return zv
|
| 1305 |
+
|
| 1306 |
+
def z_offline(ctx, w, k=0):
|
| 1307 |
+
r"""
|
| 1308 |
+
Computes Z(w) and its derivatives off the line
|
| 1309 |
+
"""
|
| 1310 |
+
s = ctx.mpf('0.5')+ctx.j*w
|
| 1311 |
+
s1 = s
|
| 1312 |
+
s2 = ctx.conj(1-s1)
|
| 1313 |
+
wpinitial = ctx.prec
|
| 1314 |
+
ctx.prec = 35
|
| 1315 |
+
# X see II Section 3.21 (109) and (110)
|
| 1316 |
+
# M1 see II Section 3.21 (111) and (112)
|
| 1317 |
+
if (ctx._re(s1) >= 0):
|
| 1318 |
+
M1 = 2*ctx.sqrt(ctx._im(s1)/(2 * ctx.pi))
|
| 1319 |
+
X = ctx.sqrt(abs(s1))
|
| 1320 |
+
else:
|
| 1321 |
+
X = (2*ctx.pi)**(ctx._re(s1)-1) * abs(1-s1)**(0.5-ctx._re(s1))
|
| 1322 |
+
M1 = 4 * ctx._im(s1)*X
|
| 1323 |
+
# M2 see II Section 3.21 (111) and (112)
|
| 1324 |
+
if (ctx._re(s2) >= 0):
|
| 1325 |
+
M2 = 2*ctx.sqrt(ctx._im(s2)/(2 * ctx.pi))
|
| 1326 |
+
else:
|
| 1327 |
+
M2 = 4 * ctx._im(s2)*(2*ctx.pi)**(ctx._re(s2)-1)*abs(1-s2)**(0.5-ctx._re(s2))
|
| 1328 |
+
# T see II Section 3.21 Prop. 27
|
| 1329 |
+
T = 2*abs(ctx.siegeltheta(w))
|
| 1330 |
+
# defining some precisions
|
| 1331 |
+
# see II Section 3.22 (115), (116), (117)
|
| 1332 |
+
aux1 = ctx.sqrt(X)
|
| 1333 |
+
aux2 = aux1*(M1+M2)
|
| 1334 |
+
aux3 = 3 +wpinitial
|
| 1335 |
+
wpbasic = max(6, 3+ctx.mag(T), ctx.mag(aux2*(26+2*T))+aux3)
|
| 1336 |
+
wptheta = max(4,ctx.mag(2.04*aux2)+aux3)
|
| 1337 |
+
wpR = ctx.mag(4*aux1)+aux3
|
| 1338 |
+
# now the computations
|
| 1339 |
+
ctx.prec = wptheta
|
| 1340 |
+
theta = ctx.siegeltheta(w)
|
| 1341 |
+
ctx.prec = wpR
|
| 1342 |
+
xrz, yrz = Rzeta_simul(ctx,s,k)
|
| 1343 |
+
pta = 0.25 + 0.5j*w
|
| 1344 |
+
ptb = 0.25 - 0.5j*w
|
| 1345 |
+
if k > 0: ps1 = 0.25*(ctx.psi(0,pta)+ctx.psi(0,ptb)) - ctx.ln(ctx.pi)/2
|
| 1346 |
+
if k > 1: ps2 = (1j/8)*(ctx.psi(1,pta)-ctx.psi(1,ptb))
|
| 1347 |
+
if k > 2: ps3 = (-1./16)*(ctx.psi(2,pta)+ctx.psi(2,ptb))
|
| 1348 |
+
if k > 3: ps4 = (-1j/32)*(ctx.psi(3,pta)-ctx.psi(3,ptb))
|
| 1349 |
+
ctx.prec = wpbasic
|
| 1350 |
+
exptheta = ctx.expj(theta)
|
| 1351 |
+
if k == 0:
|
| 1352 |
+
zv = exptheta*xrz[0]+yrz[0]/exptheta
|
| 1353 |
+
j = ctx.j
|
| 1354 |
+
if k == 1:
|
| 1355 |
+
zv = j*exptheta*(xrz[1]+xrz[0]*ps1)-j*(yrz[1]+yrz[0]*ps1)/exptheta
|
| 1356 |
+
if k == 2:
|
| 1357 |
+
zv = exptheta*(-2*xrz[1]*ps1-xrz[0]*ps1**2-xrz[2]+j*xrz[0]*ps2)
|
| 1358 |
+
zv =zv + (-2*yrz[1]*ps1-yrz[0]*ps1**2-yrz[2]-j*yrz[0]*ps2)/exptheta
|
| 1359 |
+
if k == 3:
|
| 1360 |
+
zv1 = -3*xrz[1]*ps1**2-xrz[0]*ps1**3-3*xrz[2]*ps1+j*3*xrz[1]*ps2
|
| 1361 |
+
zv1 = (zv1+ 3j*xrz[0]*ps1*ps2-xrz[3]+xrz[0]*ps3)*j*exptheta
|
| 1362 |
+
zv2 = 3*yrz[1]*ps1**2+yrz[0]*ps1**3+3*yrz[2]*ps1+j*3*yrz[1]*ps2
|
| 1363 |
+
zv2 = j*(zv2 + 3j*yrz[0]*ps1*ps2+ yrz[3]-yrz[0]*ps3)/exptheta
|
| 1364 |
+
zv = zv1+zv2
|
| 1365 |
+
if k == 4:
|
| 1366 |
+
zv1 = 4*xrz[1]*ps1**3+xrz[0]*ps1**4 + 6*xrz[2]*ps1**2
|
| 1367 |
+
zv1 = zv1-12j*xrz[1]*ps1*ps2-6j*xrz[0]*ps1**2*ps2-6j*xrz[2]*ps2
|
| 1368 |
+
zv1 = zv1-3*xrz[0]*ps2*ps2+4*xrz[3]*ps1-4*xrz[1]*ps3-4*xrz[0]*ps1*ps3
|
| 1369 |
+
zv1 = zv1+xrz[4]+j*xrz[0]*ps4
|
| 1370 |
+
zv2 = 4*yrz[1]*ps1**3+yrz[0]*ps1**4 + 6*yrz[2]*ps1**2
|
| 1371 |
+
zv2 = zv2+12j*yrz[1]*ps1*ps2+6j*yrz[0]*ps1**2*ps2+6j*yrz[2]*ps2
|
| 1372 |
+
zv2 = zv2-3*yrz[0]*ps2*ps2+4*yrz[3]*ps1-4*yrz[1]*ps3-4*yrz[0]*ps1*ps3
|
| 1373 |
+
zv2 = zv2+yrz[4]-j*yrz[0]*ps4
|
| 1374 |
+
zv = exptheta*zv1+zv2/exptheta
|
| 1375 |
+
ctx.prec = wpinitial
|
| 1376 |
+
return zv
|
| 1377 |
+
|
| 1378 |
+
@defun
|
| 1379 |
+
def rs_zeta(ctx, s, derivative=0, **kwargs):
|
| 1380 |
+
if derivative > 4:
|
| 1381 |
+
raise NotImplementedError
|
| 1382 |
+
s = ctx.convert(s)
|
| 1383 |
+
re = ctx._re(s); im = ctx._im(s)
|
| 1384 |
+
if im < 0:
|
| 1385 |
+
z = ctx.conj(ctx.rs_zeta(ctx.conj(s), derivative))
|
| 1386 |
+
return z
|
| 1387 |
+
critical_line = (re == 0.5)
|
| 1388 |
+
if critical_line:
|
| 1389 |
+
return zeta_half(ctx, s, derivative)
|
| 1390 |
+
else:
|
| 1391 |
+
return zeta_offline(ctx, s, derivative)
|
| 1392 |
+
|
| 1393 |
+
@defun
|
| 1394 |
+
def rs_z(ctx, w, derivative=0):
|
| 1395 |
+
w = ctx.convert(w)
|
| 1396 |
+
re = ctx._re(w); im = ctx._im(w)
|
| 1397 |
+
if re < 0:
|
| 1398 |
+
return rs_z(ctx, -w, derivative)
|
| 1399 |
+
critical_line = (im == 0)
|
| 1400 |
+
if critical_line :
|
| 1401 |
+
return z_half(ctx, w, derivative)
|
| 1402 |
+
else:
|
| 1403 |
+
return z_offline(ctx, w, derivative)
|
.venv/lib/python3.11/site-packages/mpmath/functions/signals.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .functions import defun_wrapped
|
| 2 |
+
|
| 3 |
+
@defun_wrapped
|
| 4 |
+
def squarew(ctx, t, amplitude=1, period=1):
|
| 5 |
+
P = period
|
| 6 |
+
A = amplitude
|
| 7 |
+
return A*((-1)**ctx.floor(2*t/P))
|
| 8 |
+
|
| 9 |
+
@defun_wrapped
|
| 10 |
+
def trianglew(ctx, t, amplitude=1, period=1):
|
| 11 |
+
A = amplitude
|
| 12 |
+
P = period
|
| 13 |
+
|
| 14 |
+
return 2*A*(0.5 - ctx.fabs(1 - 2*ctx.frac(t/P + 0.25)))
|
| 15 |
+
|
| 16 |
+
@defun_wrapped
|
| 17 |
+
def sawtoothw(ctx, t, amplitude=1, period=1):
|
| 18 |
+
A = amplitude
|
| 19 |
+
P = period
|
| 20 |
+
return A*ctx.frac(t/P)
|
| 21 |
+
|
| 22 |
+
@defun_wrapped
|
| 23 |
+
def unit_triangle(ctx, t, amplitude=1):
|
| 24 |
+
A = amplitude
|
| 25 |
+
if t <= -1 or t >= 1:
|
| 26 |
+
return ctx.zero
|
| 27 |
+
return A*(-ctx.fabs(t) + 1)
|
| 28 |
+
|
| 29 |
+
@defun_wrapped
|
| 30 |
+
def sigmoid(ctx, t, amplitude=1):
|
| 31 |
+
A = amplitude
|
| 32 |
+
return A / (1 + ctx.exp(-t))
|
.venv/lib/python3.11/site-packages/mpmath/functions/theta.py
ADDED
|
@@ -0,0 +1,1049 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .functions import defun, defun_wrapped
|
| 2 |
+
|
| 3 |
+
@defun
|
| 4 |
+
def _jacobi_theta2(ctx, z, q):
|
| 5 |
+
extra1 = 10
|
| 6 |
+
extra2 = 20
|
| 7 |
+
# the loops below break when the fixed precision quantities
|
| 8 |
+
# a and b go to zero;
|
| 9 |
+
# right shifting small negative numbers by wp one obtains -1, not zero,
|
| 10 |
+
# so the condition a**2 + b**2 > MIN is used to break the loops.
|
| 11 |
+
MIN = 2
|
| 12 |
+
if z == ctx.zero:
|
| 13 |
+
if (not ctx._im(q)):
|
| 14 |
+
wp = ctx.prec + extra1
|
| 15 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 16 |
+
x2 = (x*x) >> wp
|
| 17 |
+
a = b = x2
|
| 18 |
+
s = x2
|
| 19 |
+
while abs(a) > MIN:
|
| 20 |
+
b = (b*x2) >> wp
|
| 21 |
+
a = (a*b) >> wp
|
| 22 |
+
s += a
|
| 23 |
+
s = (1 << (wp+1)) + (s << 1)
|
| 24 |
+
s = ctx.ldexp(s, -wp)
|
| 25 |
+
else:
|
| 26 |
+
wp = ctx.prec + extra1
|
| 27 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 28 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 29 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 30 |
+
x2im = (xre*xim) >> (wp-1)
|
| 31 |
+
are = bre = x2re
|
| 32 |
+
aim = bim = x2im
|
| 33 |
+
sre = (1<<wp) + are
|
| 34 |
+
sim = aim
|
| 35 |
+
while are**2 + aim**2 > MIN:
|
| 36 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 37 |
+
(bre * x2im + bim * x2re) >> wp
|
| 38 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 39 |
+
(are * bim + aim * bre) >> wp
|
| 40 |
+
sre += are
|
| 41 |
+
sim += aim
|
| 42 |
+
sre = (sre << 1)
|
| 43 |
+
sim = (sim << 1)
|
| 44 |
+
sre = ctx.ldexp(sre, -wp)
|
| 45 |
+
sim = ctx.ldexp(sim, -wp)
|
| 46 |
+
s = ctx.mpc(sre, sim)
|
| 47 |
+
else:
|
| 48 |
+
if (not ctx._im(q)) and (not ctx._im(z)):
|
| 49 |
+
wp = ctx.prec + extra1
|
| 50 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 51 |
+
x2 = (x*x) >> wp
|
| 52 |
+
a = b = x2
|
| 53 |
+
c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
|
| 54 |
+
cn = c1 = ctx.to_fixed(c1, wp)
|
| 55 |
+
sn = s1 = ctx.to_fixed(s1, wp)
|
| 56 |
+
c2 = (c1*c1 - s1*s1) >> wp
|
| 57 |
+
s2 = (c1 * s1) >> (wp - 1)
|
| 58 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 59 |
+
s = c1 + ((a * cn) >> wp)
|
| 60 |
+
while abs(a) > MIN:
|
| 61 |
+
b = (b*x2) >> wp
|
| 62 |
+
a = (a*b) >> wp
|
| 63 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 64 |
+
s += (a * cn) >> wp
|
| 65 |
+
s = (s << 1)
|
| 66 |
+
s = ctx.ldexp(s, -wp)
|
| 67 |
+
s *= ctx.nthroot(q, 4)
|
| 68 |
+
return s
|
| 69 |
+
# case z real, q complex
|
| 70 |
+
elif not ctx._im(z):
|
| 71 |
+
wp = ctx.prec + extra2
|
| 72 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 73 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 74 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 75 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 76 |
+
are = bre = x2re
|
| 77 |
+
aim = bim = x2im
|
| 78 |
+
c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
|
| 79 |
+
cn = c1 = ctx.to_fixed(c1, wp)
|
| 80 |
+
sn = s1 = ctx.to_fixed(s1, wp)
|
| 81 |
+
c2 = (c1*c1 - s1*s1) >> wp
|
| 82 |
+
s2 = (c1 * s1) >> (wp - 1)
|
| 83 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 84 |
+
sre = c1 + ((are * cn) >> wp)
|
| 85 |
+
sim = ((aim * cn) >> wp)
|
| 86 |
+
while are**2 + aim**2 > MIN:
|
| 87 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 88 |
+
(bre * x2im + bim * x2re) >> wp
|
| 89 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 90 |
+
(are * bim + aim * bre) >> wp
|
| 91 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 92 |
+
sre += ((are * cn) >> wp)
|
| 93 |
+
sim += ((aim * cn) >> wp)
|
| 94 |
+
sre = (sre << 1)
|
| 95 |
+
sim = (sim << 1)
|
| 96 |
+
sre = ctx.ldexp(sre, -wp)
|
| 97 |
+
sim = ctx.ldexp(sim, -wp)
|
| 98 |
+
s = ctx.mpc(sre, sim)
|
| 99 |
+
#case z complex, q real
|
| 100 |
+
elif not ctx._im(q):
|
| 101 |
+
wp = ctx.prec + extra2
|
| 102 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 103 |
+
x2 = (x*x) >> wp
|
| 104 |
+
a = b = x2
|
| 105 |
+
prec0 = ctx.prec
|
| 106 |
+
ctx.prec = wp
|
| 107 |
+
c1, s1 = ctx.cos_sin(z)
|
| 108 |
+
ctx.prec = prec0
|
| 109 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 110 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 111 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 112 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 113 |
+
#c2 = (c1*c1 - s1*s1) >> wp
|
| 114 |
+
c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
|
| 115 |
+
c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
|
| 116 |
+
#s2 = (c1 * s1) >> (wp - 1)
|
| 117 |
+
s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
|
| 118 |
+
s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
|
| 119 |
+
#cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 120 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 121 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 122 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 123 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 124 |
+
cnre = t1
|
| 125 |
+
cnim = t2
|
| 126 |
+
snre = t3
|
| 127 |
+
snim = t4
|
| 128 |
+
sre = c1re + ((a * cnre) >> wp)
|
| 129 |
+
sim = c1im + ((a * cnim) >> wp)
|
| 130 |
+
while abs(a) > MIN:
|
| 131 |
+
b = (b*x2) >> wp
|
| 132 |
+
a = (a*b) >> wp
|
| 133 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 134 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 135 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 136 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 137 |
+
cnre = t1
|
| 138 |
+
cnim = t2
|
| 139 |
+
snre = t3
|
| 140 |
+
snim = t4
|
| 141 |
+
sre += ((a * cnre) >> wp)
|
| 142 |
+
sim += ((a * cnim) >> wp)
|
| 143 |
+
sre = (sre << 1)
|
| 144 |
+
sim = (sim << 1)
|
| 145 |
+
sre = ctx.ldexp(sre, -wp)
|
| 146 |
+
sim = ctx.ldexp(sim, -wp)
|
| 147 |
+
s = ctx.mpc(sre, sim)
|
| 148 |
+
# case z and q complex
|
| 149 |
+
else:
|
| 150 |
+
wp = ctx.prec + extra2
|
| 151 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 152 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 153 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 154 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 155 |
+
are = bre = x2re
|
| 156 |
+
aim = bim = x2im
|
| 157 |
+
prec0 = ctx.prec
|
| 158 |
+
ctx.prec = wp
|
| 159 |
+
# cos(z), sin(z) with z complex
|
| 160 |
+
c1, s1 = ctx.cos_sin(z)
|
| 161 |
+
ctx.prec = prec0
|
| 162 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 163 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 164 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 165 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 166 |
+
c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
|
| 167 |
+
c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
|
| 168 |
+
s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
|
| 169 |
+
s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
|
| 170 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 171 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 172 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 173 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 174 |
+
cnre = t1
|
| 175 |
+
cnim = t2
|
| 176 |
+
snre = t3
|
| 177 |
+
snim = t4
|
| 178 |
+
n = 1
|
| 179 |
+
termre = c1re
|
| 180 |
+
termim = c1im
|
| 181 |
+
sre = c1re + ((are * cnre - aim * cnim) >> wp)
|
| 182 |
+
sim = c1im + ((are * cnim + aim * cnre) >> wp)
|
| 183 |
+
n = 3
|
| 184 |
+
termre = ((are * cnre - aim * cnim) >> wp)
|
| 185 |
+
termim = ((are * cnim + aim * cnre) >> wp)
|
| 186 |
+
sre = c1re + ((are * cnre - aim * cnim) >> wp)
|
| 187 |
+
sim = c1im + ((are * cnim + aim * cnre) >> wp)
|
| 188 |
+
n = 5
|
| 189 |
+
while are**2 + aim**2 > MIN:
|
| 190 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 191 |
+
(bre * x2im + bim * x2re) >> wp
|
| 192 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 193 |
+
(are * bim + aim * bre) >> wp
|
| 194 |
+
#cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
|
| 195 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 196 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 197 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 198 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 199 |
+
cnre = t1
|
| 200 |
+
cnim = t2
|
| 201 |
+
snre = t3
|
| 202 |
+
snim = t4
|
| 203 |
+
termre = ((are * cnre - aim * cnim) >> wp)
|
| 204 |
+
termim = ((aim * cnre + are * cnim) >> wp)
|
| 205 |
+
sre += ((are * cnre - aim * cnim) >> wp)
|
| 206 |
+
sim += ((aim * cnre + are * cnim) >> wp)
|
| 207 |
+
n += 2
|
| 208 |
+
sre = (sre << 1)
|
| 209 |
+
sim = (sim << 1)
|
| 210 |
+
sre = ctx.ldexp(sre, -wp)
|
| 211 |
+
sim = ctx.ldexp(sim, -wp)
|
| 212 |
+
s = ctx.mpc(sre, sim)
|
| 213 |
+
s *= ctx.nthroot(q, 4)
|
| 214 |
+
return s
|
| 215 |
+
|
| 216 |
+
@defun
|
| 217 |
+
def _djacobi_theta2(ctx, z, q, nd):
|
| 218 |
+
MIN = 2
|
| 219 |
+
extra1 = 10
|
| 220 |
+
extra2 = 20
|
| 221 |
+
if (not ctx._im(q)) and (not ctx._im(z)):
|
| 222 |
+
wp = ctx.prec + extra1
|
| 223 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 224 |
+
x2 = (x*x) >> wp
|
| 225 |
+
a = b = x2
|
| 226 |
+
c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
|
| 227 |
+
cn = c1 = ctx.to_fixed(c1, wp)
|
| 228 |
+
sn = s1 = ctx.to_fixed(s1, wp)
|
| 229 |
+
c2 = (c1*c1 - s1*s1) >> wp
|
| 230 |
+
s2 = (c1 * s1) >> (wp - 1)
|
| 231 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 232 |
+
if (nd&1):
|
| 233 |
+
s = s1 + ((a * sn * 3**nd) >> wp)
|
| 234 |
+
else:
|
| 235 |
+
s = c1 + ((a * cn * 3**nd) >> wp)
|
| 236 |
+
n = 2
|
| 237 |
+
while abs(a) > MIN:
|
| 238 |
+
b = (b*x2) >> wp
|
| 239 |
+
a = (a*b) >> wp
|
| 240 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 241 |
+
if nd&1:
|
| 242 |
+
s += (a * sn * (2*n+1)**nd) >> wp
|
| 243 |
+
else:
|
| 244 |
+
s += (a * cn * (2*n+1)**nd) >> wp
|
| 245 |
+
n += 1
|
| 246 |
+
s = -(s << 1)
|
| 247 |
+
s = ctx.ldexp(s, -wp)
|
| 248 |
+
# case z real, q complex
|
| 249 |
+
elif not ctx._im(z):
|
| 250 |
+
wp = ctx.prec + extra2
|
| 251 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 252 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 253 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 254 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 255 |
+
are = bre = x2re
|
| 256 |
+
aim = bim = x2im
|
| 257 |
+
c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
|
| 258 |
+
cn = c1 = ctx.to_fixed(c1, wp)
|
| 259 |
+
sn = s1 = ctx.to_fixed(s1, wp)
|
| 260 |
+
c2 = (c1*c1 - s1*s1) >> wp
|
| 261 |
+
s2 = (c1 * s1) >> (wp - 1)
|
| 262 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 263 |
+
if (nd&1):
|
| 264 |
+
sre = s1 + ((are * sn * 3**nd) >> wp)
|
| 265 |
+
sim = ((aim * sn * 3**nd) >> wp)
|
| 266 |
+
else:
|
| 267 |
+
sre = c1 + ((are * cn * 3**nd) >> wp)
|
| 268 |
+
sim = ((aim * cn * 3**nd) >> wp)
|
| 269 |
+
n = 5
|
| 270 |
+
while are**2 + aim**2 > MIN:
|
| 271 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 272 |
+
(bre * x2im + bim * x2re) >> wp
|
| 273 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 274 |
+
(are * bim + aim * bre) >> wp
|
| 275 |
+
cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 276 |
+
|
| 277 |
+
if (nd&1):
|
| 278 |
+
sre += ((are * sn * n**nd) >> wp)
|
| 279 |
+
sim += ((aim * sn * n**nd) >> wp)
|
| 280 |
+
else:
|
| 281 |
+
sre += ((are * cn * n**nd) >> wp)
|
| 282 |
+
sim += ((aim * cn * n**nd) >> wp)
|
| 283 |
+
n += 2
|
| 284 |
+
sre = -(sre << 1)
|
| 285 |
+
sim = -(sim << 1)
|
| 286 |
+
sre = ctx.ldexp(sre, -wp)
|
| 287 |
+
sim = ctx.ldexp(sim, -wp)
|
| 288 |
+
s = ctx.mpc(sre, sim)
|
| 289 |
+
#case z complex, q real
|
| 290 |
+
elif not ctx._im(q):
|
| 291 |
+
wp = ctx.prec + extra2
|
| 292 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 293 |
+
x2 = (x*x) >> wp
|
| 294 |
+
a = b = x2
|
| 295 |
+
prec0 = ctx.prec
|
| 296 |
+
ctx.prec = wp
|
| 297 |
+
c1, s1 = ctx.cos_sin(z)
|
| 298 |
+
ctx.prec = prec0
|
| 299 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 300 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 301 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 302 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 303 |
+
#c2 = (c1*c1 - s1*s1) >> wp
|
| 304 |
+
c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
|
| 305 |
+
c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
|
| 306 |
+
#s2 = (c1 * s1) >> (wp - 1)
|
| 307 |
+
s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
|
| 308 |
+
s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
|
| 309 |
+
#cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
|
| 310 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 311 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 312 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 313 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 314 |
+
cnre = t1
|
| 315 |
+
cnim = t2
|
| 316 |
+
snre = t3
|
| 317 |
+
snim = t4
|
| 318 |
+
if (nd&1):
|
| 319 |
+
sre = s1re + ((a * snre * 3**nd) >> wp)
|
| 320 |
+
sim = s1im + ((a * snim * 3**nd) >> wp)
|
| 321 |
+
else:
|
| 322 |
+
sre = c1re + ((a * cnre * 3**nd) >> wp)
|
| 323 |
+
sim = c1im + ((a * cnim * 3**nd) >> wp)
|
| 324 |
+
n = 5
|
| 325 |
+
while abs(a) > MIN:
|
| 326 |
+
b = (b*x2) >> wp
|
| 327 |
+
a = (a*b) >> wp
|
| 328 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 329 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 330 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 331 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 332 |
+
cnre = t1
|
| 333 |
+
cnim = t2
|
| 334 |
+
snre = t3
|
| 335 |
+
snim = t4
|
| 336 |
+
if (nd&1):
|
| 337 |
+
sre += ((a * snre * n**nd) >> wp)
|
| 338 |
+
sim += ((a * snim * n**nd) >> wp)
|
| 339 |
+
else:
|
| 340 |
+
sre += ((a * cnre * n**nd) >> wp)
|
| 341 |
+
sim += ((a * cnim * n**nd) >> wp)
|
| 342 |
+
n += 2
|
| 343 |
+
sre = -(sre << 1)
|
| 344 |
+
sim = -(sim << 1)
|
| 345 |
+
sre = ctx.ldexp(sre, -wp)
|
| 346 |
+
sim = ctx.ldexp(sim, -wp)
|
| 347 |
+
s = ctx.mpc(sre, sim)
|
| 348 |
+
# case z and q complex
|
| 349 |
+
else:
|
| 350 |
+
wp = ctx.prec + extra2
|
| 351 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 352 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 353 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 354 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 355 |
+
are = bre = x2re
|
| 356 |
+
aim = bim = x2im
|
| 357 |
+
prec0 = ctx.prec
|
| 358 |
+
ctx.prec = wp
|
| 359 |
+
# cos(2*z), sin(2*z) with z complex
|
| 360 |
+
c1, s1 = ctx.cos_sin(z)
|
| 361 |
+
ctx.prec = prec0
|
| 362 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 363 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 364 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 365 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 366 |
+
c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
|
| 367 |
+
c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
|
| 368 |
+
s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
|
| 369 |
+
s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
|
| 370 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 371 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 372 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 373 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 374 |
+
cnre = t1
|
| 375 |
+
cnim = t2
|
| 376 |
+
snre = t3
|
| 377 |
+
snim = t4
|
| 378 |
+
if (nd&1):
|
| 379 |
+
sre = s1re + (((are * snre - aim * snim) * 3**nd) >> wp)
|
| 380 |
+
sim = s1im + (((are * snim + aim * snre)* 3**nd) >> wp)
|
| 381 |
+
else:
|
| 382 |
+
sre = c1re + (((are * cnre - aim * cnim) * 3**nd) >> wp)
|
| 383 |
+
sim = c1im + (((are * cnim + aim * cnre)* 3**nd) >> wp)
|
| 384 |
+
n = 5
|
| 385 |
+
while are**2 + aim**2 > MIN:
|
| 386 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 387 |
+
(bre * x2im + bim * x2re) >> wp
|
| 388 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 389 |
+
(are * bim + aim * bre) >> wp
|
| 390 |
+
#cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
|
| 391 |
+
t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
|
| 392 |
+
t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
|
| 393 |
+
t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
|
| 394 |
+
t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
|
| 395 |
+
cnre = t1
|
| 396 |
+
cnim = t2
|
| 397 |
+
snre = t3
|
| 398 |
+
snim = t4
|
| 399 |
+
if (nd&1):
|
| 400 |
+
sre += (((are * snre - aim * snim) * n**nd) >> wp)
|
| 401 |
+
sim += (((aim * snre + are * snim) * n**nd) >> wp)
|
| 402 |
+
else:
|
| 403 |
+
sre += (((are * cnre - aim * cnim) * n**nd) >> wp)
|
| 404 |
+
sim += (((aim * cnre + are * cnim) * n**nd) >> wp)
|
| 405 |
+
n += 2
|
| 406 |
+
sre = -(sre << 1)
|
| 407 |
+
sim = -(sim << 1)
|
| 408 |
+
sre = ctx.ldexp(sre, -wp)
|
| 409 |
+
sim = ctx.ldexp(sim, -wp)
|
| 410 |
+
s = ctx.mpc(sre, sim)
|
| 411 |
+
s *= ctx.nthroot(q, 4)
|
| 412 |
+
if (nd&1):
|
| 413 |
+
return (-1)**(nd//2) * s
|
| 414 |
+
else:
|
| 415 |
+
return (-1)**(1 + nd//2) * s
|
| 416 |
+
|
| 417 |
+
@defun
|
| 418 |
+
def _jacobi_theta3(ctx, z, q):
|
| 419 |
+
extra1 = 10
|
| 420 |
+
extra2 = 20
|
| 421 |
+
MIN = 2
|
| 422 |
+
if z == ctx.zero:
|
| 423 |
+
if not ctx._im(q):
|
| 424 |
+
wp = ctx.prec + extra1
|
| 425 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 426 |
+
s = x
|
| 427 |
+
a = b = x
|
| 428 |
+
x2 = (x*x) >> wp
|
| 429 |
+
while abs(a) > MIN:
|
| 430 |
+
b = (b*x2) >> wp
|
| 431 |
+
a = (a*b) >> wp
|
| 432 |
+
s += a
|
| 433 |
+
s = (1 << wp) + (s << 1)
|
| 434 |
+
s = ctx.ldexp(s, -wp)
|
| 435 |
+
return s
|
| 436 |
+
else:
|
| 437 |
+
wp = ctx.prec + extra1
|
| 438 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 439 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 440 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 441 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 442 |
+
sre = are = bre = xre
|
| 443 |
+
sim = aim = bim = xim
|
| 444 |
+
while are**2 + aim**2 > MIN:
|
| 445 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 446 |
+
(bre * x2im + bim * x2re) >> wp
|
| 447 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 448 |
+
(are * bim + aim * bre) >> wp
|
| 449 |
+
sre += are
|
| 450 |
+
sim += aim
|
| 451 |
+
sre = (1 << wp) + (sre << 1)
|
| 452 |
+
sim = (sim << 1)
|
| 453 |
+
sre = ctx.ldexp(sre, -wp)
|
| 454 |
+
sim = ctx.ldexp(sim, -wp)
|
| 455 |
+
s = ctx.mpc(sre, sim)
|
| 456 |
+
return s
|
| 457 |
+
else:
|
| 458 |
+
if (not ctx._im(q)) and (not ctx._im(z)):
|
| 459 |
+
s = 0
|
| 460 |
+
wp = ctx.prec + extra1
|
| 461 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 462 |
+
a = b = x
|
| 463 |
+
x2 = (x*x) >> wp
|
| 464 |
+
c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
|
| 465 |
+
c1 = ctx.to_fixed(c1, wp)
|
| 466 |
+
s1 = ctx.to_fixed(s1, wp)
|
| 467 |
+
cn = c1
|
| 468 |
+
sn = s1
|
| 469 |
+
s += (a * cn) >> wp
|
| 470 |
+
while abs(a) > MIN:
|
| 471 |
+
b = (b*x2) >> wp
|
| 472 |
+
a = (a*b) >> wp
|
| 473 |
+
cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
|
| 474 |
+
s += (a * cn) >> wp
|
| 475 |
+
s = (1 << wp) + (s << 1)
|
| 476 |
+
s = ctx.ldexp(s, -wp)
|
| 477 |
+
return s
|
| 478 |
+
# case z real, q complex
|
| 479 |
+
elif not ctx._im(z):
|
| 480 |
+
wp = ctx.prec + extra2
|
| 481 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 482 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 483 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 484 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 485 |
+
are = bre = xre
|
| 486 |
+
aim = bim = xim
|
| 487 |
+
c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
|
| 488 |
+
c1 = ctx.to_fixed(c1, wp)
|
| 489 |
+
s1 = ctx.to_fixed(s1, wp)
|
| 490 |
+
cn = c1
|
| 491 |
+
sn = s1
|
| 492 |
+
sre = (are * cn) >> wp
|
| 493 |
+
sim = (aim * cn) >> wp
|
| 494 |
+
while are**2 + aim**2 > MIN:
|
| 495 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 496 |
+
(bre * x2im + bim * x2re) >> wp
|
| 497 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 498 |
+
(are * bim + aim * bre) >> wp
|
| 499 |
+
cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
|
| 500 |
+
sre += (are * cn) >> wp
|
| 501 |
+
sim += (aim * cn) >> wp
|
| 502 |
+
sre = (1 << wp) + (sre << 1)
|
| 503 |
+
sim = (sim << 1)
|
| 504 |
+
sre = ctx.ldexp(sre, -wp)
|
| 505 |
+
sim = ctx.ldexp(sim, -wp)
|
| 506 |
+
s = ctx.mpc(sre, sim)
|
| 507 |
+
return s
|
| 508 |
+
#case z complex, q real
|
| 509 |
+
elif not ctx._im(q):
|
| 510 |
+
wp = ctx.prec + extra2
|
| 511 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 512 |
+
a = b = x
|
| 513 |
+
x2 = (x*x) >> wp
|
| 514 |
+
prec0 = ctx.prec
|
| 515 |
+
ctx.prec = wp
|
| 516 |
+
c1, s1 = ctx.cos_sin(2*z)
|
| 517 |
+
ctx.prec = prec0
|
| 518 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 519 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 520 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 521 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 522 |
+
sre = (a * cnre) >> wp
|
| 523 |
+
sim = (a * cnim) >> wp
|
| 524 |
+
while abs(a) > MIN:
|
| 525 |
+
b = (b*x2) >> wp
|
| 526 |
+
a = (a*b) >> wp
|
| 527 |
+
t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
|
| 528 |
+
t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
|
| 529 |
+
t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
|
| 530 |
+
t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
|
| 531 |
+
cnre = t1
|
| 532 |
+
cnim = t2
|
| 533 |
+
snre = t3
|
| 534 |
+
snim = t4
|
| 535 |
+
sre += (a * cnre) >> wp
|
| 536 |
+
sim += (a * cnim) >> wp
|
| 537 |
+
sre = (1 << wp) + (sre << 1)
|
| 538 |
+
sim = (sim << 1)
|
| 539 |
+
sre = ctx.ldexp(sre, -wp)
|
| 540 |
+
sim = ctx.ldexp(sim, -wp)
|
| 541 |
+
s = ctx.mpc(sre, sim)
|
| 542 |
+
return s
|
| 543 |
+
# case z and q complex
|
| 544 |
+
else:
|
| 545 |
+
wp = ctx.prec + extra2
|
| 546 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 547 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 548 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 549 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 550 |
+
are = bre = xre
|
| 551 |
+
aim = bim = xim
|
| 552 |
+
prec0 = ctx.prec
|
| 553 |
+
ctx.prec = wp
|
| 554 |
+
# cos(2*z), sin(2*z) with z complex
|
| 555 |
+
c1, s1 = ctx.cos_sin(2*z)
|
| 556 |
+
ctx.prec = prec0
|
| 557 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 558 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 559 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 560 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 561 |
+
sre = (are * cnre - aim * cnim) >> wp
|
| 562 |
+
sim = (aim * cnre + are * cnim) >> wp
|
| 563 |
+
while are**2 + aim**2 > MIN:
|
| 564 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 565 |
+
(bre * x2im + bim * x2re) >> wp
|
| 566 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 567 |
+
(are * bim + aim * bre) >> wp
|
| 568 |
+
t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
|
| 569 |
+
t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
|
| 570 |
+
t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
|
| 571 |
+
t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
|
| 572 |
+
cnre = t1
|
| 573 |
+
cnim = t2
|
| 574 |
+
snre = t3
|
| 575 |
+
snim = t4
|
| 576 |
+
sre += (are * cnre - aim * cnim) >> wp
|
| 577 |
+
sim += (aim * cnre + are * cnim) >> wp
|
| 578 |
+
sre = (1 << wp) + (sre << 1)
|
| 579 |
+
sim = (sim << 1)
|
| 580 |
+
sre = ctx.ldexp(sre, -wp)
|
| 581 |
+
sim = ctx.ldexp(sim, -wp)
|
| 582 |
+
s = ctx.mpc(sre, sim)
|
| 583 |
+
return s
|
| 584 |
+
|
| 585 |
+
@defun
|
| 586 |
+
def _djacobi_theta3(ctx, z, q, nd):
|
| 587 |
+
"""nd=1,2,3 order of the derivative with respect to z"""
|
| 588 |
+
MIN = 2
|
| 589 |
+
extra1 = 10
|
| 590 |
+
extra2 = 20
|
| 591 |
+
if (not ctx._im(q)) and (not ctx._im(z)):
|
| 592 |
+
s = 0
|
| 593 |
+
wp = ctx.prec + extra1
|
| 594 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 595 |
+
a = b = x
|
| 596 |
+
x2 = (x*x) >> wp
|
| 597 |
+
c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
|
| 598 |
+
c1 = ctx.to_fixed(c1, wp)
|
| 599 |
+
s1 = ctx.to_fixed(s1, wp)
|
| 600 |
+
cn = c1
|
| 601 |
+
sn = s1
|
| 602 |
+
if (nd&1):
|
| 603 |
+
s += (a * sn) >> wp
|
| 604 |
+
else:
|
| 605 |
+
s += (a * cn) >> wp
|
| 606 |
+
n = 2
|
| 607 |
+
while abs(a) > MIN:
|
| 608 |
+
b = (b*x2) >> wp
|
| 609 |
+
a = (a*b) >> wp
|
| 610 |
+
cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
|
| 611 |
+
if nd&1:
|
| 612 |
+
s += (a * sn * n**nd) >> wp
|
| 613 |
+
else:
|
| 614 |
+
s += (a * cn * n**nd) >> wp
|
| 615 |
+
n += 1
|
| 616 |
+
s = -(s << (nd+1))
|
| 617 |
+
s = ctx.ldexp(s, -wp)
|
| 618 |
+
# case z real, q complex
|
| 619 |
+
elif not ctx._im(z):
|
| 620 |
+
wp = ctx.prec + extra2
|
| 621 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 622 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 623 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 624 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 625 |
+
are = bre = xre
|
| 626 |
+
aim = bim = xim
|
| 627 |
+
c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
|
| 628 |
+
c1 = ctx.to_fixed(c1, wp)
|
| 629 |
+
s1 = ctx.to_fixed(s1, wp)
|
| 630 |
+
cn = c1
|
| 631 |
+
sn = s1
|
| 632 |
+
if (nd&1):
|
| 633 |
+
sre = (are * sn) >> wp
|
| 634 |
+
sim = (aim * sn) >> wp
|
| 635 |
+
else:
|
| 636 |
+
sre = (are * cn) >> wp
|
| 637 |
+
sim = (aim * cn) >> wp
|
| 638 |
+
n = 2
|
| 639 |
+
while are**2 + aim**2 > MIN:
|
| 640 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 641 |
+
(bre * x2im + bim * x2re) >> wp
|
| 642 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 643 |
+
(are * bim + aim * bre) >> wp
|
| 644 |
+
cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
|
| 645 |
+
if nd&1:
|
| 646 |
+
sre += (are * sn * n**nd) >> wp
|
| 647 |
+
sim += (aim * sn * n**nd) >> wp
|
| 648 |
+
else:
|
| 649 |
+
sre += (are * cn * n**nd) >> wp
|
| 650 |
+
sim += (aim * cn * n**nd) >> wp
|
| 651 |
+
n += 1
|
| 652 |
+
sre = -(sre << (nd+1))
|
| 653 |
+
sim = -(sim << (nd+1))
|
| 654 |
+
sre = ctx.ldexp(sre, -wp)
|
| 655 |
+
sim = ctx.ldexp(sim, -wp)
|
| 656 |
+
s = ctx.mpc(sre, sim)
|
| 657 |
+
#case z complex, q real
|
| 658 |
+
elif not ctx._im(q):
|
| 659 |
+
wp = ctx.prec + extra2
|
| 660 |
+
x = ctx.to_fixed(ctx._re(q), wp)
|
| 661 |
+
a = b = x
|
| 662 |
+
x2 = (x*x) >> wp
|
| 663 |
+
prec0 = ctx.prec
|
| 664 |
+
ctx.prec = wp
|
| 665 |
+
c1, s1 = ctx.cos_sin(2*z)
|
| 666 |
+
ctx.prec = prec0
|
| 667 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 668 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 669 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 670 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 671 |
+
if (nd&1):
|
| 672 |
+
sre = (a * snre) >> wp
|
| 673 |
+
sim = (a * snim) >> wp
|
| 674 |
+
else:
|
| 675 |
+
sre = (a * cnre) >> wp
|
| 676 |
+
sim = (a * cnim) >> wp
|
| 677 |
+
n = 2
|
| 678 |
+
while abs(a) > MIN:
|
| 679 |
+
b = (b*x2) >> wp
|
| 680 |
+
a = (a*b) >> wp
|
| 681 |
+
t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
|
| 682 |
+
t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
|
| 683 |
+
t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
|
| 684 |
+
t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
|
| 685 |
+
cnre = t1
|
| 686 |
+
cnim = t2
|
| 687 |
+
snre = t3
|
| 688 |
+
snim = t4
|
| 689 |
+
if (nd&1):
|
| 690 |
+
sre += (a * snre * n**nd) >> wp
|
| 691 |
+
sim += (a * snim * n**nd) >> wp
|
| 692 |
+
else:
|
| 693 |
+
sre += (a * cnre * n**nd) >> wp
|
| 694 |
+
sim += (a * cnim * n**nd) >> wp
|
| 695 |
+
n += 1
|
| 696 |
+
sre = -(sre << (nd+1))
|
| 697 |
+
sim = -(sim << (nd+1))
|
| 698 |
+
sre = ctx.ldexp(sre, -wp)
|
| 699 |
+
sim = ctx.ldexp(sim, -wp)
|
| 700 |
+
s = ctx.mpc(sre, sim)
|
| 701 |
+
# case z and q complex
|
| 702 |
+
else:
|
| 703 |
+
wp = ctx.prec + extra2
|
| 704 |
+
xre = ctx.to_fixed(ctx._re(q), wp)
|
| 705 |
+
xim = ctx.to_fixed(ctx._im(q), wp)
|
| 706 |
+
x2re = (xre*xre - xim*xim) >> wp
|
| 707 |
+
x2im = (xre*xim) >> (wp - 1)
|
| 708 |
+
are = bre = xre
|
| 709 |
+
aim = bim = xim
|
| 710 |
+
prec0 = ctx.prec
|
| 711 |
+
ctx.prec = wp
|
| 712 |
+
# cos(2*z), sin(2*z) with z complex
|
| 713 |
+
c1, s1 = ctx.cos_sin(2*z)
|
| 714 |
+
ctx.prec = prec0
|
| 715 |
+
cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
|
| 716 |
+
cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
|
| 717 |
+
snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
|
| 718 |
+
snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
|
| 719 |
+
if (nd&1):
|
| 720 |
+
sre = (are * snre - aim * snim) >> wp
|
| 721 |
+
sim = (aim * snre + are * snim) >> wp
|
| 722 |
+
else:
|
| 723 |
+
sre = (are * cnre - aim * cnim) >> wp
|
| 724 |
+
sim = (aim * cnre + are * cnim) >> wp
|
| 725 |
+
n = 2
|
| 726 |
+
while are**2 + aim**2 > MIN:
|
| 727 |
+
bre, bim = (bre * x2re - bim * x2im) >> wp, \
|
| 728 |
+
(bre * x2im + bim * x2re) >> wp
|
| 729 |
+
are, aim = (are * bre - aim * bim) >> wp, \
|
| 730 |
+
(are * bim + aim * bre) >> wp
|
| 731 |
+
t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
|
| 732 |
+
t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
|
| 733 |
+
t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
|
| 734 |
+
t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
|
| 735 |
+
cnre = t1
|
| 736 |
+
cnim = t2
|
| 737 |
+
snre = t3
|
| 738 |
+
snim = t4
|
| 739 |
+
if(nd&1):
|
| 740 |
+
sre += ((are * snre - aim * snim) * n**nd) >> wp
|
| 741 |
+
sim += ((aim * snre + are * snim) * n**nd) >> wp
|
| 742 |
+
else:
|
| 743 |
+
sre += ((are * cnre - aim * cnim) * n**nd) >> wp
|
| 744 |
+
sim += ((aim * cnre + are * cnim) * n**nd) >> wp
|
| 745 |
+
n += 1
|
| 746 |
+
sre = -(sre << (nd+1))
|
| 747 |
+
sim = -(sim << (nd+1))
|
| 748 |
+
sre = ctx.ldexp(sre, -wp)
|
| 749 |
+
sim = ctx.ldexp(sim, -wp)
|
| 750 |
+
s = ctx.mpc(sre, sim)
|
| 751 |
+
if (nd&1):
|
| 752 |
+
return (-1)**(nd//2) * s
|
| 753 |
+
else:
|
| 754 |
+
return (-1)**(1 + nd//2) * s
|
| 755 |
+
|
| 756 |
+
@defun
|
| 757 |
+
def _jacobi_theta2a(ctx, z, q):
|
| 758 |
+
"""
|
| 759 |
+
case ctx._im(z) != 0
|
| 760 |
+
theta(2, z, q) =
|
| 761 |
+
q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n=-inf, inf)
|
| 762 |
+
max term for minimum (2*n+1)*log(q).real - 2* ctx._im(z)
|
| 763 |
+
n0 = int(ctx._im(z)/log(q).real - 1/2)
|
| 764 |
+
theta(2, z, q) =
|
| 765 |
+
q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n=n0, inf) +
|
| 766 |
+
q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n, n0-1, -inf)
|
| 767 |
+
"""
|
| 768 |
+
n = n0 = int(ctx._im(z)/ctx._re(ctx.log(q)) - 1/2)
|
| 769 |
+
e2 = ctx.expj(2*z)
|
| 770 |
+
e = e0 = ctx.expj((2*n+1)*z)
|
| 771 |
+
a = q**(n*n + n)
|
| 772 |
+
# leading term
|
| 773 |
+
term = a * e
|
| 774 |
+
s = term
|
| 775 |
+
eps1 = ctx.eps*abs(term)
|
| 776 |
+
while 1:
|
| 777 |
+
n += 1
|
| 778 |
+
e = e * e2
|
| 779 |
+
term = q**(n*n + n) * e
|
| 780 |
+
if abs(term) < eps1:
|
| 781 |
+
break
|
| 782 |
+
s += term
|
| 783 |
+
e = e0
|
| 784 |
+
e2 = ctx.expj(-2*z)
|
| 785 |
+
n = n0
|
| 786 |
+
while 1:
|
| 787 |
+
n -= 1
|
| 788 |
+
e = e * e2
|
| 789 |
+
term = q**(n*n + n) * e
|
| 790 |
+
if abs(term) < eps1:
|
| 791 |
+
break
|
| 792 |
+
s += term
|
| 793 |
+
s = s * ctx.nthroot(q, 4)
|
| 794 |
+
return s
|
| 795 |
+
|
| 796 |
+
@defun
|
| 797 |
+
def _jacobi_theta3a(ctx, z, q):
|
| 798 |
+
"""
|
| 799 |
+
case ctx._im(z) != 0
|
| 800 |
+
theta3(z, q) = Sum(q**(n*n) * exp(j*2*n*z), n, -inf, inf)
|
| 801 |
+
max term for n*abs(log(q).real) + ctx._im(z) ~= 0
|
| 802 |
+
n0 = int(- ctx._im(z)/abs(log(q).real))
|
| 803 |
+
"""
|
| 804 |
+
n = n0 = int(-ctx._im(z)/abs(ctx._re(ctx.log(q))))
|
| 805 |
+
e2 = ctx.expj(2*z)
|
| 806 |
+
e = e0 = ctx.expj(2*n*z)
|
| 807 |
+
s = term = q**(n*n) * e
|
| 808 |
+
eps1 = ctx.eps*abs(term)
|
| 809 |
+
while 1:
|
| 810 |
+
n += 1
|
| 811 |
+
e = e * e2
|
| 812 |
+
term = q**(n*n) * e
|
| 813 |
+
if abs(term) < eps1:
|
| 814 |
+
break
|
| 815 |
+
s += term
|
| 816 |
+
e = e0
|
| 817 |
+
e2 = ctx.expj(-2*z)
|
| 818 |
+
n = n0
|
| 819 |
+
while 1:
|
| 820 |
+
n -= 1
|
| 821 |
+
e = e * e2
|
| 822 |
+
term = q**(n*n) * e
|
| 823 |
+
if abs(term) < eps1:
|
| 824 |
+
break
|
| 825 |
+
s += term
|
| 826 |
+
return s
|
| 827 |
+
|
| 828 |
+
@defun
|
| 829 |
+
def _djacobi_theta2a(ctx, z, q, nd):
|
| 830 |
+
"""
|
| 831 |
+
case ctx._im(z) != 0
|
| 832 |
+
dtheta(2, z, q, nd) =
|
| 833 |
+
j* q**1/4 * Sum(q**(n*n + n) * (2*n+1)*exp(j*(2*n + 1)*z), n=-inf, inf)
|
| 834 |
+
max term for (2*n0+1)*log(q).real - 2* ctx._im(z) ~= 0
|
| 835 |
+
n0 = int(ctx._im(z)/log(q).real - 1/2)
|
| 836 |
+
"""
|
| 837 |
+
n = n0 = int(ctx._im(z)/ctx._re(ctx.log(q)) - 1/2)
|
| 838 |
+
e2 = ctx.expj(2*z)
|
| 839 |
+
e = e0 = ctx.expj((2*n + 1)*z)
|
| 840 |
+
a = q**(n*n + n)
|
| 841 |
+
# leading term
|
| 842 |
+
term = (2*n+1)**nd * a * e
|
| 843 |
+
s = term
|
| 844 |
+
eps1 = ctx.eps*abs(term)
|
| 845 |
+
while 1:
|
| 846 |
+
n += 1
|
| 847 |
+
e = e * e2
|
| 848 |
+
term = (2*n+1)**nd * q**(n*n + n) * e
|
| 849 |
+
if abs(term) < eps1:
|
| 850 |
+
break
|
| 851 |
+
s += term
|
| 852 |
+
e = e0
|
| 853 |
+
e2 = ctx.expj(-2*z)
|
| 854 |
+
n = n0
|
| 855 |
+
while 1:
|
| 856 |
+
n -= 1
|
| 857 |
+
e = e * e2
|
| 858 |
+
term = (2*n+1)**nd * q**(n*n + n) * e
|
| 859 |
+
if abs(term) < eps1:
|
| 860 |
+
break
|
| 861 |
+
s += term
|
| 862 |
+
return ctx.j**nd * s * ctx.nthroot(q, 4)
|
| 863 |
+
|
| 864 |
+
@defun
|
| 865 |
+
def _djacobi_theta3a(ctx, z, q, nd):
|
| 866 |
+
"""
|
| 867 |
+
case ctx._im(z) != 0
|
| 868 |
+
djtheta3(z, q, nd) = (2*j)**nd *
|
| 869 |
+
Sum(q**(n*n) * n**nd * exp(j*2*n*z), n, -inf, inf)
|
| 870 |
+
max term for minimum n*abs(log(q).real) + ctx._im(z)
|
| 871 |
+
"""
|
| 872 |
+
n = n0 = int(-ctx._im(z)/abs(ctx._re(ctx.log(q))))
|
| 873 |
+
e2 = ctx.expj(2*z)
|
| 874 |
+
e = e0 = ctx.expj(2*n*z)
|
| 875 |
+
a = q**(n*n) * e
|
| 876 |
+
s = term = n**nd * a
|
| 877 |
+
if n != 0:
|
| 878 |
+
eps1 = ctx.eps*abs(term)
|
| 879 |
+
else:
|
| 880 |
+
eps1 = ctx.eps*abs(a)
|
| 881 |
+
while 1:
|
| 882 |
+
n += 1
|
| 883 |
+
e = e * e2
|
| 884 |
+
a = q**(n*n) * e
|
| 885 |
+
term = n**nd * a
|
| 886 |
+
if n != 0:
|
| 887 |
+
aterm = abs(term)
|
| 888 |
+
else:
|
| 889 |
+
aterm = abs(a)
|
| 890 |
+
if aterm < eps1:
|
| 891 |
+
break
|
| 892 |
+
s += term
|
| 893 |
+
e = e0
|
| 894 |
+
e2 = ctx.expj(-2*z)
|
| 895 |
+
n = n0
|
| 896 |
+
while 1:
|
| 897 |
+
n -= 1
|
| 898 |
+
e = e * e2
|
| 899 |
+
a = q**(n*n) * e
|
| 900 |
+
term = n**nd * a
|
| 901 |
+
if n != 0:
|
| 902 |
+
aterm = abs(term)
|
| 903 |
+
else:
|
| 904 |
+
aterm = abs(a)
|
| 905 |
+
if aterm < eps1:
|
| 906 |
+
break
|
| 907 |
+
s += term
|
| 908 |
+
return (2*ctx.j)**nd * s
|
| 909 |
+
|
| 910 |
+
@defun
|
| 911 |
+
def jtheta(ctx, n, z, q, derivative=0):
|
| 912 |
+
if derivative:
|
| 913 |
+
return ctx._djtheta(n, z, q, derivative)
|
| 914 |
+
|
| 915 |
+
z = ctx.convert(z)
|
| 916 |
+
q = ctx.convert(q)
|
| 917 |
+
|
| 918 |
+
# Implementation note
|
| 919 |
+
# If ctx._im(z) is close to zero, _jacobi_theta2 and _jacobi_theta3
|
| 920 |
+
# are used,
|
| 921 |
+
# which compute the series starting from n=0 using fixed precision
|
| 922 |
+
# numbers;
|
| 923 |
+
# otherwise _jacobi_theta2a and _jacobi_theta3a are used, which compute
|
| 924 |
+
# the series starting from n=n0, which is the largest term.
|
| 925 |
+
|
| 926 |
+
# TODO: write _jacobi_theta2a and _jacobi_theta3a using fixed-point
|
| 927 |
+
|
| 928 |
+
if abs(q) > ctx.THETA_Q_LIM:
|
| 929 |
+
raise ValueError('abs(q) > THETA_Q_LIM = %f' % ctx.THETA_Q_LIM)
|
| 930 |
+
|
| 931 |
+
extra = 10
|
| 932 |
+
if z:
|
| 933 |
+
M = ctx.mag(z)
|
| 934 |
+
if M > 5 or (n == 1 and M < -5):
|
| 935 |
+
extra += 2*abs(M)
|
| 936 |
+
cz = 0.5
|
| 937 |
+
extra2 = 50
|
| 938 |
+
prec0 = ctx.prec
|
| 939 |
+
try:
|
| 940 |
+
ctx.prec += extra
|
| 941 |
+
if n == 1:
|
| 942 |
+
if ctx._im(z):
|
| 943 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 944 |
+
ctx.dps += extra2
|
| 945 |
+
res = ctx._jacobi_theta2(z - ctx.pi/2, q)
|
| 946 |
+
else:
|
| 947 |
+
ctx.dps += 10
|
| 948 |
+
res = ctx._jacobi_theta2a(z - ctx.pi/2, q)
|
| 949 |
+
else:
|
| 950 |
+
res = ctx._jacobi_theta2(z - ctx.pi/2, q)
|
| 951 |
+
elif n == 2:
|
| 952 |
+
if ctx._im(z):
|
| 953 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 954 |
+
ctx.dps += extra2
|
| 955 |
+
res = ctx._jacobi_theta2(z, q)
|
| 956 |
+
else:
|
| 957 |
+
ctx.dps += 10
|
| 958 |
+
res = ctx._jacobi_theta2a(z, q)
|
| 959 |
+
else:
|
| 960 |
+
res = ctx._jacobi_theta2(z, q)
|
| 961 |
+
elif n == 3:
|
| 962 |
+
if ctx._im(z):
|
| 963 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 964 |
+
ctx.dps += extra2
|
| 965 |
+
res = ctx._jacobi_theta3(z, q)
|
| 966 |
+
else:
|
| 967 |
+
ctx.dps += 10
|
| 968 |
+
res = ctx._jacobi_theta3a(z, q)
|
| 969 |
+
else:
|
| 970 |
+
res = ctx._jacobi_theta3(z, q)
|
| 971 |
+
elif n == 4:
|
| 972 |
+
if ctx._im(z):
|
| 973 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 974 |
+
ctx.dps += extra2
|
| 975 |
+
res = ctx._jacobi_theta3(z, -q)
|
| 976 |
+
else:
|
| 977 |
+
ctx.dps += 10
|
| 978 |
+
res = ctx._jacobi_theta3a(z, -q)
|
| 979 |
+
else:
|
| 980 |
+
res = ctx._jacobi_theta3(z, -q)
|
| 981 |
+
else:
|
| 982 |
+
raise ValueError
|
| 983 |
+
finally:
|
| 984 |
+
ctx.prec = prec0
|
| 985 |
+
return res
|
| 986 |
+
|
| 987 |
+
@defun
|
| 988 |
+
def _djtheta(ctx, n, z, q, derivative=1):
|
| 989 |
+
z = ctx.convert(z)
|
| 990 |
+
q = ctx.convert(q)
|
| 991 |
+
nd = int(derivative)
|
| 992 |
+
|
| 993 |
+
if abs(q) > ctx.THETA_Q_LIM:
|
| 994 |
+
raise ValueError('abs(q) > THETA_Q_LIM = %f' % ctx.THETA_Q_LIM)
|
| 995 |
+
extra = 10 + ctx.prec * nd // 10
|
| 996 |
+
if z:
|
| 997 |
+
M = ctx.mag(z)
|
| 998 |
+
if M > 5 or (n != 1 and M < -5):
|
| 999 |
+
extra += 2*abs(M)
|
| 1000 |
+
cz = 0.5
|
| 1001 |
+
extra2 = 50
|
| 1002 |
+
prec0 = ctx.prec
|
| 1003 |
+
try:
|
| 1004 |
+
ctx.prec += extra
|
| 1005 |
+
if n == 1:
|
| 1006 |
+
if ctx._im(z):
|
| 1007 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 1008 |
+
ctx.dps += extra2
|
| 1009 |
+
res = ctx._djacobi_theta2(z - ctx.pi/2, q, nd)
|
| 1010 |
+
else:
|
| 1011 |
+
ctx.dps += 10
|
| 1012 |
+
res = ctx._djacobi_theta2a(z - ctx.pi/2, q, nd)
|
| 1013 |
+
else:
|
| 1014 |
+
res = ctx._djacobi_theta2(z - ctx.pi/2, q, nd)
|
| 1015 |
+
elif n == 2:
|
| 1016 |
+
if ctx._im(z):
|
| 1017 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 1018 |
+
ctx.dps += extra2
|
| 1019 |
+
res = ctx._djacobi_theta2(z, q, nd)
|
| 1020 |
+
else:
|
| 1021 |
+
ctx.dps += 10
|
| 1022 |
+
res = ctx._djacobi_theta2a(z, q, nd)
|
| 1023 |
+
else:
|
| 1024 |
+
res = ctx._djacobi_theta2(z, q, nd)
|
| 1025 |
+
elif n == 3:
|
| 1026 |
+
if ctx._im(z):
|
| 1027 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 1028 |
+
ctx.dps += extra2
|
| 1029 |
+
res = ctx._djacobi_theta3(z, q, nd)
|
| 1030 |
+
else:
|
| 1031 |
+
ctx.dps += 10
|
| 1032 |
+
res = ctx._djacobi_theta3a(z, q, nd)
|
| 1033 |
+
else:
|
| 1034 |
+
res = ctx._djacobi_theta3(z, q, nd)
|
| 1035 |
+
elif n == 4:
|
| 1036 |
+
if ctx._im(z):
|
| 1037 |
+
if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
|
| 1038 |
+
ctx.dps += extra2
|
| 1039 |
+
res = ctx._djacobi_theta3(z, -q, nd)
|
| 1040 |
+
else:
|
| 1041 |
+
ctx.dps += 10
|
| 1042 |
+
res = ctx._djacobi_theta3a(z, -q, nd)
|
| 1043 |
+
else:
|
| 1044 |
+
res = ctx._djacobi_theta3(z, -q, nd)
|
| 1045 |
+
else:
|
| 1046 |
+
raise ValueError
|
| 1047 |
+
finally:
|
| 1048 |
+
ctx.prec = prec0
|
| 1049 |
+
return +res
|
.venv/lib/python3.11/site-packages/mpmath/functions/zeta.py
ADDED
|
@@ -0,0 +1,1154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import print_function
|
| 2 |
+
|
| 3 |
+
from ..libmp.backend import xrange
|
| 4 |
+
from .functions import defun, defun_wrapped, defun_static
|
| 5 |
+
|
| 6 |
+
@defun
|
| 7 |
+
def stieltjes(ctx, n, a=1):
|
| 8 |
+
n = ctx.convert(n)
|
| 9 |
+
a = ctx.convert(a)
|
| 10 |
+
if n < 0:
|
| 11 |
+
return ctx.bad_domain("Stieltjes constants defined for n >= 0")
|
| 12 |
+
if hasattr(ctx, "stieltjes_cache"):
|
| 13 |
+
stieltjes_cache = ctx.stieltjes_cache
|
| 14 |
+
else:
|
| 15 |
+
stieltjes_cache = ctx.stieltjes_cache = {}
|
| 16 |
+
if a == 1:
|
| 17 |
+
if n == 0:
|
| 18 |
+
return +ctx.euler
|
| 19 |
+
if n in stieltjes_cache:
|
| 20 |
+
prec, s = stieltjes_cache[n]
|
| 21 |
+
if prec >= ctx.prec:
|
| 22 |
+
return +s
|
| 23 |
+
mag = 1
|
| 24 |
+
def f(x):
|
| 25 |
+
xa = x/a
|
| 26 |
+
v = (xa-ctx.j)*ctx.ln(a-ctx.j*x)**n/(1+xa**2)/(ctx.exp(2*ctx.pi*x)-1)
|
| 27 |
+
return ctx._re(v) / mag
|
| 28 |
+
orig = ctx.prec
|
| 29 |
+
try:
|
| 30 |
+
# Normalize integrand by approx. magnitude to
|
| 31 |
+
# speed up quadrature (which uses absolute error)
|
| 32 |
+
if n > 50:
|
| 33 |
+
ctx.prec = 20
|
| 34 |
+
mag = ctx.quad(f, [0,ctx.inf], maxdegree=3)
|
| 35 |
+
ctx.prec = orig + 10 + int(n**0.5)
|
| 36 |
+
s = ctx.quad(f, [0,ctx.inf], maxdegree=20)
|
| 37 |
+
v = ctx.ln(a)**n/(2*a) - ctx.ln(a)**(n+1)/(n+1) + 2*s/a*mag
|
| 38 |
+
finally:
|
| 39 |
+
ctx.prec = orig
|
| 40 |
+
if a == 1 and ctx.isint(n):
|
| 41 |
+
stieltjes_cache[n] = (ctx.prec, v)
|
| 42 |
+
return +v
|
| 43 |
+
|
| 44 |
+
@defun_wrapped
|
| 45 |
+
def siegeltheta(ctx, t, derivative=0):
|
| 46 |
+
d = int(derivative)
|
| 47 |
+
if (t == ctx.inf or t == ctx.ninf):
|
| 48 |
+
if d < 2:
|
| 49 |
+
if t == ctx.ninf and d == 0:
|
| 50 |
+
return ctx.ninf
|
| 51 |
+
return ctx.inf
|
| 52 |
+
else:
|
| 53 |
+
return ctx.zero
|
| 54 |
+
if d == 0:
|
| 55 |
+
if ctx._im(t):
|
| 56 |
+
# XXX: cancellation occurs
|
| 57 |
+
a = ctx.loggamma(0.25+0.5j*t)
|
| 58 |
+
b = ctx.loggamma(0.25-0.5j*t)
|
| 59 |
+
return -ctx.ln(ctx.pi)/2*t - 0.5j*(a-b)
|
| 60 |
+
else:
|
| 61 |
+
if ctx.isinf(t):
|
| 62 |
+
return t
|
| 63 |
+
return ctx._im(ctx.loggamma(0.25+0.5j*t)) - ctx.ln(ctx.pi)/2*t
|
| 64 |
+
if d > 0:
|
| 65 |
+
a = (-0.5j)**(d-1)*ctx.polygamma(d-1, 0.25-0.5j*t)
|
| 66 |
+
b = (0.5j)**(d-1)*ctx.polygamma(d-1, 0.25+0.5j*t)
|
| 67 |
+
if ctx._im(t):
|
| 68 |
+
if d == 1:
|
| 69 |
+
return -0.5*ctx.log(ctx.pi)+0.25*(a+b)
|
| 70 |
+
else:
|
| 71 |
+
return 0.25*(a+b)
|
| 72 |
+
else:
|
| 73 |
+
if d == 1:
|
| 74 |
+
return ctx._re(-0.5*ctx.log(ctx.pi)+0.25*(a+b))
|
| 75 |
+
else:
|
| 76 |
+
return ctx._re(0.25*(a+b))
|
| 77 |
+
|
| 78 |
+
@defun_wrapped
|
| 79 |
+
def grampoint(ctx, n):
|
| 80 |
+
# asymptotic expansion, from
|
| 81 |
+
# http://mathworld.wolfram.com/GramPoint.html
|
| 82 |
+
g = 2*ctx.pi*ctx.exp(1+ctx.lambertw((8*n+1)/(8*ctx.e)))
|
| 83 |
+
return ctx.findroot(lambda t: ctx.siegeltheta(t)-ctx.pi*n, g)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
@defun_wrapped
|
| 87 |
+
def siegelz(ctx, t, **kwargs):
|
| 88 |
+
d = int(kwargs.get("derivative", 0))
|
| 89 |
+
t = ctx.convert(t)
|
| 90 |
+
t1 = ctx._re(t)
|
| 91 |
+
t2 = ctx._im(t)
|
| 92 |
+
prec = ctx.prec
|
| 93 |
+
try:
|
| 94 |
+
if abs(t1) > 500*prec and t2**2 < t1:
|
| 95 |
+
v = ctx.rs_z(t, d)
|
| 96 |
+
if ctx._is_real_type(t):
|
| 97 |
+
return ctx._re(v)
|
| 98 |
+
return v
|
| 99 |
+
except NotImplementedError:
|
| 100 |
+
pass
|
| 101 |
+
ctx.prec += 21
|
| 102 |
+
e1 = ctx.expj(ctx.siegeltheta(t))
|
| 103 |
+
z = ctx.zeta(0.5+ctx.j*t)
|
| 104 |
+
if d == 0:
|
| 105 |
+
v = e1*z
|
| 106 |
+
ctx.prec=prec
|
| 107 |
+
if ctx._is_real_type(t):
|
| 108 |
+
return ctx._re(v)
|
| 109 |
+
return +v
|
| 110 |
+
z1 = ctx.zeta(0.5+ctx.j*t, derivative=1)
|
| 111 |
+
theta1 = ctx.siegeltheta(t, derivative=1)
|
| 112 |
+
if d == 1:
|
| 113 |
+
v = ctx.j*e1*(z1+z*theta1)
|
| 114 |
+
ctx.prec=prec
|
| 115 |
+
if ctx._is_real_type(t):
|
| 116 |
+
return ctx._re(v)
|
| 117 |
+
return +v
|
| 118 |
+
z2 = ctx.zeta(0.5+ctx.j*t, derivative=2)
|
| 119 |
+
theta2 = ctx.siegeltheta(t, derivative=2)
|
| 120 |
+
comb1 = theta1**2-ctx.j*theta2
|
| 121 |
+
if d == 2:
|
| 122 |
+
def terms():
|
| 123 |
+
return [2*z1*theta1, z2, z*comb1]
|
| 124 |
+
v = ctx.sum_accurately(terms, 1)
|
| 125 |
+
v = -e1*v
|
| 126 |
+
ctx.prec = prec
|
| 127 |
+
if ctx._is_real_type(t):
|
| 128 |
+
return ctx._re(v)
|
| 129 |
+
return +v
|
| 130 |
+
ctx.prec += 10
|
| 131 |
+
z3 = ctx.zeta(0.5+ctx.j*t, derivative=3)
|
| 132 |
+
theta3 = ctx.siegeltheta(t, derivative=3)
|
| 133 |
+
comb2 = theta1**3-3*ctx.j*theta1*theta2-theta3
|
| 134 |
+
if d == 3:
|
| 135 |
+
def terms():
|
| 136 |
+
return [3*theta1*z2, 3*z1*comb1, z3+z*comb2]
|
| 137 |
+
v = ctx.sum_accurately(terms, 1)
|
| 138 |
+
v = -ctx.j*e1*v
|
| 139 |
+
ctx.prec = prec
|
| 140 |
+
if ctx._is_real_type(t):
|
| 141 |
+
return ctx._re(v)
|
| 142 |
+
return +v
|
| 143 |
+
z4 = ctx.zeta(0.5+ctx.j*t, derivative=4)
|
| 144 |
+
theta4 = ctx.siegeltheta(t, derivative=4)
|
| 145 |
+
def terms():
|
| 146 |
+
return [theta1**4, -6*ctx.j*theta1**2*theta2, -3*theta2**2,
|
| 147 |
+
-4*theta1*theta3, ctx.j*theta4]
|
| 148 |
+
comb3 = ctx.sum_accurately(terms, 1)
|
| 149 |
+
if d == 4:
|
| 150 |
+
def terms():
|
| 151 |
+
return [6*theta1**2*z2, -6*ctx.j*z2*theta2, 4*theta1*z3,
|
| 152 |
+
4*z1*comb2, z4, z*comb3]
|
| 153 |
+
v = ctx.sum_accurately(terms, 1)
|
| 154 |
+
v = e1*v
|
| 155 |
+
ctx.prec = prec
|
| 156 |
+
if ctx._is_real_type(t):
|
| 157 |
+
return ctx._re(v)
|
| 158 |
+
return +v
|
| 159 |
+
if d > 4:
|
| 160 |
+
h = lambda x: ctx.siegelz(x, derivative=4)
|
| 161 |
+
return ctx.diff(h, t, n=d-4)
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
_zeta_zeros = [
|
| 165 |
+
14.134725142,21.022039639,25.010857580,30.424876126,32.935061588,
|
| 166 |
+
37.586178159,40.918719012,43.327073281,48.005150881,49.773832478,
|
| 167 |
+
52.970321478,56.446247697,59.347044003,60.831778525,65.112544048,
|
| 168 |
+
67.079810529,69.546401711,72.067157674,75.704690699,77.144840069,
|
| 169 |
+
79.337375020,82.910380854,84.735492981,87.425274613,88.809111208,
|
| 170 |
+
92.491899271,94.651344041,95.870634228,98.831194218,101.317851006,
|
| 171 |
+
103.725538040,105.446623052,107.168611184,111.029535543,111.874659177,
|
| 172 |
+
114.320220915,116.226680321,118.790782866,121.370125002,122.946829294,
|
| 173 |
+
124.256818554,127.516683880,129.578704200,131.087688531,133.497737203,
|
| 174 |
+
134.756509753,138.116042055,139.736208952,141.123707404,143.111845808,
|
| 175 |
+
146.000982487,147.422765343,150.053520421,150.925257612,153.024693811,
|
| 176 |
+
156.112909294,157.597591818,158.849988171,161.188964138,163.030709687,
|
| 177 |
+
165.537069188,167.184439978,169.094515416,169.911976479,173.411536520,
|
| 178 |
+
174.754191523,176.441434298,178.377407776,179.916484020,182.207078484,
|
| 179 |
+
184.874467848,185.598783678,187.228922584,189.416158656,192.026656361,
|
| 180 |
+
193.079726604,195.265396680,196.876481841,198.015309676,201.264751944,
|
| 181 |
+
202.493594514,204.189671803,205.394697202,207.906258888,209.576509717,
|
| 182 |
+
211.690862595,213.347919360,214.547044783,216.169538508,219.067596349,
|
| 183 |
+
220.714918839,221.430705555,224.007000255,224.983324670,227.421444280,
|
| 184 |
+
229.337413306,231.250188700,231.987235253,233.693404179,236.524229666,
|
| 185 |
+
]
|
| 186 |
+
|
| 187 |
+
def _load_zeta_zeros(url):
|
| 188 |
+
import urllib
|
| 189 |
+
d = urllib.urlopen(url)
|
| 190 |
+
L = [float(x) for x in d.readlines()]
|
| 191 |
+
# Sanity check
|
| 192 |
+
assert round(L[0]) == 14
|
| 193 |
+
_zeta_zeros[:] = L
|
| 194 |
+
|
| 195 |
+
@defun
|
| 196 |
+
def oldzetazero(ctx, n, url='http://www.dtc.umn.edu/~odlyzko/zeta_tables/zeros1'):
|
| 197 |
+
n = int(n)
|
| 198 |
+
if n < 0:
|
| 199 |
+
return ctx.zetazero(-n).conjugate()
|
| 200 |
+
if n == 0:
|
| 201 |
+
raise ValueError("n must be nonzero")
|
| 202 |
+
if n > len(_zeta_zeros) and n <= 100000:
|
| 203 |
+
_load_zeta_zeros(url)
|
| 204 |
+
if n > len(_zeta_zeros):
|
| 205 |
+
raise NotImplementedError("n too large for zetazeros")
|
| 206 |
+
return ctx.mpc(0.5, ctx.findroot(ctx.siegelz, _zeta_zeros[n-1]))
|
| 207 |
+
|
| 208 |
+
@defun_wrapped
|
| 209 |
+
def riemannr(ctx, x):
|
| 210 |
+
if x == 0:
|
| 211 |
+
return ctx.zero
|
| 212 |
+
# Check if a simple asymptotic estimate is accurate enough
|
| 213 |
+
if abs(x) > 1000:
|
| 214 |
+
a = ctx.li(x)
|
| 215 |
+
b = 0.5*ctx.li(ctx.sqrt(x))
|
| 216 |
+
if abs(b) < abs(a)*ctx.eps:
|
| 217 |
+
return a
|
| 218 |
+
if abs(x) < 0.01:
|
| 219 |
+
# XXX
|
| 220 |
+
ctx.prec += int(-ctx.log(abs(x),2))
|
| 221 |
+
# Sum Gram's series
|
| 222 |
+
s = t = ctx.one
|
| 223 |
+
u = ctx.ln(x)
|
| 224 |
+
k = 1
|
| 225 |
+
while abs(t) > abs(s)*ctx.eps:
|
| 226 |
+
t = t * u / k
|
| 227 |
+
s += t / (k * ctx._zeta_int(k+1))
|
| 228 |
+
k += 1
|
| 229 |
+
return s
|
| 230 |
+
|
| 231 |
+
@defun_static
|
| 232 |
+
def primepi(ctx, x):
|
| 233 |
+
x = int(x)
|
| 234 |
+
if x < 2:
|
| 235 |
+
return 0
|
| 236 |
+
return len(ctx.list_primes(x))
|
| 237 |
+
|
| 238 |
+
# TODO: fix the interface wrt contexts
|
| 239 |
+
@defun_wrapped
|
| 240 |
+
def primepi2(ctx, x):
|
| 241 |
+
x = int(x)
|
| 242 |
+
if x < 2:
|
| 243 |
+
return ctx._iv.zero
|
| 244 |
+
if x < 2657:
|
| 245 |
+
return ctx._iv.mpf(ctx.primepi(x))
|
| 246 |
+
mid = ctx.li(x)
|
| 247 |
+
# Schoenfeld's estimate for x >= 2657, assuming RH
|
| 248 |
+
err = ctx.sqrt(x,rounding='u')*ctx.ln(x,rounding='u')/8/ctx.pi(rounding='d')
|
| 249 |
+
a = ctx.floor((ctx._iv.mpf(mid)-err).a, rounding='d')
|
| 250 |
+
b = ctx.ceil((ctx._iv.mpf(mid)+err).b, rounding='u')
|
| 251 |
+
return ctx._iv.mpf([a,b])
|
| 252 |
+
|
| 253 |
+
@defun_wrapped
|
| 254 |
+
def primezeta(ctx, s):
|
| 255 |
+
if ctx.isnan(s):
|
| 256 |
+
return s
|
| 257 |
+
if ctx.re(s) <= 0:
|
| 258 |
+
raise ValueError("prime zeta function defined only for re(s) > 0")
|
| 259 |
+
if s == 1:
|
| 260 |
+
return ctx.inf
|
| 261 |
+
if s == 0.5:
|
| 262 |
+
return ctx.mpc(ctx.ninf, ctx.pi)
|
| 263 |
+
r = ctx.re(s)
|
| 264 |
+
if r > ctx.prec:
|
| 265 |
+
return 0.5**s
|
| 266 |
+
else:
|
| 267 |
+
wp = ctx.prec + int(r)
|
| 268 |
+
def terms():
|
| 269 |
+
orig = ctx.prec
|
| 270 |
+
# zeta ~ 1+eps; need to set precision
|
| 271 |
+
# to get logarithm accurately
|
| 272 |
+
k = 0
|
| 273 |
+
while 1:
|
| 274 |
+
k += 1
|
| 275 |
+
u = ctx.moebius(k)
|
| 276 |
+
if not u:
|
| 277 |
+
continue
|
| 278 |
+
ctx.prec = wp
|
| 279 |
+
t = u*ctx.ln(ctx.zeta(k*s))/k
|
| 280 |
+
if not t:
|
| 281 |
+
return
|
| 282 |
+
#print ctx.prec, ctx.nstr(t)
|
| 283 |
+
ctx.prec = orig
|
| 284 |
+
yield t
|
| 285 |
+
return ctx.sum_accurately(terms)
|
| 286 |
+
|
| 287 |
+
# TODO: for bernpoly and eulerpoly, ensure that all exact zeros are covered
|
| 288 |
+
|
| 289 |
+
@defun_wrapped
|
| 290 |
+
def bernpoly(ctx, n, z):
|
| 291 |
+
# Slow implementation:
|
| 292 |
+
#return sum(ctx.binomial(n,k)*ctx.bernoulli(k)*z**(n-k) for k in xrange(0,n+1))
|
| 293 |
+
n = int(n)
|
| 294 |
+
if n < 0:
|
| 295 |
+
raise ValueError("Bernoulli polynomials only defined for n >= 0")
|
| 296 |
+
if z == 0 or (z == 1 and n > 1):
|
| 297 |
+
return ctx.bernoulli(n)
|
| 298 |
+
if z == 0.5:
|
| 299 |
+
return (ctx.ldexp(1,1-n)-1)*ctx.bernoulli(n)
|
| 300 |
+
if n <= 3:
|
| 301 |
+
if n == 0: return z ** 0
|
| 302 |
+
if n == 1: return z - 0.5
|
| 303 |
+
if n == 2: return (6*z*(z-1)+1)/6
|
| 304 |
+
if n == 3: return z*(z*(z-1.5)+0.5)
|
| 305 |
+
if ctx.isinf(z):
|
| 306 |
+
return z ** n
|
| 307 |
+
if ctx.isnan(z):
|
| 308 |
+
return z
|
| 309 |
+
if abs(z) > 2:
|
| 310 |
+
def terms():
|
| 311 |
+
t = ctx.one
|
| 312 |
+
yield t
|
| 313 |
+
r = ctx.one/z
|
| 314 |
+
k = 1
|
| 315 |
+
while k <= n:
|
| 316 |
+
t = t*(n+1-k)/k*r
|
| 317 |
+
if not (k > 2 and k & 1):
|
| 318 |
+
yield t*ctx.bernoulli(k)
|
| 319 |
+
k += 1
|
| 320 |
+
return ctx.sum_accurately(terms) * z**n
|
| 321 |
+
else:
|
| 322 |
+
def terms():
|
| 323 |
+
yield ctx.bernoulli(n)
|
| 324 |
+
t = ctx.one
|
| 325 |
+
k = 1
|
| 326 |
+
while k <= n:
|
| 327 |
+
t = t*(n+1-k)/k * z
|
| 328 |
+
m = n-k
|
| 329 |
+
if not (m > 2 and m & 1):
|
| 330 |
+
yield t*ctx.bernoulli(m)
|
| 331 |
+
k += 1
|
| 332 |
+
return ctx.sum_accurately(terms)
|
| 333 |
+
|
| 334 |
+
@defun_wrapped
|
| 335 |
+
def eulerpoly(ctx, n, z):
|
| 336 |
+
n = int(n)
|
| 337 |
+
if n < 0:
|
| 338 |
+
raise ValueError("Euler polynomials only defined for n >= 0")
|
| 339 |
+
if n <= 2:
|
| 340 |
+
if n == 0: return z ** 0
|
| 341 |
+
if n == 1: return z - 0.5
|
| 342 |
+
if n == 2: return z*(z-1)
|
| 343 |
+
if ctx.isinf(z):
|
| 344 |
+
return z**n
|
| 345 |
+
if ctx.isnan(z):
|
| 346 |
+
return z
|
| 347 |
+
m = n+1
|
| 348 |
+
if z == 0:
|
| 349 |
+
return -2*(ctx.ldexp(1,m)-1)*ctx.bernoulli(m)/m * z**0
|
| 350 |
+
if z == 1:
|
| 351 |
+
return 2*(ctx.ldexp(1,m)-1)*ctx.bernoulli(m)/m * z**0
|
| 352 |
+
if z == 0.5:
|
| 353 |
+
if n % 2:
|
| 354 |
+
return ctx.zero
|
| 355 |
+
# Use exact code for Euler numbers
|
| 356 |
+
if n < 100 or n*ctx.mag(0.46839865*n) < ctx.prec*0.25:
|
| 357 |
+
return ctx.ldexp(ctx._eulernum(n), -n)
|
| 358 |
+
# http://functions.wolfram.com/Polynomials/EulerE2/06/01/02/01/0002/
|
| 359 |
+
def terms():
|
| 360 |
+
t = ctx.one
|
| 361 |
+
k = 0
|
| 362 |
+
w = ctx.ldexp(1,n+2)
|
| 363 |
+
while 1:
|
| 364 |
+
v = n-k+1
|
| 365 |
+
if not (v > 2 and v & 1):
|
| 366 |
+
yield (2-w)*ctx.bernoulli(v)*t
|
| 367 |
+
k += 1
|
| 368 |
+
if k > n:
|
| 369 |
+
break
|
| 370 |
+
t = t*z*(n-k+2)/k
|
| 371 |
+
w *= 0.5
|
| 372 |
+
return ctx.sum_accurately(terms) / m
|
| 373 |
+
|
| 374 |
+
@defun
|
| 375 |
+
def eulernum(ctx, n, exact=False):
|
| 376 |
+
n = int(n)
|
| 377 |
+
if exact:
|
| 378 |
+
return int(ctx._eulernum(n))
|
| 379 |
+
if n < 100:
|
| 380 |
+
return ctx.mpf(ctx._eulernum(n))
|
| 381 |
+
if n % 2:
|
| 382 |
+
return ctx.zero
|
| 383 |
+
return ctx.ldexp(ctx.eulerpoly(n,0.5), n)
|
| 384 |
+
|
| 385 |
+
# TODO: this should be implemented low-level
|
| 386 |
+
def polylog_series(ctx, s, z):
|
| 387 |
+
tol = +ctx.eps
|
| 388 |
+
l = ctx.zero
|
| 389 |
+
k = 1
|
| 390 |
+
zk = z
|
| 391 |
+
while 1:
|
| 392 |
+
term = zk / k**s
|
| 393 |
+
l += term
|
| 394 |
+
if abs(term) < tol:
|
| 395 |
+
break
|
| 396 |
+
zk *= z
|
| 397 |
+
k += 1
|
| 398 |
+
return l
|
| 399 |
+
|
| 400 |
+
def polylog_continuation(ctx, n, z):
|
| 401 |
+
if n < 0:
|
| 402 |
+
return z*0
|
| 403 |
+
twopij = 2j * ctx.pi
|
| 404 |
+
a = -twopij**n/ctx.fac(n) * ctx.bernpoly(n, ctx.ln(z)/twopij)
|
| 405 |
+
if ctx._is_real_type(z) and z < 0:
|
| 406 |
+
a = ctx._re(a)
|
| 407 |
+
if ctx._im(z) < 0 or (ctx._im(z) == 0 and ctx._re(z) >= 1):
|
| 408 |
+
a -= twopij*ctx.ln(z)**(n-1)/ctx.fac(n-1)
|
| 409 |
+
return a
|
| 410 |
+
|
| 411 |
+
def polylog_unitcircle(ctx, n, z):
|
| 412 |
+
tol = +ctx.eps
|
| 413 |
+
if n > 1:
|
| 414 |
+
l = ctx.zero
|
| 415 |
+
logz = ctx.ln(z)
|
| 416 |
+
logmz = ctx.one
|
| 417 |
+
m = 0
|
| 418 |
+
while 1:
|
| 419 |
+
if (n-m) != 1:
|
| 420 |
+
term = ctx.zeta(n-m) * logmz / ctx.fac(m)
|
| 421 |
+
if term and abs(term) < tol:
|
| 422 |
+
break
|
| 423 |
+
l += term
|
| 424 |
+
logmz *= logz
|
| 425 |
+
m += 1
|
| 426 |
+
l += ctx.ln(z)**(n-1)/ctx.fac(n-1)*(ctx.harmonic(n-1)-ctx.ln(-ctx.ln(z)))
|
| 427 |
+
elif n < 1: # else
|
| 428 |
+
l = ctx.fac(-n)*(-ctx.ln(z))**(n-1)
|
| 429 |
+
logz = ctx.ln(z)
|
| 430 |
+
logkz = ctx.one
|
| 431 |
+
k = 0
|
| 432 |
+
while 1:
|
| 433 |
+
b = ctx.bernoulli(k-n+1)
|
| 434 |
+
if b:
|
| 435 |
+
term = b*logkz/(ctx.fac(k)*(k-n+1))
|
| 436 |
+
if abs(term) < tol:
|
| 437 |
+
break
|
| 438 |
+
l -= term
|
| 439 |
+
logkz *= logz
|
| 440 |
+
k += 1
|
| 441 |
+
else:
|
| 442 |
+
raise ValueError
|
| 443 |
+
if ctx._is_real_type(z) and z < 0:
|
| 444 |
+
l = ctx._re(l)
|
| 445 |
+
return l
|
| 446 |
+
|
| 447 |
+
def polylog_general(ctx, s, z):
|
| 448 |
+
v = ctx.zero
|
| 449 |
+
u = ctx.ln(z)
|
| 450 |
+
if not abs(u) < 5: # theoretically |u| < 2*pi
|
| 451 |
+
j = ctx.j
|
| 452 |
+
v = 1-s
|
| 453 |
+
y = ctx.ln(-z)/(2*ctx.pi*j)
|
| 454 |
+
return ctx.gamma(v)*(j**v*ctx.zeta(v,0.5+y) + j**-v*ctx.zeta(v,0.5-y))/(2*ctx.pi)**v
|
| 455 |
+
t = 1
|
| 456 |
+
k = 0
|
| 457 |
+
while 1:
|
| 458 |
+
term = ctx.zeta(s-k) * t
|
| 459 |
+
if abs(term) < ctx.eps:
|
| 460 |
+
break
|
| 461 |
+
v += term
|
| 462 |
+
k += 1
|
| 463 |
+
t *= u
|
| 464 |
+
t /= k
|
| 465 |
+
return ctx.gamma(1-s)*(-u)**(s-1) + v
|
| 466 |
+
|
| 467 |
+
@defun_wrapped
|
| 468 |
+
def polylog(ctx, s, z):
|
| 469 |
+
s = ctx.convert(s)
|
| 470 |
+
z = ctx.convert(z)
|
| 471 |
+
if z == 1:
|
| 472 |
+
return ctx.zeta(s)
|
| 473 |
+
if z == -1:
|
| 474 |
+
return -ctx.altzeta(s)
|
| 475 |
+
if s == 0:
|
| 476 |
+
return z/(1-z)
|
| 477 |
+
if s == 1:
|
| 478 |
+
return -ctx.ln(1-z)
|
| 479 |
+
if s == -1:
|
| 480 |
+
return z/(1-z)**2
|
| 481 |
+
if abs(z) <= 0.75 or (not ctx.isint(s) and abs(z) < 0.9):
|
| 482 |
+
return polylog_series(ctx, s, z)
|
| 483 |
+
if abs(z) >= 1.4 and ctx.isint(s):
|
| 484 |
+
return (-1)**(s+1)*polylog_series(ctx, s, 1/z) + polylog_continuation(ctx, int(ctx.re(s)), z)
|
| 485 |
+
if ctx.isint(s):
|
| 486 |
+
return polylog_unitcircle(ctx, int(ctx.re(s)), z)
|
| 487 |
+
return polylog_general(ctx, s, z)
|
| 488 |
+
|
| 489 |
+
@defun_wrapped
|
| 490 |
+
def clsin(ctx, s, z, pi=False):
|
| 491 |
+
if ctx.isint(s) and s < 0 and int(s) % 2 == 1:
|
| 492 |
+
return z*0
|
| 493 |
+
if pi:
|
| 494 |
+
a = ctx.expjpi(z)
|
| 495 |
+
else:
|
| 496 |
+
a = ctx.expj(z)
|
| 497 |
+
if ctx._is_real_type(z) and ctx._is_real_type(s):
|
| 498 |
+
return ctx.im(ctx.polylog(s,a))
|
| 499 |
+
b = 1/a
|
| 500 |
+
return (-0.5j)*(ctx.polylog(s,a) - ctx.polylog(s,b))
|
| 501 |
+
|
| 502 |
+
@defun_wrapped
|
| 503 |
+
def clcos(ctx, s, z, pi=False):
|
| 504 |
+
if ctx.isint(s) and s < 0 and int(s) % 2 == 0:
|
| 505 |
+
return z*0
|
| 506 |
+
if pi:
|
| 507 |
+
a = ctx.expjpi(z)
|
| 508 |
+
else:
|
| 509 |
+
a = ctx.expj(z)
|
| 510 |
+
if ctx._is_real_type(z) and ctx._is_real_type(s):
|
| 511 |
+
return ctx.re(ctx.polylog(s,a))
|
| 512 |
+
b = 1/a
|
| 513 |
+
return 0.5*(ctx.polylog(s,a) + ctx.polylog(s,b))
|
| 514 |
+
|
| 515 |
+
@defun
|
| 516 |
+
def altzeta(ctx, s, **kwargs):
|
| 517 |
+
try:
|
| 518 |
+
return ctx._altzeta(s, **kwargs)
|
| 519 |
+
except NotImplementedError:
|
| 520 |
+
return ctx._altzeta_generic(s)
|
| 521 |
+
|
| 522 |
+
@defun_wrapped
|
| 523 |
+
def _altzeta_generic(ctx, s):
|
| 524 |
+
if s == 1:
|
| 525 |
+
return ctx.ln2 + 0*s
|
| 526 |
+
return -ctx.powm1(2, 1-s) * ctx.zeta(s)
|
| 527 |
+
|
| 528 |
+
@defun
|
| 529 |
+
def zeta(ctx, s, a=1, derivative=0, method=None, **kwargs):
|
| 530 |
+
d = int(derivative)
|
| 531 |
+
if a == 1 and not (d or method):
|
| 532 |
+
try:
|
| 533 |
+
return ctx._zeta(s, **kwargs)
|
| 534 |
+
except NotImplementedError:
|
| 535 |
+
pass
|
| 536 |
+
s = ctx.convert(s)
|
| 537 |
+
prec = ctx.prec
|
| 538 |
+
method = kwargs.get('method')
|
| 539 |
+
verbose = kwargs.get('verbose')
|
| 540 |
+
if (not s) and (not derivative):
|
| 541 |
+
return ctx.mpf(0.5) - ctx._convert_param(a)[0]
|
| 542 |
+
if a == 1 and method != 'euler-maclaurin':
|
| 543 |
+
im = abs(ctx._im(s))
|
| 544 |
+
re = abs(ctx._re(s))
|
| 545 |
+
#if (im < prec or method == 'borwein') and not derivative:
|
| 546 |
+
# try:
|
| 547 |
+
# if verbose:
|
| 548 |
+
# print "zeta: Attempting to use the Borwein algorithm"
|
| 549 |
+
# return ctx._zeta(s, **kwargs)
|
| 550 |
+
# except NotImplementedError:
|
| 551 |
+
# if verbose:
|
| 552 |
+
# print "zeta: Could not use the Borwein algorithm"
|
| 553 |
+
# pass
|
| 554 |
+
if abs(im) > 500*prec and 10*re < prec and derivative <= 4 or \
|
| 555 |
+
method == 'riemann-siegel':
|
| 556 |
+
try: # py2.4 compatible try block
|
| 557 |
+
try:
|
| 558 |
+
if verbose:
|
| 559 |
+
print("zeta: Attempting to use the Riemann-Siegel algorithm")
|
| 560 |
+
return ctx.rs_zeta(s, derivative, **kwargs)
|
| 561 |
+
except NotImplementedError:
|
| 562 |
+
if verbose:
|
| 563 |
+
print("zeta: Could not use the Riemann-Siegel algorithm")
|
| 564 |
+
pass
|
| 565 |
+
finally:
|
| 566 |
+
ctx.prec = prec
|
| 567 |
+
if s == 1:
|
| 568 |
+
return ctx.inf
|
| 569 |
+
abss = abs(s)
|
| 570 |
+
if abss == ctx.inf:
|
| 571 |
+
if ctx.re(s) == ctx.inf:
|
| 572 |
+
if d == 0:
|
| 573 |
+
return ctx.one
|
| 574 |
+
return ctx.zero
|
| 575 |
+
return s*0
|
| 576 |
+
elif ctx.isnan(abss):
|
| 577 |
+
return 1/s
|
| 578 |
+
if ctx.re(s) > 2*ctx.prec and a == 1 and not derivative:
|
| 579 |
+
return ctx.one + ctx.power(2, -s)
|
| 580 |
+
return +ctx._hurwitz(s, a, d, **kwargs)
|
| 581 |
+
|
| 582 |
+
@defun
|
| 583 |
+
def _hurwitz(ctx, s, a=1, d=0, **kwargs):
|
| 584 |
+
prec = ctx.prec
|
| 585 |
+
verbose = kwargs.get('verbose')
|
| 586 |
+
try:
|
| 587 |
+
extraprec = 10
|
| 588 |
+
ctx.prec += extraprec
|
| 589 |
+
# We strongly want to special-case rational a
|
| 590 |
+
a, atype = ctx._convert_param(a)
|
| 591 |
+
if ctx.re(s) < 0:
|
| 592 |
+
if verbose:
|
| 593 |
+
print("zeta: Attempting reflection formula")
|
| 594 |
+
try:
|
| 595 |
+
return _hurwitz_reflection(ctx, s, a, d, atype)
|
| 596 |
+
except NotImplementedError:
|
| 597 |
+
pass
|
| 598 |
+
if verbose:
|
| 599 |
+
print("zeta: Reflection formula failed")
|
| 600 |
+
if verbose:
|
| 601 |
+
print("zeta: Using the Euler-Maclaurin algorithm")
|
| 602 |
+
while 1:
|
| 603 |
+
ctx.prec = prec + extraprec
|
| 604 |
+
T1, T2 = _hurwitz_em(ctx, s, a, d, prec+10, verbose)
|
| 605 |
+
cancellation = ctx.mag(T1) - ctx.mag(T1+T2)
|
| 606 |
+
if verbose:
|
| 607 |
+
print("Term 1:", T1)
|
| 608 |
+
print("Term 2:", T2)
|
| 609 |
+
print("Cancellation:", cancellation, "bits")
|
| 610 |
+
if cancellation < extraprec:
|
| 611 |
+
return T1 + T2
|
| 612 |
+
else:
|
| 613 |
+
extraprec = max(2*extraprec, min(cancellation + 5, 100*prec))
|
| 614 |
+
if extraprec > kwargs.get('maxprec', 100*prec):
|
| 615 |
+
raise ctx.NoConvergence("zeta: too much cancellation")
|
| 616 |
+
finally:
|
| 617 |
+
ctx.prec = prec
|
| 618 |
+
|
| 619 |
+
def _hurwitz_reflection(ctx, s, a, d, atype):
|
| 620 |
+
# TODO: implement for derivatives
|
| 621 |
+
if d != 0:
|
| 622 |
+
raise NotImplementedError
|
| 623 |
+
res = ctx.re(s)
|
| 624 |
+
negs = -s
|
| 625 |
+
# Integer reflection formula
|
| 626 |
+
if ctx.isnpint(s):
|
| 627 |
+
n = int(res)
|
| 628 |
+
if n <= 0:
|
| 629 |
+
return ctx.bernpoly(1-n, a) / (n-1)
|
| 630 |
+
if not (atype == 'Q' or atype == 'Z'):
|
| 631 |
+
raise NotImplementedError
|
| 632 |
+
t = 1-s
|
| 633 |
+
# We now require a to be standardized
|
| 634 |
+
v = 0
|
| 635 |
+
shift = 0
|
| 636 |
+
b = a
|
| 637 |
+
while ctx.re(b) > 1:
|
| 638 |
+
b -= 1
|
| 639 |
+
v -= b**negs
|
| 640 |
+
shift -= 1
|
| 641 |
+
while ctx.re(b) <= 0:
|
| 642 |
+
v += b**negs
|
| 643 |
+
b += 1
|
| 644 |
+
shift += 1
|
| 645 |
+
# Rational reflection formula
|
| 646 |
+
try:
|
| 647 |
+
p, q = a._mpq_
|
| 648 |
+
except:
|
| 649 |
+
assert a == int(a)
|
| 650 |
+
p = int(a)
|
| 651 |
+
q = 1
|
| 652 |
+
p += shift*q
|
| 653 |
+
assert 1 <= p <= q
|
| 654 |
+
g = ctx.fsum(ctx.cospi(t/2-2*k*b)*ctx._hurwitz(t,(k,q)) \
|
| 655 |
+
for k in range(1,q+1))
|
| 656 |
+
g *= 2*ctx.gamma(t)/(2*ctx.pi*q)**t
|
| 657 |
+
v += g
|
| 658 |
+
return v
|
| 659 |
+
|
| 660 |
+
def _hurwitz_em(ctx, s, a, d, prec, verbose):
|
| 661 |
+
# May not be converted at this point
|
| 662 |
+
a = ctx.convert(a)
|
| 663 |
+
tol = -prec
|
| 664 |
+
# Estimate number of terms for Euler-Maclaurin summation; could be improved
|
| 665 |
+
M1 = 0
|
| 666 |
+
M2 = prec // 3
|
| 667 |
+
N = M2
|
| 668 |
+
lsum = 0
|
| 669 |
+
# This speeds up the recurrence for derivatives
|
| 670 |
+
if ctx.isint(s):
|
| 671 |
+
s = int(ctx._re(s))
|
| 672 |
+
s1 = s-1
|
| 673 |
+
while 1:
|
| 674 |
+
# Truncated L-series
|
| 675 |
+
l = ctx._zetasum(s, M1+a, M2-M1-1, [d])[0][0]
|
| 676 |
+
#if d:
|
| 677 |
+
# l = ctx.fsum((-ctx.ln(n+a))**d * (n+a)**negs for n in range(M1,M2))
|
| 678 |
+
#else:
|
| 679 |
+
# l = ctx.fsum((n+a)**negs for n in range(M1,M2))
|
| 680 |
+
lsum += l
|
| 681 |
+
M2a = M2+a
|
| 682 |
+
logM2a = ctx.ln(M2a)
|
| 683 |
+
logM2ad = logM2a**d
|
| 684 |
+
logs = [logM2ad]
|
| 685 |
+
logr = 1/logM2a
|
| 686 |
+
rM2a = 1/M2a
|
| 687 |
+
M2as = M2a**(-s)
|
| 688 |
+
if d:
|
| 689 |
+
tailsum = ctx.gammainc(d+1, s1*logM2a) / s1**(d+1)
|
| 690 |
+
else:
|
| 691 |
+
tailsum = 1/((s1)*(M2a)**s1)
|
| 692 |
+
tailsum += 0.5 * logM2ad * M2as
|
| 693 |
+
U = [1]
|
| 694 |
+
r = M2as
|
| 695 |
+
fact = 2
|
| 696 |
+
for j in range(1, N+1):
|
| 697 |
+
# TODO: the following could perhaps be tidied a bit
|
| 698 |
+
j2 = 2*j
|
| 699 |
+
if j == 1:
|
| 700 |
+
upds = [1]
|
| 701 |
+
else:
|
| 702 |
+
upds = [j2-2, j2-1]
|
| 703 |
+
for m in upds:
|
| 704 |
+
D = min(m,d+1)
|
| 705 |
+
if m <= d:
|
| 706 |
+
logs.append(logs[-1] * logr)
|
| 707 |
+
Un = [0]*(D+1)
|
| 708 |
+
for i in xrange(D): Un[i] = (1-m-s)*U[i]
|
| 709 |
+
for i in xrange(1,D+1): Un[i] += (d-(i-1))*U[i-1]
|
| 710 |
+
U = Un
|
| 711 |
+
r *= rM2a
|
| 712 |
+
t = ctx.fdot(U, logs) * r * ctx.bernoulli(j2)/(-fact)
|
| 713 |
+
tailsum += t
|
| 714 |
+
if ctx.mag(t) < tol:
|
| 715 |
+
return lsum, (-1)**d * tailsum
|
| 716 |
+
fact *= (j2+1)*(j2+2)
|
| 717 |
+
if verbose:
|
| 718 |
+
print("Sum range:", M1, M2, "term magnitude", ctx.mag(t), "tolerance", tol)
|
| 719 |
+
M1, M2 = M2, M2*2
|
| 720 |
+
if ctx.re(s) < 0:
|
| 721 |
+
N += N//2
|
| 722 |
+
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
@defun
|
| 726 |
+
def _zetasum(ctx, s, a, n, derivatives=[0], reflect=False):
|
| 727 |
+
"""
|
| 728 |
+
Returns [xd0,xd1,...,xdr], [yd0,yd1,...ydr] where
|
| 729 |
+
|
| 730 |
+
xdk = D^k ( 1/a^s + 1/(a+1)^s + ... + 1/(a+n)^s )
|
| 731 |
+
ydk = D^k conj( 1/a^(1-s) + 1/(a+1)^(1-s) + ... + 1/(a+n)^(1-s) )
|
| 732 |
+
|
| 733 |
+
D^k = kth derivative with respect to s, k ranges over the given list of
|
| 734 |
+
derivatives (which should consist of either a single element
|
| 735 |
+
or a range 0,1,...r). If reflect=False, the ydks are not computed.
|
| 736 |
+
"""
|
| 737 |
+
#print "zetasum", s, a, n
|
| 738 |
+
# don't use the fixed-point code if there are large exponentials
|
| 739 |
+
if abs(ctx.re(s)) < 0.5 * ctx.prec:
|
| 740 |
+
try:
|
| 741 |
+
return ctx._zetasum_fast(s, a, n, derivatives, reflect)
|
| 742 |
+
except NotImplementedError:
|
| 743 |
+
pass
|
| 744 |
+
negs = ctx.fneg(s, exact=True)
|
| 745 |
+
have_derivatives = derivatives != [0]
|
| 746 |
+
have_one_derivative = len(derivatives) == 1
|
| 747 |
+
if not reflect:
|
| 748 |
+
if not have_derivatives:
|
| 749 |
+
return [ctx.fsum((a+k)**negs for k in xrange(n+1))], []
|
| 750 |
+
if have_one_derivative:
|
| 751 |
+
d = derivatives[0]
|
| 752 |
+
x = ctx.fsum(ctx.ln(a+k)**d * (a+k)**negs for k in xrange(n+1))
|
| 753 |
+
return [(-1)**d * x], []
|
| 754 |
+
maxd = max(derivatives)
|
| 755 |
+
if not have_one_derivative:
|
| 756 |
+
derivatives = range(maxd+1)
|
| 757 |
+
xs = [ctx.zero for d in derivatives]
|
| 758 |
+
if reflect:
|
| 759 |
+
ys = [ctx.zero for d in derivatives]
|
| 760 |
+
else:
|
| 761 |
+
ys = []
|
| 762 |
+
for k in xrange(n+1):
|
| 763 |
+
w = a + k
|
| 764 |
+
xterm = w ** negs
|
| 765 |
+
if reflect:
|
| 766 |
+
yterm = ctx.conj(ctx.one / (w * xterm))
|
| 767 |
+
if have_derivatives:
|
| 768 |
+
logw = -ctx.ln(w)
|
| 769 |
+
if have_one_derivative:
|
| 770 |
+
logw = logw ** maxd
|
| 771 |
+
xs[0] += xterm * logw
|
| 772 |
+
if reflect:
|
| 773 |
+
ys[0] += yterm * logw
|
| 774 |
+
else:
|
| 775 |
+
t = ctx.one
|
| 776 |
+
for d in derivatives:
|
| 777 |
+
xs[d] += xterm * t
|
| 778 |
+
if reflect:
|
| 779 |
+
ys[d] += yterm * t
|
| 780 |
+
t *= logw
|
| 781 |
+
else:
|
| 782 |
+
xs[0] += xterm
|
| 783 |
+
if reflect:
|
| 784 |
+
ys[0] += yterm
|
| 785 |
+
return xs, ys
|
| 786 |
+
|
| 787 |
+
@defun
|
| 788 |
+
def dirichlet(ctx, s, chi=[1], derivative=0):
|
| 789 |
+
s = ctx.convert(s)
|
| 790 |
+
q = len(chi)
|
| 791 |
+
d = int(derivative)
|
| 792 |
+
if d > 2:
|
| 793 |
+
raise NotImplementedError("arbitrary order derivatives")
|
| 794 |
+
prec = ctx.prec
|
| 795 |
+
try:
|
| 796 |
+
ctx.prec += 10
|
| 797 |
+
if s == 1:
|
| 798 |
+
have_pole = True
|
| 799 |
+
for x in chi:
|
| 800 |
+
if x and x != 1:
|
| 801 |
+
have_pole = False
|
| 802 |
+
h = +ctx.eps
|
| 803 |
+
ctx.prec *= 2*(d+1)
|
| 804 |
+
s += h
|
| 805 |
+
if have_pole:
|
| 806 |
+
return +ctx.inf
|
| 807 |
+
z = ctx.zero
|
| 808 |
+
for p in range(1,q+1):
|
| 809 |
+
if chi[p%q]:
|
| 810 |
+
if d == 1:
|
| 811 |
+
z += chi[p%q] * (ctx.zeta(s, (p,q), 1) - \
|
| 812 |
+
ctx.zeta(s, (p,q))*ctx.log(q))
|
| 813 |
+
else:
|
| 814 |
+
z += chi[p%q] * ctx.zeta(s, (p,q))
|
| 815 |
+
z /= q**s
|
| 816 |
+
finally:
|
| 817 |
+
ctx.prec = prec
|
| 818 |
+
return +z
|
| 819 |
+
|
| 820 |
+
|
| 821 |
+
def secondzeta_main_term(ctx, s, a, **kwargs):
|
| 822 |
+
tol = ctx.eps
|
| 823 |
+
f = lambda n: ctx.gammainc(0.5*s, a*gamm**2, regularized=True)*gamm**(-s)
|
| 824 |
+
totsum = term = ctx.zero
|
| 825 |
+
mg = ctx.inf
|
| 826 |
+
n = 0
|
| 827 |
+
while mg > tol:
|
| 828 |
+
totsum += term
|
| 829 |
+
n += 1
|
| 830 |
+
gamm = ctx.im(ctx.zetazero_memoized(n))
|
| 831 |
+
term = f(n)
|
| 832 |
+
mg = abs(term)
|
| 833 |
+
err = 0
|
| 834 |
+
if kwargs.get("error"):
|
| 835 |
+
sg = ctx.re(s)
|
| 836 |
+
err = 0.5*ctx.pi**(-1)*max(1,sg)*a**(sg-0.5)*ctx.log(gamm/(2*ctx.pi))*\
|
| 837 |
+
ctx.gammainc(-0.5, a*gamm**2)/abs(ctx.gamma(s/2))
|
| 838 |
+
err = abs(err)
|
| 839 |
+
return +totsum, err, n
|
| 840 |
+
|
| 841 |
+
def secondzeta_prime_term(ctx, s, a, **kwargs):
|
| 842 |
+
tol = ctx.eps
|
| 843 |
+
f = lambda n: ctx.gammainc(0.5*(1-s),0.25*ctx.log(n)**2 * a**(-1))*\
|
| 844 |
+
((0.5*ctx.log(n))**(s-1))*ctx.mangoldt(n)/ctx.sqrt(n)/\
|
| 845 |
+
(2*ctx.gamma(0.5*s)*ctx.sqrt(ctx.pi))
|
| 846 |
+
totsum = term = ctx.zero
|
| 847 |
+
mg = ctx.inf
|
| 848 |
+
n = 1
|
| 849 |
+
while mg > tol or n < 9:
|
| 850 |
+
totsum += term
|
| 851 |
+
n += 1
|
| 852 |
+
term = f(n)
|
| 853 |
+
if term == 0:
|
| 854 |
+
mg = ctx.inf
|
| 855 |
+
else:
|
| 856 |
+
mg = abs(term)
|
| 857 |
+
if kwargs.get("error"):
|
| 858 |
+
err = mg
|
| 859 |
+
return +totsum, err, n
|
| 860 |
+
|
| 861 |
+
def secondzeta_exp_term(ctx, s, a):
|
| 862 |
+
if ctx.isint(s) and ctx.re(s) <= 0:
|
| 863 |
+
m = int(round(ctx.re(s)))
|
| 864 |
+
if not m & 1:
|
| 865 |
+
return ctx.mpf('-0.25')**(-m//2)
|
| 866 |
+
tol = ctx.eps
|
| 867 |
+
f = lambda n: (0.25*a)**n/((n+0.5*s)*ctx.fac(n))
|
| 868 |
+
totsum = ctx.zero
|
| 869 |
+
term = f(0)
|
| 870 |
+
mg = ctx.inf
|
| 871 |
+
n = 0
|
| 872 |
+
while mg > tol:
|
| 873 |
+
totsum += term
|
| 874 |
+
n += 1
|
| 875 |
+
term = f(n)
|
| 876 |
+
mg = abs(term)
|
| 877 |
+
v = a**(0.5*s)*totsum/ctx.gamma(0.5*s)
|
| 878 |
+
return v
|
| 879 |
+
|
| 880 |
+
def secondzeta_singular_term(ctx, s, a, **kwargs):
|
| 881 |
+
factor = a**(0.5*(s-1))/(4*ctx.sqrt(ctx.pi)*ctx.gamma(0.5*s))
|
| 882 |
+
extraprec = ctx.mag(factor)
|
| 883 |
+
ctx.prec += extraprec
|
| 884 |
+
factor = a**(0.5*(s-1))/(4*ctx.sqrt(ctx.pi)*ctx.gamma(0.5*s))
|
| 885 |
+
tol = ctx.eps
|
| 886 |
+
f = lambda n: ctx.bernpoly(n,0.75)*(4*ctx.sqrt(a))**n*\
|
| 887 |
+
ctx.gamma(0.5*n)/((s+n-1)*ctx.fac(n))
|
| 888 |
+
totsum = ctx.zero
|
| 889 |
+
mg1 = ctx.inf
|
| 890 |
+
n = 1
|
| 891 |
+
term = f(n)
|
| 892 |
+
mg2 = abs(term)
|
| 893 |
+
while mg2 > tol and mg2 <= mg1:
|
| 894 |
+
totsum += term
|
| 895 |
+
n += 1
|
| 896 |
+
term = f(n)
|
| 897 |
+
totsum += term
|
| 898 |
+
n +=1
|
| 899 |
+
term = f(n)
|
| 900 |
+
mg1 = mg2
|
| 901 |
+
mg2 = abs(term)
|
| 902 |
+
totsum += term
|
| 903 |
+
pole = -2*(s-1)**(-2)+(ctx.euler+ctx.log(16*ctx.pi**2*a))*(s-1)**(-1)
|
| 904 |
+
st = factor*(pole+totsum)
|
| 905 |
+
err = 0
|
| 906 |
+
if kwargs.get("error"):
|
| 907 |
+
if not ((mg2 > tol) and (mg2 <= mg1)):
|
| 908 |
+
if mg2 <= tol:
|
| 909 |
+
err = ctx.mpf(10)**int(ctx.log(abs(factor*tol),10))
|
| 910 |
+
if mg2 > mg1:
|
| 911 |
+
err = ctx.mpf(10)**int(ctx.log(abs(factor*mg1),10))
|
| 912 |
+
err = max(err, ctx.eps*1.)
|
| 913 |
+
ctx.prec -= extraprec
|
| 914 |
+
return +st, err
|
| 915 |
+
|
| 916 |
+
@defun
|
| 917 |
+
def secondzeta(ctx, s, a = 0.015, **kwargs):
|
| 918 |
+
r"""
|
| 919 |
+
Evaluates the secondary zeta function `Z(s)`, defined for
|
| 920 |
+
`\mathrm{Re}(s)>1` by
|
| 921 |
+
|
| 922 |
+
.. math ::
|
| 923 |
+
|
| 924 |
+
Z(s) = \sum_{n=1}^{\infty} \frac{1}{\tau_n^s}
|
| 925 |
+
|
| 926 |
+
where `\frac12+i\tau_n` runs through the zeros of `\zeta(s)` with
|
| 927 |
+
imaginary part positive.
|
| 928 |
+
|
| 929 |
+
`Z(s)` extends to a meromorphic function on `\mathbb{C}` with a
|
| 930 |
+
double pole at `s=1` and simple poles at the points `-2n` for
|
| 931 |
+
`n=0`, 1, 2, ...
|
| 932 |
+
|
| 933 |
+
**Examples**
|
| 934 |
+
|
| 935 |
+
>>> from mpmath import *
|
| 936 |
+
>>> mp.pretty = True; mp.dps = 15
|
| 937 |
+
>>> secondzeta(2)
|
| 938 |
+
0.023104993115419
|
| 939 |
+
>>> xi = lambda s: 0.5*s*(s-1)*pi**(-0.5*s)*gamma(0.5*s)*zeta(s)
|
| 940 |
+
>>> Xi = lambda t: xi(0.5+t*j)
|
| 941 |
+
>>> chop(-0.5*diff(Xi,0,n=2)/Xi(0))
|
| 942 |
+
0.023104993115419
|
| 943 |
+
|
| 944 |
+
We may ask for an approximate error value::
|
| 945 |
+
|
| 946 |
+
>>> secondzeta(0.5+100j, error=True)
|
| 947 |
+
((-0.216272011276718 - 0.844952708937228j), 2.22044604925031e-16)
|
| 948 |
+
|
| 949 |
+
The function has poles at the negative odd integers,
|
| 950 |
+
and dyadic rational values at the negative even integers::
|
| 951 |
+
|
| 952 |
+
>>> mp.dps = 30
|
| 953 |
+
>>> secondzeta(-8)
|
| 954 |
+
-0.67236328125
|
| 955 |
+
>>> secondzeta(-7)
|
| 956 |
+
+inf
|
| 957 |
+
|
| 958 |
+
**Implementation notes**
|
| 959 |
+
|
| 960 |
+
The function is computed as sum of four terms `Z(s)=A(s)-P(s)+E(s)-S(s)`
|
| 961 |
+
respectively main, prime, exponential and singular terms.
|
| 962 |
+
The main term `A(s)` is computed from the zeros of zeta.
|
| 963 |
+
The prime term depends on the von Mangoldt function.
|
| 964 |
+
The singular term is responsible for the poles of the function.
|
| 965 |
+
|
| 966 |
+
The four terms depends on a small parameter `a`. We may change the
|
| 967 |
+
value of `a`. Theoretically this has no effect on the sum of the four
|
| 968 |
+
terms, but in practice may be important.
|
| 969 |
+
|
| 970 |
+
A smaller value of the parameter `a` makes `A(s)` depend on
|
| 971 |
+
a smaller number of zeros of zeta, but `P(s)` uses more values of
|
| 972 |
+
von Mangoldt function.
|
| 973 |
+
|
| 974 |
+
We may also add a verbose option to obtain data about the
|
| 975 |
+
values of the four terms.
|
| 976 |
+
|
| 977 |
+
>>> mp.dps = 10
|
| 978 |
+
>>> secondzeta(0.5 + 40j, error=True, verbose=True)
|
| 979 |
+
main term = (-30190318549.138656312556 - 13964804384.624622876523j)
|
| 980 |
+
computed using 19 zeros of zeta
|
| 981 |
+
prime term = (132717176.89212754625045 + 188980555.17563978290601j)
|
| 982 |
+
computed using 9 values of the von Mangoldt function
|
| 983 |
+
exponential term = (542447428666.07179812536 + 362434922978.80192435203j)
|
| 984 |
+
singular term = (512124392939.98154322355 + 348281138038.65531023921j)
|
| 985 |
+
((0.059471043 + 0.3463514534j), 1.455191523e-11)
|
| 986 |
+
|
| 987 |
+
>>> secondzeta(0.5 + 40j, a=0.04, error=True, verbose=True)
|
| 988 |
+
main term = (-151962888.19606243907725 - 217930683.90210294051982j)
|
| 989 |
+
computed using 9 zeros of zeta
|
| 990 |
+
prime term = (2476659342.3038722372461 + 28711581821.921627163136j)
|
| 991 |
+
computed using 37 values of the von Mangoldt function
|
| 992 |
+
exponential term = (178506047114.7838188264 + 819674143244.45677330576j)
|
| 993 |
+
singular term = (175877424884.22441310708 + 790744630738.28669174871j)
|
| 994 |
+
((0.059471043 + 0.3463514534j), 1.455191523e-11)
|
| 995 |
+
|
| 996 |
+
Notice the great cancellation between the four terms. Changing `a`, the
|
| 997 |
+
four terms are very different numbers but the cancellation gives
|
| 998 |
+
the good value of Z(s).
|
| 999 |
+
|
| 1000 |
+
**References**
|
| 1001 |
+
|
| 1002 |
+
A. Voros, Zeta functions for the Riemann zeros, Ann. Institute Fourier,
|
| 1003 |
+
53, (2003) 665--699.
|
| 1004 |
+
|
| 1005 |
+
A. Voros, Zeta functions over Zeros of Zeta Functions, Lecture Notes
|
| 1006 |
+
of the Unione Matematica Italiana, Springer, 2009.
|
| 1007 |
+
"""
|
| 1008 |
+
s = ctx.convert(s)
|
| 1009 |
+
a = ctx.convert(a)
|
| 1010 |
+
tol = ctx.eps
|
| 1011 |
+
if ctx.isint(s) and ctx.re(s) <= 1:
|
| 1012 |
+
if abs(s-1) < tol*1000:
|
| 1013 |
+
return ctx.inf
|
| 1014 |
+
m = int(round(ctx.re(s)))
|
| 1015 |
+
if m & 1:
|
| 1016 |
+
return ctx.inf
|
| 1017 |
+
else:
|
| 1018 |
+
return ((-1)**(-m//2)*\
|
| 1019 |
+
ctx.fraction(8-ctx.eulernum(-m,exact=True),2**(-m+3)))
|
| 1020 |
+
prec = ctx.prec
|
| 1021 |
+
try:
|
| 1022 |
+
t3 = secondzeta_exp_term(ctx, s, a)
|
| 1023 |
+
extraprec = max(ctx.mag(t3),0)
|
| 1024 |
+
ctx.prec += extraprec + 3
|
| 1025 |
+
t1, r1, gt = secondzeta_main_term(ctx,s,a,error='True', verbose='True')
|
| 1026 |
+
t2, r2, pt = secondzeta_prime_term(ctx,s,a,error='True', verbose='True')
|
| 1027 |
+
t4, r4 = secondzeta_singular_term(ctx,s,a,error='True')
|
| 1028 |
+
t3 = secondzeta_exp_term(ctx, s, a)
|
| 1029 |
+
err = r1+r2+r4
|
| 1030 |
+
t = t1-t2+t3-t4
|
| 1031 |
+
if kwargs.get("verbose"):
|
| 1032 |
+
print('main term =', t1)
|
| 1033 |
+
print(' computed using', gt, 'zeros of zeta')
|
| 1034 |
+
print('prime term =', t2)
|
| 1035 |
+
print(' computed using', pt, 'values of the von Mangoldt function')
|
| 1036 |
+
print('exponential term =', t3)
|
| 1037 |
+
print('singular term =', t4)
|
| 1038 |
+
finally:
|
| 1039 |
+
ctx.prec = prec
|
| 1040 |
+
if kwargs.get("error"):
|
| 1041 |
+
w = max(ctx.mag(abs(t)),0)
|
| 1042 |
+
err = max(err*2**w, ctx.eps*1.*2**w)
|
| 1043 |
+
return +t, err
|
| 1044 |
+
return +t
|
| 1045 |
+
|
| 1046 |
+
|
| 1047 |
+
@defun_wrapped
|
| 1048 |
+
def lerchphi(ctx, z, s, a):
|
| 1049 |
+
r"""
|
| 1050 |
+
Gives the Lerch transcendent, defined for `|z| < 1` and
|
| 1051 |
+
`\Re{a} > 0` by
|
| 1052 |
+
|
| 1053 |
+
.. math ::
|
| 1054 |
+
|
| 1055 |
+
\Phi(z,s,a) = \sum_{k=0}^{\infty} \frac{z^k}{(a+k)^s}
|
| 1056 |
+
|
| 1057 |
+
and generally by the recurrence `\Phi(z,s,a) = z \Phi(z,s,a+1) + a^{-s}`
|
| 1058 |
+
along with the integral representation valid for `\Re{a} > 0`
|
| 1059 |
+
|
| 1060 |
+
.. math ::
|
| 1061 |
+
|
| 1062 |
+
\Phi(z,s,a) = \frac{1}{2 a^s} +
|
| 1063 |
+
\int_0^{\infty} \frac{z^t}{(a+t)^s} dt -
|
| 1064 |
+
2 \int_0^{\infty} \frac{\sin(t \log z - s
|
| 1065 |
+
\operatorname{arctan}(t/a)}{(a^2 + t^2)^{s/2}
|
| 1066 |
+
(e^{2 \pi t}-1)} dt.
|
| 1067 |
+
|
| 1068 |
+
The Lerch transcendent generalizes the Hurwitz zeta function :func:`zeta`
|
| 1069 |
+
(`z = 1`) and the polylogarithm :func:`polylog` (`a = 1`).
|
| 1070 |
+
|
| 1071 |
+
**Examples**
|
| 1072 |
+
|
| 1073 |
+
Several evaluations in terms of simpler functions::
|
| 1074 |
+
|
| 1075 |
+
>>> from mpmath import *
|
| 1076 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 1077 |
+
>>> lerchphi(-1,2,0.5); 4*catalan
|
| 1078 |
+
3.663862376708876060218414
|
| 1079 |
+
3.663862376708876060218414
|
| 1080 |
+
>>> diff(lerchphi, (-1,-2,1), (0,1,0)); 7*zeta(3)/(4*pi**2)
|
| 1081 |
+
0.2131391994087528954617607
|
| 1082 |
+
0.2131391994087528954617607
|
| 1083 |
+
>>> lerchphi(-4,1,1); log(5)/4
|
| 1084 |
+
0.4023594781085250936501898
|
| 1085 |
+
0.4023594781085250936501898
|
| 1086 |
+
>>> lerchphi(-3+2j,1,0.5); 2*atanh(sqrt(-3+2j))/sqrt(-3+2j)
|
| 1087 |
+
(1.142423447120257137774002 + 0.2118232380980201350495795j)
|
| 1088 |
+
(1.142423447120257137774002 + 0.2118232380980201350495795j)
|
| 1089 |
+
|
| 1090 |
+
Evaluation works for complex arguments and `|z| \ge 1`::
|
| 1091 |
+
|
| 1092 |
+
>>> lerchphi(1+2j, 3-j, 4+2j)
|
| 1093 |
+
(0.002025009957009908600539469 + 0.003327897536813558807438089j)
|
| 1094 |
+
>>> lerchphi(-2,2,-2.5)
|
| 1095 |
+
-12.28676272353094275265944
|
| 1096 |
+
>>> lerchphi(10,10,10)
|
| 1097 |
+
(-4.462130727102185701817349e-11 - 1.575172198981096218823481e-12j)
|
| 1098 |
+
>>> lerchphi(10,10,-10.5)
|
| 1099 |
+
(112658784011940.5605789002 - 498113185.5756221777743631j)
|
| 1100 |
+
|
| 1101 |
+
Some degenerate cases::
|
| 1102 |
+
|
| 1103 |
+
>>> lerchphi(0,1,2)
|
| 1104 |
+
0.5
|
| 1105 |
+
>>> lerchphi(0,1,-2)
|
| 1106 |
+
-0.5
|
| 1107 |
+
|
| 1108 |
+
Reduction to simpler functions::
|
| 1109 |
+
|
| 1110 |
+
>>> lerchphi(1, 4.25+1j, 1)
|
| 1111 |
+
(1.044674457556746668033975 - 0.04674508654012658932271226j)
|
| 1112 |
+
>>> zeta(4.25+1j)
|
| 1113 |
+
(1.044674457556746668033975 - 0.04674508654012658932271226j)
|
| 1114 |
+
>>> lerchphi(1 - 0.5**10, 4.25+1j, 1)
|
| 1115 |
+
(1.044629338021507546737197 - 0.04667768813963388181708101j)
|
| 1116 |
+
>>> lerchphi(3, 4, 1)
|
| 1117 |
+
(1.249503297023366545192592 - 0.2314252413375664776474462j)
|
| 1118 |
+
>>> polylog(4, 3) / 3
|
| 1119 |
+
(1.249503297023366545192592 - 0.2314252413375664776474462j)
|
| 1120 |
+
>>> lerchphi(3, 4, 1 - 0.5**10)
|
| 1121 |
+
(1.253978063946663945672674 - 0.2316736622836535468765376j)
|
| 1122 |
+
|
| 1123 |
+
**References**
|
| 1124 |
+
|
| 1125 |
+
1. [DLMF]_ section 25.14
|
| 1126 |
+
|
| 1127 |
+
"""
|
| 1128 |
+
if z == 0:
|
| 1129 |
+
return a ** (-s)
|
| 1130 |
+
# Faster, but these cases are useful for testing right now
|
| 1131 |
+
if z == 1:
|
| 1132 |
+
return ctx.zeta(s, a)
|
| 1133 |
+
if a == 1:
|
| 1134 |
+
return ctx.polylog(s, z) / z
|
| 1135 |
+
if ctx.re(a) < 1:
|
| 1136 |
+
if ctx.isnpint(a):
|
| 1137 |
+
raise ValueError("Lerch transcendent complex infinity")
|
| 1138 |
+
m = int(ctx.ceil(1-ctx.re(a)))
|
| 1139 |
+
v = ctx.zero
|
| 1140 |
+
zpow = ctx.one
|
| 1141 |
+
for n in xrange(m):
|
| 1142 |
+
v += zpow / (a+n)**s
|
| 1143 |
+
zpow *= z
|
| 1144 |
+
return zpow * ctx.lerchphi(z,s, a+m) + v
|
| 1145 |
+
g = ctx.ln(z)
|
| 1146 |
+
v = 1/(2*a**s) + ctx.gammainc(1-s, -a*g) * (-g)**(s-1) / z**a
|
| 1147 |
+
h = s / 2
|
| 1148 |
+
r = 2*ctx.pi
|
| 1149 |
+
f = lambda t: ctx.sin(s*ctx.atan(t/a)-t*g) / \
|
| 1150 |
+
((a**2+t**2)**h * ctx.expm1(r*t))
|
| 1151 |
+
v += 2*ctx.quad(f, [0, ctx.inf])
|
| 1152 |
+
if not ctx.im(z) and not ctx.im(s) and not ctx.im(a) and ctx.re(z) < 1:
|
| 1153 |
+
v = ctx.chop(v)
|
| 1154 |
+
return v
|
.venv/lib/python3.11/site-packages/mpmath/functions/zetazeros.py
ADDED
|
@@ -0,0 +1,1018 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
The function zetazero(n) computes the n-th nontrivial zero of zeta(s).
|
| 3 |
+
|
| 4 |
+
The general strategy is to locate a block of Gram intervals B where we
|
| 5 |
+
know exactly the number of zeros contained and which of those zeros
|
| 6 |
+
is that which we search.
|
| 7 |
+
|
| 8 |
+
If n <= 400 000 000 we know exactly the Rosser exceptions, contained
|
| 9 |
+
in a list in this file. Hence for n<=400 000 000 we simply
|
| 10 |
+
look at these list of exceptions. If our zero is implicated in one of
|
| 11 |
+
these exceptions we have our block B. In other case we simply locate
|
| 12 |
+
the good Rosser block containing our zero.
|
| 13 |
+
|
| 14 |
+
For n > 400 000 000 we apply the method of Turing, as complemented by
|
| 15 |
+
Lehman, Brent and Trudgian to find a suitable B.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
from .functions import defun, defun_wrapped
|
| 19 |
+
|
| 20 |
+
def find_rosser_block_zero(ctx, n):
|
| 21 |
+
"""for n<400 000 000 determines a block were one find our zero"""
|
| 22 |
+
for k in range(len(_ROSSER_EXCEPTIONS)//2):
|
| 23 |
+
a=_ROSSER_EXCEPTIONS[2*k][0]
|
| 24 |
+
b=_ROSSER_EXCEPTIONS[2*k][1]
|
| 25 |
+
if ((a<= n-2) and (n-1 <= b)):
|
| 26 |
+
t0 = ctx.grampoint(a)
|
| 27 |
+
t1 = ctx.grampoint(b)
|
| 28 |
+
v0 = ctx._fp.siegelz(t0)
|
| 29 |
+
v1 = ctx._fp.siegelz(t1)
|
| 30 |
+
my_zero_number = n-a-1
|
| 31 |
+
zero_number_block = b-a
|
| 32 |
+
pattern = _ROSSER_EXCEPTIONS[2*k+1]
|
| 33 |
+
return (my_zero_number, [a,b], [t0,t1], [v0,v1])
|
| 34 |
+
k = n-2
|
| 35 |
+
t,v,b = compute_triple_tvb(ctx, k)
|
| 36 |
+
T = [t]
|
| 37 |
+
V = [v]
|
| 38 |
+
while b < 0:
|
| 39 |
+
k -= 1
|
| 40 |
+
t,v,b = compute_triple_tvb(ctx, k)
|
| 41 |
+
T.insert(0,t)
|
| 42 |
+
V.insert(0,v)
|
| 43 |
+
my_zero_number = n-k-1
|
| 44 |
+
m = n-1
|
| 45 |
+
t,v,b = compute_triple_tvb(ctx, m)
|
| 46 |
+
T.append(t)
|
| 47 |
+
V.append(v)
|
| 48 |
+
while b < 0:
|
| 49 |
+
m += 1
|
| 50 |
+
t,v,b = compute_triple_tvb(ctx, m)
|
| 51 |
+
T.append(t)
|
| 52 |
+
V.append(v)
|
| 53 |
+
return (my_zero_number, [k,m], T, V)
|
| 54 |
+
|
| 55 |
+
def wpzeros(t):
|
| 56 |
+
"""Precision needed to compute higher zeros"""
|
| 57 |
+
wp = 53
|
| 58 |
+
if t > 3*10**8:
|
| 59 |
+
wp = 63
|
| 60 |
+
if t > 10**11:
|
| 61 |
+
wp = 70
|
| 62 |
+
if t > 10**14:
|
| 63 |
+
wp = 83
|
| 64 |
+
return wp
|
| 65 |
+
|
| 66 |
+
def separate_zeros_in_block(ctx, zero_number_block, T, V, limitloop=None,
|
| 67 |
+
fp_tolerance=None):
|
| 68 |
+
"""Separate the zeros contained in the block T, limitloop
|
| 69 |
+
determines how long one must search"""
|
| 70 |
+
if limitloop is None:
|
| 71 |
+
limitloop = ctx.inf
|
| 72 |
+
loopnumber = 0
|
| 73 |
+
variations = count_variations(V)
|
| 74 |
+
while ((variations < zero_number_block) and (loopnumber <limitloop)):
|
| 75 |
+
a = T[0]
|
| 76 |
+
v = V[0]
|
| 77 |
+
newT = [a]
|
| 78 |
+
newV = [v]
|
| 79 |
+
variations = 0
|
| 80 |
+
for n in range(1,len(T)):
|
| 81 |
+
b2 = T[n]
|
| 82 |
+
u = V[n]
|
| 83 |
+
if (u*v>0):
|
| 84 |
+
alpha = ctx.sqrt(u/v)
|
| 85 |
+
b= (alpha*a+b2)/(alpha+1)
|
| 86 |
+
else:
|
| 87 |
+
b = (a+b2)/2
|
| 88 |
+
if fp_tolerance < 10:
|
| 89 |
+
w = ctx._fp.siegelz(b)
|
| 90 |
+
if abs(w)<fp_tolerance:
|
| 91 |
+
w = ctx.siegelz(b)
|
| 92 |
+
else:
|
| 93 |
+
w=ctx.siegelz(b)
|
| 94 |
+
if v*w<0:
|
| 95 |
+
variations += 1
|
| 96 |
+
newT.append(b)
|
| 97 |
+
newV.append(w)
|
| 98 |
+
u = V[n]
|
| 99 |
+
if u*w <0:
|
| 100 |
+
variations += 1
|
| 101 |
+
newT.append(b2)
|
| 102 |
+
newV.append(u)
|
| 103 |
+
a = b2
|
| 104 |
+
v = u
|
| 105 |
+
T = newT
|
| 106 |
+
V = newV
|
| 107 |
+
loopnumber +=1
|
| 108 |
+
if (limitloop>ITERATION_LIMIT)and(loopnumber>2)and(variations+2==zero_number_block):
|
| 109 |
+
dtMax=0
|
| 110 |
+
dtSec=0
|
| 111 |
+
kMax = 0
|
| 112 |
+
for k1 in range(1,len(T)):
|
| 113 |
+
dt = T[k1]-T[k1-1]
|
| 114 |
+
if dt > dtMax:
|
| 115 |
+
kMax=k1
|
| 116 |
+
dtSec = dtMax
|
| 117 |
+
dtMax = dt
|
| 118 |
+
elif (dt<dtMax) and(dt >dtSec):
|
| 119 |
+
dtSec = dt
|
| 120 |
+
if dtMax>3*dtSec:
|
| 121 |
+
f = lambda x: ctx.rs_z(x,derivative=1)
|
| 122 |
+
t0=T[kMax-1]
|
| 123 |
+
t1 = T[kMax]
|
| 124 |
+
t=ctx.findroot(f, (t0,t1), solver ='illinois',verify=False, verbose=False)
|
| 125 |
+
v = ctx.siegelz(t)
|
| 126 |
+
if (t0<t) and (t<t1) and (v*V[kMax]<0):
|
| 127 |
+
T.insert(kMax,t)
|
| 128 |
+
V.insert(kMax,v)
|
| 129 |
+
variations = count_variations(V)
|
| 130 |
+
if variations == zero_number_block:
|
| 131 |
+
separated = True
|
| 132 |
+
else:
|
| 133 |
+
separated = False
|
| 134 |
+
return (T,V, separated)
|
| 135 |
+
|
| 136 |
+
def separate_my_zero(ctx, my_zero_number, zero_number_block, T, V, prec):
|
| 137 |
+
"""If we know which zero of this block is mine,
|
| 138 |
+
the function separates the zero"""
|
| 139 |
+
variations = 0
|
| 140 |
+
v0 = V[0]
|
| 141 |
+
for k in range(1,len(V)):
|
| 142 |
+
v1 = V[k]
|
| 143 |
+
if v0*v1 < 0:
|
| 144 |
+
variations +=1
|
| 145 |
+
if variations == my_zero_number:
|
| 146 |
+
k0 = k
|
| 147 |
+
leftv = v0
|
| 148 |
+
rightv = v1
|
| 149 |
+
v0 = v1
|
| 150 |
+
t1 = T[k0]
|
| 151 |
+
t0 = T[k0-1]
|
| 152 |
+
ctx.prec = prec
|
| 153 |
+
wpz = wpzeros(my_zero_number*ctx.log(my_zero_number))
|
| 154 |
+
|
| 155 |
+
guard = 4*ctx.mag(my_zero_number)
|
| 156 |
+
precs = [ctx.prec+4]
|
| 157 |
+
index=0
|
| 158 |
+
while precs[0] > 2*wpz:
|
| 159 |
+
index +=1
|
| 160 |
+
precs = [precs[0] // 2 +3+2*index] + precs
|
| 161 |
+
ctx.prec = precs[0] + guard
|
| 162 |
+
r = ctx.findroot(lambda x:ctx.siegelz(x), (t0,t1), solver ='illinois', verbose=False)
|
| 163 |
+
#print "first step at", ctx.dps, "digits"
|
| 164 |
+
z=ctx.mpc(0.5,r)
|
| 165 |
+
for prec in precs[1:]:
|
| 166 |
+
ctx.prec = prec + guard
|
| 167 |
+
#print "refining to", ctx.dps, "digits"
|
| 168 |
+
znew = z - ctx.zeta(z) / ctx.zeta(z, derivative=1)
|
| 169 |
+
#print "difference", ctx.nstr(abs(z-znew))
|
| 170 |
+
z=ctx.mpc(0.5,ctx.im(znew))
|
| 171 |
+
return ctx.im(z)
|
| 172 |
+
|
| 173 |
+
def sure_number_block(ctx, n):
|
| 174 |
+
"""The number of good Rosser blocks needed to apply
|
| 175 |
+
Turing method
|
| 176 |
+
References:
|
| 177 |
+
R. P. Brent, On the Zeros of the Riemann Zeta Function
|
| 178 |
+
in the Critical Strip, Math. Comp. 33 (1979) 1361--1372
|
| 179 |
+
T. Trudgian, Improvements to Turing Method, Math. Comp."""
|
| 180 |
+
if n < 9*10**5:
|
| 181 |
+
return(2)
|
| 182 |
+
g = ctx.grampoint(n-100)
|
| 183 |
+
lg = ctx._fp.ln(g)
|
| 184 |
+
brent = 0.0061 * lg**2 +0.08*lg
|
| 185 |
+
trudgian = 0.0031 * lg**2 +0.11*lg
|
| 186 |
+
N = ctx.ceil(min(brent,trudgian))
|
| 187 |
+
N = int(N)
|
| 188 |
+
return N
|
| 189 |
+
|
| 190 |
+
def compute_triple_tvb(ctx, n):
|
| 191 |
+
t = ctx.grampoint(n)
|
| 192 |
+
v = ctx._fp.siegelz(t)
|
| 193 |
+
if ctx.mag(abs(v))<ctx.mag(t)-45:
|
| 194 |
+
v = ctx.siegelz(t)
|
| 195 |
+
b = v*(-1)**n
|
| 196 |
+
return t,v,b
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
ITERATION_LIMIT = 4
|
| 201 |
+
|
| 202 |
+
def search_supergood_block(ctx, n, fp_tolerance):
|
| 203 |
+
"""To use for n>400 000 000"""
|
| 204 |
+
sb = sure_number_block(ctx, n)
|
| 205 |
+
number_goodblocks = 0
|
| 206 |
+
m2 = n-1
|
| 207 |
+
t, v, b = compute_triple_tvb(ctx, m2)
|
| 208 |
+
Tf = [t]
|
| 209 |
+
Vf = [v]
|
| 210 |
+
while b < 0:
|
| 211 |
+
m2 += 1
|
| 212 |
+
t,v,b = compute_triple_tvb(ctx, m2)
|
| 213 |
+
Tf.append(t)
|
| 214 |
+
Vf.append(v)
|
| 215 |
+
goodpoints = [m2]
|
| 216 |
+
T = [t]
|
| 217 |
+
V = [v]
|
| 218 |
+
while number_goodblocks < 2*sb:
|
| 219 |
+
m2 += 1
|
| 220 |
+
t, v, b = compute_triple_tvb(ctx, m2)
|
| 221 |
+
T.append(t)
|
| 222 |
+
V.append(v)
|
| 223 |
+
while b < 0:
|
| 224 |
+
m2 += 1
|
| 225 |
+
t,v,b = compute_triple_tvb(ctx, m2)
|
| 226 |
+
T.append(t)
|
| 227 |
+
V.append(v)
|
| 228 |
+
goodpoints.append(m2)
|
| 229 |
+
zn = len(T)-1
|
| 230 |
+
A, B, separated =\
|
| 231 |
+
separate_zeros_in_block(ctx, zn, T, V, limitloop=ITERATION_LIMIT,
|
| 232 |
+
fp_tolerance=fp_tolerance)
|
| 233 |
+
Tf.pop()
|
| 234 |
+
Tf.extend(A)
|
| 235 |
+
Vf.pop()
|
| 236 |
+
Vf.extend(B)
|
| 237 |
+
if separated:
|
| 238 |
+
number_goodblocks += 1
|
| 239 |
+
else:
|
| 240 |
+
number_goodblocks = 0
|
| 241 |
+
T = [t]
|
| 242 |
+
V = [v]
|
| 243 |
+
# Now the same procedure to the left
|
| 244 |
+
number_goodblocks = 0
|
| 245 |
+
m2 = n-2
|
| 246 |
+
t, v, b = compute_triple_tvb(ctx, m2)
|
| 247 |
+
Tf.insert(0,t)
|
| 248 |
+
Vf.insert(0,v)
|
| 249 |
+
while b < 0:
|
| 250 |
+
m2 -= 1
|
| 251 |
+
t,v,b = compute_triple_tvb(ctx, m2)
|
| 252 |
+
Tf.insert(0,t)
|
| 253 |
+
Vf.insert(0,v)
|
| 254 |
+
goodpoints.insert(0,m2)
|
| 255 |
+
T = [t]
|
| 256 |
+
V = [v]
|
| 257 |
+
while number_goodblocks < 2*sb:
|
| 258 |
+
m2 -= 1
|
| 259 |
+
t, v, b = compute_triple_tvb(ctx, m2)
|
| 260 |
+
T.insert(0,t)
|
| 261 |
+
V.insert(0,v)
|
| 262 |
+
while b < 0:
|
| 263 |
+
m2 -= 1
|
| 264 |
+
t,v,b = compute_triple_tvb(ctx, m2)
|
| 265 |
+
T.insert(0,t)
|
| 266 |
+
V.insert(0,v)
|
| 267 |
+
goodpoints.insert(0,m2)
|
| 268 |
+
zn = len(T)-1
|
| 269 |
+
A, B, separated =\
|
| 270 |
+
separate_zeros_in_block(ctx, zn, T, V, limitloop=ITERATION_LIMIT, fp_tolerance=fp_tolerance)
|
| 271 |
+
A.pop()
|
| 272 |
+
Tf = A+Tf
|
| 273 |
+
B.pop()
|
| 274 |
+
Vf = B+Vf
|
| 275 |
+
if separated:
|
| 276 |
+
number_goodblocks += 1
|
| 277 |
+
else:
|
| 278 |
+
number_goodblocks = 0
|
| 279 |
+
T = [t]
|
| 280 |
+
V = [v]
|
| 281 |
+
r = goodpoints[2*sb]
|
| 282 |
+
lg = len(goodpoints)
|
| 283 |
+
s = goodpoints[lg-2*sb-1]
|
| 284 |
+
tr, vr, br = compute_triple_tvb(ctx, r)
|
| 285 |
+
ar = Tf.index(tr)
|
| 286 |
+
ts, vs, bs = compute_triple_tvb(ctx, s)
|
| 287 |
+
as1 = Tf.index(ts)
|
| 288 |
+
T = Tf[ar:as1+1]
|
| 289 |
+
V = Vf[ar:as1+1]
|
| 290 |
+
zn = s-r
|
| 291 |
+
A, B, separated =\
|
| 292 |
+
separate_zeros_in_block(ctx, zn,T,V,limitloop=ITERATION_LIMIT, fp_tolerance=fp_tolerance)
|
| 293 |
+
if separated:
|
| 294 |
+
return (n-r-1,[r,s],A,B)
|
| 295 |
+
q = goodpoints[sb]
|
| 296 |
+
lg = len(goodpoints)
|
| 297 |
+
t = goodpoints[lg-sb-1]
|
| 298 |
+
tq, vq, bq = compute_triple_tvb(ctx, q)
|
| 299 |
+
aq = Tf.index(tq)
|
| 300 |
+
tt, vt, bt = compute_triple_tvb(ctx, t)
|
| 301 |
+
at = Tf.index(tt)
|
| 302 |
+
T = Tf[aq:at+1]
|
| 303 |
+
V = Vf[aq:at+1]
|
| 304 |
+
return (n-q-1,[q,t],T,V)
|
| 305 |
+
|
| 306 |
+
def count_variations(V):
|
| 307 |
+
count = 0
|
| 308 |
+
vold = V[0]
|
| 309 |
+
for n in range(1, len(V)):
|
| 310 |
+
vnew = V[n]
|
| 311 |
+
if vold*vnew < 0:
|
| 312 |
+
count +=1
|
| 313 |
+
vold = vnew
|
| 314 |
+
return count
|
| 315 |
+
|
| 316 |
+
def pattern_construct(ctx, block, T, V):
|
| 317 |
+
pattern = '('
|
| 318 |
+
a = block[0]
|
| 319 |
+
b = block[1]
|
| 320 |
+
t0,v0,b0 = compute_triple_tvb(ctx, a)
|
| 321 |
+
k = 0
|
| 322 |
+
k0 = 0
|
| 323 |
+
for n in range(a+1,b+1):
|
| 324 |
+
t1,v1,b1 = compute_triple_tvb(ctx, n)
|
| 325 |
+
lgT =len(T)
|
| 326 |
+
while (k < lgT) and (T[k] <= t1):
|
| 327 |
+
k += 1
|
| 328 |
+
L = V[k0:k]
|
| 329 |
+
L.append(v1)
|
| 330 |
+
L.insert(0,v0)
|
| 331 |
+
count = count_variations(L)
|
| 332 |
+
pattern = pattern + ("%s" % count)
|
| 333 |
+
if b1 > 0:
|
| 334 |
+
pattern = pattern + ')('
|
| 335 |
+
k0 = k
|
| 336 |
+
t0,v0,b0 = t1,v1,b1
|
| 337 |
+
pattern = pattern[:-1]
|
| 338 |
+
return pattern
|
| 339 |
+
|
| 340 |
+
@defun
|
| 341 |
+
def zetazero(ctx, n, info=False, round=True):
|
| 342 |
+
r"""
|
| 343 |
+
Computes the `n`-th nontrivial zero of `\zeta(s)` on the critical line,
|
| 344 |
+
i.e. returns an approximation of the `n`-th largest complex number
|
| 345 |
+
`s = \frac{1}{2} + ti` for which `\zeta(s) = 0`. Equivalently, the
|
| 346 |
+
imaginary part `t` is a zero of the Z-function (:func:`~mpmath.siegelz`).
|
| 347 |
+
|
| 348 |
+
**Examples**
|
| 349 |
+
|
| 350 |
+
The first few zeros::
|
| 351 |
+
|
| 352 |
+
>>> from mpmath import *
|
| 353 |
+
>>> mp.dps = 25; mp.pretty = True
|
| 354 |
+
>>> zetazero(1)
|
| 355 |
+
(0.5 + 14.13472514173469379045725j)
|
| 356 |
+
>>> zetazero(2)
|
| 357 |
+
(0.5 + 21.02203963877155499262848j)
|
| 358 |
+
>>> zetazero(20)
|
| 359 |
+
(0.5 + 77.14484006887480537268266j)
|
| 360 |
+
|
| 361 |
+
Verifying that the values are zeros::
|
| 362 |
+
|
| 363 |
+
>>> for n in range(1,5):
|
| 364 |
+
... s = zetazero(n)
|
| 365 |
+
... chop(zeta(s)), chop(siegelz(s.imag))
|
| 366 |
+
...
|
| 367 |
+
(0.0, 0.0)
|
| 368 |
+
(0.0, 0.0)
|
| 369 |
+
(0.0, 0.0)
|
| 370 |
+
(0.0, 0.0)
|
| 371 |
+
|
| 372 |
+
Negative indices give the conjugate zeros (`n = 0` is undefined)::
|
| 373 |
+
|
| 374 |
+
>>> zetazero(-1)
|
| 375 |
+
(0.5 - 14.13472514173469379045725j)
|
| 376 |
+
|
| 377 |
+
:func:`~mpmath.zetazero` supports arbitrarily large `n` and arbitrary precision::
|
| 378 |
+
|
| 379 |
+
>>> mp.dps = 15
|
| 380 |
+
>>> zetazero(1234567)
|
| 381 |
+
(0.5 + 727690.906948208j)
|
| 382 |
+
>>> mp.dps = 50
|
| 383 |
+
>>> zetazero(1234567)
|
| 384 |
+
(0.5 + 727690.9069482075392389420041147142092708393819935j)
|
| 385 |
+
>>> chop(zeta(_)/_)
|
| 386 |
+
0.0
|
| 387 |
+
|
| 388 |
+
with *info=True*, :func:`~mpmath.zetazero` gives additional information::
|
| 389 |
+
|
| 390 |
+
>>> mp.dps = 15
|
| 391 |
+
>>> zetazero(542964976,info=True)
|
| 392 |
+
((0.5 + 209039046.578535j), [542964969, 542964978], 6, '(013111110)')
|
| 393 |
+
|
| 394 |
+
This means that the zero is between Gram points 542964969 and 542964978;
|
| 395 |
+
it is the 6-th zero between them. Finally (01311110) is the pattern
|
| 396 |
+
of zeros in this interval. The numbers indicate the number of zeros
|
| 397 |
+
in each Gram interval (Rosser blocks between parenthesis). In this case
|
| 398 |
+
there is only one Rosser block of length nine.
|
| 399 |
+
"""
|
| 400 |
+
n = int(n)
|
| 401 |
+
if n < 0:
|
| 402 |
+
return ctx.zetazero(-n).conjugate()
|
| 403 |
+
if n == 0:
|
| 404 |
+
raise ValueError("n must be nonzero")
|
| 405 |
+
wpinitial = ctx.prec
|
| 406 |
+
try:
|
| 407 |
+
wpz, fp_tolerance = comp_fp_tolerance(ctx, n)
|
| 408 |
+
ctx.prec = wpz
|
| 409 |
+
if n < 400000000:
|
| 410 |
+
my_zero_number, block, T, V =\
|
| 411 |
+
find_rosser_block_zero(ctx, n)
|
| 412 |
+
else:
|
| 413 |
+
my_zero_number, block, T, V =\
|
| 414 |
+
search_supergood_block(ctx, n, fp_tolerance)
|
| 415 |
+
zero_number_block = block[1]-block[0]
|
| 416 |
+
T, V, separated = separate_zeros_in_block(ctx, zero_number_block, T, V,
|
| 417 |
+
limitloop=ctx.inf, fp_tolerance=fp_tolerance)
|
| 418 |
+
if info:
|
| 419 |
+
pattern = pattern_construct(ctx,block,T,V)
|
| 420 |
+
prec = max(wpinitial, wpz)
|
| 421 |
+
t = separate_my_zero(ctx, my_zero_number, zero_number_block,T,V,prec)
|
| 422 |
+
v = ctx.mpc(0.5,t)
|
| 423 |
+
finally:
|
| 424 |
+
ctx.prec = wpinitial
|
| 425 |
+
if round:
|
| 426 |
+
v =+v
|
| 427 |
+
if info:
|
| 428 |
+
return (v,block,my_zero_number,pattern)
|
| 429 |
+
else:
|
| 430 |
+
return v
|
| 431 |
+
|
| 432 |
+
def gram_index(ctx, t):
|
| 433 |
+
if t > 10**13:
|
| 434 |
+
wp = 3*ctx.log(t, 10)
|
| 435 |
+
else:
|
| 436 |
+
wp = 0
|
| 437 |
+
prec = ctx.prec
|
| 438 |
+
try:
|
| 439 |
+
ctx.prec += wp
|
| 440 |
+
h = int(ctx.siegeltheta(t)/ctx.pi)
|
| 441 |
+
finally:
|
| 442 |
+
ctx.prec = prec
|
| 443 |
+
return(h)
|
| 444 |
+
|
| 445 |
+
def count_to(ctx, t, T, V):
|
| 446 |
+
count = 0
|
| 447 |
+
vold = V[0]
|
| 448 |
+
told = T[0]
|
| 449 |
+
tnew = T[1]
|
| 450 |
+
k = 1
|
| 451 |
+
while tnew < t:
|
| 452 |
+
vnew = V[k]
|
| 453 |
+
if vold*vnew < 0:
|
| 454 |
+
count += 1
|
| 455 |
+
vold = vnew
|
| 456 |
+
k += 1
|
| 457 |
+
tnew = T[k]
|
| 458 |
+
a = ctx.siegelz(t)
|
| 459 |
+
if a*vold < 0:
|
| 460 |
+
count += 1
|
| 461 |
+
return count
|
| 462 |
+
|
| 463 |
+
def comp_fp_tolerance(ctx, n):
|
| 464 |
+
wpz = wpzeros(n*ctx.log(n))
|
| 465 |
+
if n < 15*10**8:
|
| 466 |
+
fp_tolerance = 0.0005
|
| 467 |
+
elif n <= 10**14:
|
| 468 |
+
fp_tolerance = 0.1
|
| 469 |
+
else:
|
| 470 |
+
fp_tolerance = 100
|
| 471 |
+
return wpz, fp_tolerance
|
| 472 |
+
|
| 473 |
+
@defun
|
| 474 |
+
def nzeros(ctx, t):
|
| 475 |
+
r"""
|
| 476 |
+
Computes the number of zeros of the Riemann zeta function in
|
| 477 |
+
`(0,1) \times (0,t]`, usually denoted by `N(t)`.
|
| 478 |
+
|
| 479 |
+
**Examples**
|
| 480 |
+
|
| 481 |
+
The first zero has imaginary part between 14 and 15::
|
| 482 |
+
|
| 483 |
+
>>> from mpmath import *
|
| 484 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 485 |
+
>>> nzeros(14)
|
| 486 |
+
0
|
| 487 |
+
>>> nzeros(15)
|
| 488 |
+
1
|
| 489 |
+
>>> zetazero(1)
|
| 490 |
+
(0.5 + 14.1347251417347j)
|
| 491 |
+
|
| 492 |
+
Some closely spaced zeros::
|
| 493 |
+
|
| 494 |
+
>>> nzeros(10**7)
|
| 495 |
+
21136125
|
| 496 |
+
>>> zetazero(21136125)
|
| 497 |
+
(0.5 + 9999999.32718175j)
|
| 498 |
+
>>> zetazero(21136126)
|
| 499 |
+
(0.5 + 10000000.2400236j)
|
| 500 |
+
>>> nzeros(545439823.215)
|
| 501 |
+
1500000001
|
| 502 |
+
>>> zetazero(1500000001)
|
| 503 |
+
(0.5 + 545439823.201985j)
|
| 504 |
+
>>> zetazero(1500000002)
|
| 505 |
+
(0.5 + 545439823.325697j)
|
| 506 |
+
|
| 507 |
+
This confirms the data given by J. van de Lune,
|
| 508 |
+
H. J. J. te Riele and D. T. Winter in 1986.
|
| 509 |
+
"""
|
| 510 |
+
if t < 14.1347251417347:
|
| 511 |
+
return 0
|
| 512 |
+
x = gram_index(ctx, t)
|
| 513 |
+
k = int(ctx.floor(x))
|
| 514 |
+
wpinitial = ctx.prec
|
| 515 |
+
wpz, fp_tolerance = comp_fp_tolerance(ctx, k)
|
| 516 |
+
ctx.prec = wpz
|
| 517 |
+
a = ctx.siegelz(t)
|
| 518 |
+
if k == -1 and a < 0:
|
| 519 |
+
return 0
|
| 520 |
+
elif k == -1 and a > 0:
|
| 521 |
+
return 1
|
| 522 |
+
if k+2 < 400000000:
|
| 523 |
+
Rblock = find_rosser_block_zero(ctx, k+2)
|
| 524 |
+
else:
|
| 525 |
+
Rblock = search_supergood_block(ctx, k+2, fp_tolerance)
|
| 526 |
+
n1, n2 = Rblock[1]
|
| 527 |
+
if n2-n1 == 1:
|
| 528 |
+
b = Rblock[3][0]
|
| 529 |
+
if a*b > 0:
|
| 530 |
+
ctx.prec = wpinitial
|
| 531 |
+
return k+1
|
| 532 |
+
else:
|
| 533 |
+
ctx.prec = wpinitial
|
| 534 |
+
return k+2
|
| 535 |
+
my_zero_number,block, T, V = Rblock
|
| 536 |
+
zero_number_block = n2-n1
|
| 537 |
+
T, V, separated = separate_zeros_in_block(ctx,\
|
| 538 |
+
zero_number_block, T, V,\
|
| 539 |
+
limitloop=ctx.inf,\
|
| 540 |
+
fp_tolerance=fp_tolerance)
|
| 541 |
+
n = count_to(ctx, t, T, V)
|
| 542 |
+
ctx.prec = wpinitial
|
| 543 |
+
return n+n1+1
|
| 544 |
+
|
| 545 |
+
@defun_wrapped
|
| 546 |
+
def backlunds(ctx, t):
|
| 547 |
+
r"""
|
| 548 |
+
Computes the function
|
| 549 |
+
`S(t) = \operatorname{arg} \zeta(\frac{1}{2} + it) / \pi`.
|
| 550 |
+
|
| 551 |
+
See Titchmarsh Section 9.3 for details of the definition.
|
| 552 |
+
|
| 553 |
+
**Examples**
|
| 554 |
+
|
| 555 |
+
>>> from mpmath import *
|
| 556 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 557 |
+
>>> backlunds(217.3)
|
| 558 |
+
0.16302205431184
|
| 559 |
+
|
| 560 |
+
Generally, the value is a small number. At Gram points it is an integer,
|
| 561 |
+
frequently equal to 0::
|
| 562 |
+
|
| 563 |
+
>>> chop(backlunds(grampoint(200)))
|
| 564 |
+
0.0
|
| 565 |
+
>>> backlunds(extraprec(10)(grampoint)(211))
|
| 566 |
+
1.0
|
| 567 |
+
>>> backlunds(extraprec(10)(grampoint)(232))
|
| 568 |
+
-1.0
|
| 569 |
+
|
| 570 |
+
The number of zeros of the Riemann zeta function up to height `t`
|
| 571 |
+
satisfies `N(t) = \theta(t)/\pi + 1 + S(t)` (see :func:nzeros` and
|
| 572 |
+
:func:`siegeltheta`)::
|
| 573 |
+
|
| 574 |
+
>>> t = 1234.55
|
| 575 |
+
>>> nzeros(t)
|
| 576 |
+
842
|
| 577 |
+
>>> siegeltheta(t)/pi+1+backlunds(t)
|
| 578 |
+
842.0
|
| 579 |
+
|
| 580 |
+
"""
|
| 581 |
+
return ctx.nzeros(t)-1-ctx.siegeltheta(t)/ctx.pi
|
| 582 |
+
|
| 583 |
+
|
| 584 |
+
"""
|
| 585 |
+
_ROSSER_EXCEPTIONS is a list of all exceptions to
|
| 586 |
+
Rosser's rule for n <= 400 000 000.
|
| 587 |
+
|
| 588 |
+
Alternately the entry is of type [n,m], or a string.
|
| 589 |
+
The string is the zero pattern of the Block and the relevant
|
| 590 |
+
adjacent. For example (010)3 corresponds to a block
|
| 591 |
+
composed of three Gram intervals, the first ant third without
|
| 592 |
+
a zero and the intermediate with a zero. The next Gram interval
|
| 593 |
+
contain three zeros. So that in total we have 4 zeros in 4 Gram
|
| 594 |
+
blocks. n and m are the indices of the Gram points of this
|
| 595 |
+
interval of four Gram intervals. The Rosser exception is therefore
|
| 596 |
+
formed by the three Gram intervals that are signaled between
|
| 597 |
+
parenthesis.
|
| 598 |
+
|
| 599 |
+
We have included also some Rosser's exceptions beyond n=400 000 000
|
| 600 |
+
that are noted in the literature by some reason.
|
| 601 |
+
|
| 602 |
+
The list is composed from the data published in the references:
|
| 603 |
+
|
| 604 |
+
R. P. Brent, J. van de Lune, H. J. J. te Riele, D. T. Winter,
|
| 605 |
+
'On the Zeros of the Riemann Zeta Function in the Critical Strip. II',
|
| 606 |
+
Math. Comp. 39 (1982) 681--688.
|
| 607 |
+
See also Corrigenda in Math. Comp. 46 (1986) 771.
|
| 608 |
+
|
| 609 |
+
J. van de Lune, H. J. J. te Riele,
|
| 610 |
+
'On the Zeros of the Riemann Zeta Function in the Critical Strip. III',
|
| 611 |
+
Math. Comp. 41 (1983) 759--767.
|
| 612 |
+
See also Corrigenda in Math. Comp. 46 (1986) 771.
|
| 613 |
+
|
| 614 |
+
J. van de Lune,
|
| 615 |
+
'Sums of Equal Powers of Positive Integers',
|
| 616 |
+
Dissertation,
|
| 617 |
+
Vrije Universiteit te Amsterdam, Centrum voor Wiskunde en Informatica,
|
| 618 |
+
Amsterdam, 1984.
|
| 619 |
+
|
| 620 |
+
Thanks to the authors all this papers and those others that have
|
| 621 |
+
contributed to make this possible.
|
| 622 |
+
"""
|
| 623 |
+
|
| 624 |
+
|
| 625 |
+
|
| 626 |
+
|
| 627 |
+
|
| 628 |
+
|
| 629 |
+
|
| 630 |
+
_ROSSER_EXCEPTIONS = \
|
| 631 |
+
[[13999525, 13999528], '(00)3',
|
| 632 |
+
[30783329, 30783332], '(00)3',
|
| 633 |
+
[30930926, 30930929], '3(00)',
|
| 634 |
+
[37592215, 37592218], '(00)3',
|
| 635 |
+
[40870156, 40870159], '(00)3',
|
| 636 |
+
[43628107, 43628110], '(00)3',
|
| 637 |
+
[46082042, 46082045], '(00)3',
|
| 638 |
+
[46875667, 46875670], '(00)3',
|
| 639 |
+
[49624540, 49624543], '3(00)',
|
| 640 |
+
[50799238, 50799241], '(00)3',
|
| 641 |
+
[55221453, 55221456], '3(00)',
|
| 642 |
+
[56948779, 56948782], '3(00)',
|
| 643 |
+
[60515663, 60515666], '(00)3',
|
| 644 |
+
[61331766, 61331770], '(00)40',
|
| 645 |
+
[69784843, 69784846], '3(00)',
|
| 646 |
+
[75052114, 75052117], '(00)3',
|
| 647 |
+
[79545240, 79545243], '3(00)',
|
| 648 |
+
[79652247, 79652250], '3(00)',
|
| 649 |
+
[83088043, 83088046], '(00)3',
|
| 650 |
+
[83689522, 83689525], '3(00)',
|
| 651 |
+
[85348958, 85348961], '(00)3',
|
| 652 |
+
[86513820, 86513823], '(00)3',
|
| 653 |
+
[87947596, 87947599], '3(00)',
|
| 654 |
+
[88600095, 88600098], '(00)3',
|
| 655 |
+
[93681183, 93681186], '(00)3',
|
| 656 |
+
[100316551, 100316554], '3(00)',
|
| 657 |
+
[100788444, 100788447], '(00)3',
|
| 658 |
+
[106236172, 106236175], '(00)3',
|
| 659 |
+
[106941327, 106941330], '3(00)',
|
| 660 |
+
[107287955, 107287958], '(00)3',
|
| 661 |
+
[107532016, 107532019], '3(00)',
|
| 662 |
+
[110571044, 110571047], '(00)3',
|
| 663 |
+
[111885253, 111885256], '3(00)',
|
| 664 |
+
[113239783, 113239786], '(00)3',
|
| 665 |
+
[120159903, 120159906], '(00)3',
|
| 666 |
+
[121424391, 121424394], '3(00)',
|
| 667 |
+
[121692931, 121692934], '3(00)',
|
| 668 |
+
[121934170, 121934173], '3(00)',
|
| 669 |
+
[122612848, 122612851], '3(00)',
|
| 670 |
+
[126116567, 126116570], '(00)3',
|
| 671 |
+
[127936513, 127936516], '(00)3',
|
| 672 |
+
[128710277, 128710280], '3(00)',
|
| 673 |
+
[129398902, 129398905], '3(00)',
|
| 674 |
+
[130461096, 130461099], '3(00)',
|
| 675 |
+
[131331947, 131331950], '3(00)',
|
| 676 |
+
[137334071, 137334074], '3(00)',
|
| 677 |
+
[137832603, 137832606], '(00)3',
|
| 678 |
+
[138799471, 138799474], '3(00)',
|
| 679 |
+
[139027791, 139027794], '(00)3',
|
| 680 |
+
[141617806, 141617809], '(00)3',
|
| 681 |
+
[144454931, 144454934], '(00)3',
|
| 682 |
+
[145402379, 145402382], '3(00)',
|
| 683 |
+
[146130245, 146130248], '3(00)',
|
| 684 |
+
[147059770, 147059773], '(00)3',
|
| 685 |
+
[147896099, 147896102], '3(00)',
|
| 686 |
+
[151097113, 151097116], '(00)3',
|
| 687 |
+
[152539438, 152539441], '(00)3',
|
| 688 |
+
[152863168, 152863171], '3(00)',
|
| 689 |
+
[153522726, 153522729], '3(00)',
|
| 690 |
+
[155171524, 155171527], '3(00)',
|
| 691 |
+
[155366607, 155366610], '(00)3',
|
| 692 |
+
[157260686, 157260689], '3(00)',
|
| 693 |
+
[157269224, 157269227], '(00)3',
|
| 694 |
+
[157755123, 157755126], '(00)3',
|
| 695 |
+
[158298484, 158298487], '3(00)',
|
| 696 |
+
[160369050, 160369053], '3(00)',
|
| 697 |
+
[162962787, 162962790], '(00)3',
|
| 698 |
+
[163724709, 163724712], '(00)3',
|
| 699 |
+
[164198113, 164198116], '3(00)',
|
| 700 |
+
[164689301, 164689305], '(00)40',
|
| 701 |
+
[164880228, 164880231], '3(00)',
|
| 702 |
+
[166201932, 166201935], '(00)3',
|
| 703 |
+
[168573836, 168573839], '(00)3',
|
| 704 |
+
[169750763, 169750766], '(00)3',
|
| 705 |
+
[170375507, 170375510], '(00)3',
|
| 706 |
+
[170704879, 170704882], '3(00)',
|
| 707 |
+
[172000992, 172000995], '3(00)',
|
| 708 |
+
[173289941, 173289944], '(00)3',
|
| 709 |
+
[173737613, 173737616], '3(00)',
|
| 710 |
+
[174102513, 174102516], '(00)3',
|
| 711 |
+
[174284990, 174284993], '(00)3',
|
| 712 |
+
[174500513, 174500516], '(00)3',
|
| 713 |
+
[175710609, 175710612], '(00)3',
|
| 714 |
+
[176870843, 176870846], '3(00)',
|
| 715 |
+
[177332732, 177332735], '3(00)',
|
| 716 |
+
[177902861, 177902864], '3(00)',
|
| 717 |
+
[179979095, 179979098], '(00)3',
|
| 718 |
+
[181233726, 181233729], '3(00)',
|
| 719 |
+
[181625435, 181625438], '(00)3',
|
| 720 |
+
[182105255, 182105259], '22(00)',
|
| 721 |
+
[182223559, 182223562], '3(00)',
|
| 722 |
+
[191116404, 191116407], '3(00)',
|
| 723 |
+
[191165599, 191165602], '3(00)',
|
| 724 |
+
[191297535, 191297539], '(00)22',
|
| 725 |
+
[192485616, 192485619], '(00)3',
|
| 726 |
+
[193264634, 193264638], '22(00)',
|
| 727 |
+
[194696968, 194696971], '(00)3',
|
| 728 |
+
[195876805, 195876808], '(00)3',
|
| 729 |
+
[195916548, 195916551], '3(00)',
|
| 730 |
+
[196395160, 196395163], '3(00)',
|
| 731 |
+
[196676303, 196676306], '(00)3',
|
| 732 |
+
[197889882, 197889885], '3(00)',
|
| 733 |
+
[198014122, 198014125], '(00)3',
|
| 734 |
+
[199235289, 199235292], '(00)3',
|
| 735 |
+
[201007375, 201007378], '(00)3',
|
| 736 |
+
[201030605, 201030608], '3(00)',
|
| 737 |
+
[201184290, 201184293], '3(00)',
|
| 738 |
+
[201685414, 201685418], '(00)22',
|
| 739 |
+
[202762875, 202762878], '3(00)',
|
| 740 |
+
[202860957, 202860960], '3(00)',
|
| 741 |
+
[203832577, 203832580], '3(00)',
|
| 742 |
+
[205880544, 205880547], '(00)3',
|
| 743 |
+
[206357111, 206357114], '(00)3',
|
| 744 |
+
[207159767, 207159770], '3(00)',
|
| 745 |
+
[207167343, 207167346], '3(00)',
|
| 746 |
+
[207482539, 207482543], '3(010)',
|
| 747 |
+
[207669540, 207669543], '3(00)',
|
| 748 |
+
[208053426, 208053429], '(00)3',
|
| 749 |
+
[208110027, 208110030], '3(00)',
|
| 750 |
+
[209513826, 209513829], '3(00)',
|
| 751 |
+
[212623522, 212623525], '(00)3',
|
| 752 |
+
[213841715, 213841718], '(00)3',
|
| 753 |
+
[214012333, 214012336], '(00)3',
|
| 754 |
+
[214073567, 214073570], '(00)3',
|
| 755 |
+
[215170600, 215170603], '3(00)',
|
| 756 |
+
[215881039, 215881042], '3(00)',
|
| 757 |
+
[216274604, 216274607], '3(00)',
|
| 758 |
+
[216957120, 216957123], '3(00)',
|
| 759 |
+
[217323208, 217323211], '(00)3',
|
| 760 |
+
[218799264, 218799267], '(00)3',
|
| 761 |
+
[218803557, 218803560], '3(00)',
|
| 762 |
+
[219735146, 219735149], '(00)3',
|
| 763 |
+
[219830062, 219830065], '3(00)',
|
| 764 |
+
[219897904, 219897907], '(00)3',
|
| 765 |
+
[221205545, 221205548], '(00)3',
|
| 766 |
+
[223601929, 223601932], '(00)3',
|
| 767 |
+
[223907076, 223907079], '3(00)',
|
| 768 |
+
[223970397, 223970400], '(00)3',
|
| 769 |
+
[224874044, 224874048], '22(00)',
|
| 770 |
+
[225291157, 225291160], '(00)3',
|
| 771 |
+
[227481734, 227481737], '(00)3',
|
| 772 |
+
[228006442, 228006445], '3(00)',
|
| 773 |
+
[228357900, 228357903], '(00)3',
|
| 774 |
+
[228386399, 228386402], '(00)3',
|
| 775 |
+
[228907446, 228907449], '(00)3',
|
| 776 |
+
[228984552, 228984555], '3(00)',
|
| 777 |
+
[229140285, 229140288], '3(00)',
|
| 778 |
+
[231810024, 231810027], '(00)3',
|
| 779 |
+
[232838062, 232838065], '3(00)',
|
| 780 |
+
[234389088, 234389091], '3(00)',
|
| 781 |
+
[235588194, 235588197], '(00)3',
|
| 782 |
+
[236645695, 236645698], '(00)3',
|
| 783 |
+
[236962876, 236962879], '3(00)',
|
| 784 |
+
[237516723, 237516727], '04(00)',
|
| 785 |
+
[240004911, 240004914], '(00)3',
|
| 786 |
+
[240221306, 240221309], '3(00)',
|
| 787 |
+
[241389213, 241389217], '(010)3',
|
| 788 |
+
[241549003, 241549006], '(00)3',
|
| 789 |
+
[241729717, 241729720], '(00)3',
|
| 790 |
+
[241743684, 241743687], '3(00)',
|
| 791 |
+
[243780200, 243780203], '3(00)',
|
| 792 |
+
[243801317, 243801320], '(00)3',
|
| 793 |
+
[244122072, 244122075], '(00)3',
|
| 794 |
+
[244691224, 244691227], '3(00)',
|
| 795 |
+
[244841577, 244841580], '(00)3',
|
| 796 |
+
[245813461, 245813464], '(00)3',
|
| 797 |
+
[246299475, 246299478], '(00)3',
|
| 798 |
+
[246450176, 246450179], '3(00)',
|
| 799 |
+
[249069349, 249069352], '(00)3',
|
| 800 |
+
[250076378, 250076381], '(00)3',
|
| 801 |
+
[252442157, 252442160], '3(00)',
|
| 802 |
+
[252904231, 252904234], '3(00)',
|
| 803 |
+
[255145220, 255145223], '(00)3',
|
| 804 |
+
[255285971, 255285974], '3(00)',
|
| 805 |
+
[256713230, 256713233], '(00)3',
|
| 806 |
+
[257992082, 257992085], '(00)3',
|
| 807 |
+
[258447955, 258447959], '22(00)',
|
| 808 |
+
[259298045, 259298048], '3(00)',
|
| 809 |
+
[262141503, 262141506], '(00)3',
|
| 810 |
+
[263681743, 263681746], '3(00)',
|
| 811 |
+
[266527881, 266527885], '(010)3',
|
| 812 |
+
[266617122, 266617125], '(00)3',
|
| 813 |
+
[266628044, 266628047], '3(00)',
|
| 814 |
+
[267305763, 267305766], '(00)3',
|
| 815 |
+
[267388404, 267388407], '3(00)',
|
| 816 |
+
[267441672, 267441675], '3(00)',
|
| 817 |
+
[267464886, 267464889], '(00)3',
|
| 818 |
+
[267554907, 267554910], '3(00)',
|
| 819 |
+
[269787480, 269787483], '(00)3',
|
| 820 |
+
[270881434, 270881437], '(00)3',
|
| 821 |
+
[270997583, 270997586], '3(00)',
|
| 822 |
+
[272096378, 272096381], '3(00)',
|
| 823 |
+
[272583009, 272583012], '(00)3',
|
| 824 |
+
[274190881, 274190884], '3(00)',
|
| 825 |
+
[274268747, 274268750], '(00)3',
|
| 826 |
+
[275297429, 275297432], '3(00)',
|
| 827 |
+
[275545476, 275545479], '3(00)',
|
| 828 |
+
[275898479, 275898482], '3(00)',
|
| 829 |
+
[275953000, 275953003], '(00)3',
|
| 830 |
+
[277117197, 277117201], '(00)22',
|
| 831 |
+
[277447310, 277447313], '3(00)',
|
| 832 |
+
[279059657, 279059660], '3(00)',
|
| 833 |
+
[279259144, 279259147], '3(00)',
|
| 834 |
+
[279513636, 279513639], '3(00)',
|
| 835 |
+
[279849069, 279849072], '3(00)',
|
| 836 |
+
[280291419, 280291422], '(00)3',
|
| 837 |
+
[281449425, 281449428], '3(00)',
|
| 838 |
+
[281507953, 281507956], '3(00)',
|
| 839 |
+
[281825600, 281825603], '(00)3',
|
| 840 |
+
[282547093, 282547096], '3(00)',
|
| 841 |
+
[283120963, 283120966], '3(00)',
|
| 842 |
+
[283323493, 283323496], '(00)3',
|
| 843 |
+
[284764535, 284764538], '3(00)',
|
| 844 |
+
[286172639, 286172642], '3(00)',
|
| 845 |
+
[286688824, 286688827], '(00)3',
|
| 846 |
+
[287222172, 287222175], '3(00)',
|
| 847 |
+
[287235534, 287235537], '3(00)',
|
| 848 |
+
[287304861, 287304864], '3(00)',
|
| 849 |
+
[287433571, 287433574], '(00)3',
|
| 850 |
+
[287823551, 287823554], '(00)3',
|
| 851 |
+
[287872422, 287872425], '3(00)',
|
| 852 |
+
[288766615, 288766618], '3(00)',
|
| 853 |
+
[290122963, 290122966], '3(00)',
|
| 854 |
+
[290450849, 290450853], '(00)22',
|
| 855 |
+
[291426141, 291426144], '3(00)',
|
| 856 |
+
[292810353, 292810356], '3(00)',
|
| 857 |
+
[293109861, 293109864], '3(00)',
|
| 858 |
+
[293398054, 293398057], '3(00)',
|
| 859 |
+
[294134426, 294134429], '3(00)',
|
| 860 |
+
[294216438, 294216441], '(00)3',
|
| 861 |
+
[295367141, 295367144], '3(00)',
|
| 862 |
+
[297834111, 297834114], '3(00)',
|
| 863 |
+
[299099969, 299099972], '3(00)',
|
| 864 |
+
[300746958, 300746961], '3(00)',
|
| 865 |
+
[301097423, 301097426], '(00)3',
|
| 866 |
+
[301834209, 301834212], '(00)3',
|
| 867 |
+
[302554791, 302554794], '(00)3',
|
| 868 |
+
[303497445, 303497448], '3(00)',
|
| 869 |
+
[304165344, 304165347], '3(00)',
|
| 870 |
+
[304790218, 304790222], '3(010)',
|
| 871 |
+
[305302352, 305302355], '(00)3',
|
| 872 |
+
[306785996, 306785999], '3(00)',
|
| 873 |
+
[307051443, 307051446], '3(00)',
|
| 874 |
+
[307481539, 307481542], '3(00)',
|
| 875 |
+
[308605569, 308605572], '3(00)',
|
| 876 |
+
[309237610, 309237613], '3(00)',
|
| 877 |
+
[310509287, 310509290], '(00)3',
|
| 878 |
+
[310554057, 310554060], '3(00)',
|
| 879 |
+
[310646345, 310646348], '3(00)',
|
| 880 |
+
[311274896, 311274899], '(00)3',
|
| 881 |
+
[311894272, 311894275], '3(00)',
|
| 882 |
+
[312269470, 312269473], '(00)3',
|
| 883 |
+
[312306601, 312306605], '(00)40',
|
| 884 |
+
[312683193, 312683196], '3(00)',
|
| 885 |
+
[314499804, 314499807], '3(00)',
|
| 886 |
+
[314636802, 314636805], '(00)3',
|
| 887 |
+
[314689897, 314689900], '3(00)',
|
| 888 |
+
[314721319, 314721322], '3(00)',
|
| 889 |
+
[316132890, 316132893], '3(00)',
|
| 890 |
+
[316217470, 316217474], '(010)3',
|
| 891 |
+
[316465705, 316465708], '3(00)',
|
| 892 |
+
[316542790, 316542793], '(00)3',
|
| 893 |
+
[320822347, 320822350], '3(00)',
|
| 894 |
+
[321733242, 321733245], '3(00)',
|
| 895 |
+
[324413970, 324413973], '(00)3',
|
| 896 |
+
[325950140, 325950143], '(00)3',
|
| 897 |
+
[326675884, 326675887], '(00)3',
|
| 898 |
+
[326704208, 326704211], '3(00)',
|
| 899 |
+
[327596247, 327596250], '3(00)',
|
| 900 |
+
[328123172, 328123175], '3(00)',
|
| 901 |
+
[328182212, 328182215], '(00)3',
|
| 902 |
+
[328257498, 328257501], '3(00)',
|
| 903 |
+
[328315836, 328315839], '(00)3',
|
| 904 |
+
[328800974, 328800977], '(00)3',
|
| 905 |
+
[328998509, 328998512], '3(00)',
|
| 906 |
+
[329725370, 329725373], '(00)3',
|
| 907 |
+
[332080601, 332080604], '(00)3',
|
| 908 |
+
[332221246, 332221249], '(00)3',
|
| 909 |
+
[332299899, 332299902], '(00)3',
|
| 910 |
+
[332532822, 332532825], '(00)3',
|
| 911 |
+
[333334544, 333334548], '(00)22',
|
| 912 |
+
[333881266, 333881269], '3(00)',
|
| 913 |
+
[334703267, 334703270], '3(00)',
|
| 914 |
+
[334875138, 334875141], '3(00)',
|
| 915 |
+
[336531451, 336531454], '3(00)',
|
| 916 |
+
[336825907, 336825910], '(00)3',
|
| 917 |
+
[336993167, 336993170], '(00)3',
|
| 918 |
+
[337493998, 337494001], '3(00)',
|
| 919 |
+
[337861034, 337861037], '3(00)',
|
| 920 |
+
[337899191, 337899194], '(00)3',
|
| 921 |
+
[337958123, 337958126], '(00)3',
|
| 922 |
+
[342331982, 342331985], '3(00)',
|
| 923 |
+
[342676068, 342676071], '3(00)',
|
| 924 |
+
[347063781, 347063784], '3(00)',
|
| 925 |
+
[347697348, 347697351], '3(00)',
|
| 926 |
+
[347954319, 347954322], '3(00)',
|
| 927 |
+
[348162775, 348162778], '3(00)',
|
| 928 |
+
[349210702, 349210705], '(00)3',
|
| 929 |
+
[349212913, 349212916], '3(00)',
|
| 930 |
+
[349248650, 349248653], '(00)3',
|
| 931 |
+
[349913500, 349913503], '3(00)',
|
| 932 |
+
[350891529, 350891532], '3(00)',
|
| 933 |
+
[351089323, 351089326], '3(00)',
|
| 934 |
+
[351826158, 351826161], '3(00)',
|
| 935 |
+
[352228580, 352228583], '(00)3',
|
| 936 |
+
[352376244, 352376247], '3(00)',
|
| 937 |
+
[352853758, 352853761], '(00)3',
|
| 938 |
+
[355110439, 355110442], '(00)3',
|
| 939 |
+
[355808090, 355808094], '(00)40',
|
| 940 |
+
[355941556, 355941559], '3(00)',
|
| 941 |
+
[356360231, 356360234], '(00)3',
|
| 942 |
+
[356586657, 356586660], '3(00)',
|
| 943 |
+
[356892926, 356892929], '(00)3',
|
| 944 |
+
[356908232, 356908235], '3(00)',
|
| 945 |
+
[357912730, 357912733], '3(00)',
|
| 946 |
+
[358120344, 358120347], '3(00)',
|
| 947 |
+
[359044096, 359044099], '(00)3',
|
| 948 |
+
[360819357, 360819360], '3(00)',
|
| 949 |
+
[361399662, 361399666], '(010)3',
|
| 950 |
+
[362361315, 362361318], '(00)3',
|
| 951 |
+
[363610112, 363610115], '(00)3',
|
| 952 |
+
[363964804, 363964807], '3(00)',
|
| 953 |
+
[364527375, 364527378], '(00)3',
|
| 954 |
+
[365090327, 365090330], '(00)3',
|
| 955 |
+
[365414539, 365414542], '3(00)',
|
| 956 |
+
[366738474, 366738477], '3(00)',
|
| 957 |
+
[368714778, 368714783], '04(010)',
|
| 958 |
+
[368831545, 368831548], '(00)3',
|
| 959 |
+
[368902387, 368902390], '(00)3',
|
| 960 |
+
[370109769, 370109772], '3(00)',
|
| 961 |
+
[370963333, 370963336], '3(00)',
|
| 962 |
+
[372541136, 372541140], '3(010)',
|
| 963 |
+
[372681562, 372681565], '(00)3',
|
| 964 |
+
[373009410, 373009413], '(00)3',
|
| 965 |
+
[373458970, 373458973], '3(00)',
|
| 966 |
+
[375648658, 375648661], '3(00)',
|
| 967 |
+
[376834728, 376834731], '3(00)',
|
| 968 |
+
[377119945, 377119948], '(00)3',
|
| 969 |
+
[377335703, 377335706], '(00)3',
|
| 970 |
+
[378091745, 378091748], '3(00)',
|
| 971 |
+
[379139522, 379139525], '3(00)',
|
| 972 |
+
[380279160, 380279163], '(00)3',
|
| 973 |
+
[380619442, 380619445], '3(00)',
|
| 974 |
+
[381244231, 381244234], '3(00)',
|
| 975 |
+
[382327446, 382327450], '(010)3',
|
| 976 |
+
[382357073, 382357076], '3(00)',
|
| 977 |
+
[383545479, 383545482], '3(00)',
|
| 978 |
+
[384363766, 384363769], '(00)3',
|
| 979 |
+
[384401786, 384401790], '22(00)',
|
| 980 |
+
[385198212, 385198215], '3(00)',
|
| 981 |
+
[385824476, 385824479], '(00)3',
|
| 982 |
+
[385908194, 385908197], '3(00)',
|
| 983 |
+
[386946806, 386946809], '3(00)',
|
| 984 |
+
[387592175, 387592179], '22(00)',
|
| 985 |
+
[388329293, 388329296], '(00)3',
|
| 986 |
+
[388679566, 388679569], '3(00)',
|
| 987 |
+
[388832142, 388832145], '3(00)',
|
| 988 |
+
[390087103, 390087106], '(00)3',
|
| 989 |
+
[390190926, 390190930], '(00)22',
|
| 990 |
+
[390331207, 390331210], '3(00)',
|
| 991 |
+
[391674495, 391674498], '3(00)',
|
| 992 |
+
[391937831, 391937834], '3(00)',
|
| 993 |
+
[391951632, 391951636], '(00)22',
|
| 994 |
+
[392963986, 392963989], '(00)3',
|
| 995 |
+
[393007921, 393007924], '3(00)',
|
| 996 |
+
[393373210, 393373213], '3(00)',
|
| 997 |
+
[393759572, 393759575], '(00)3',
|
| 998 |
+
[394036662, 394036665], '(00)3',
|
| 999 |
+
[395813866, 395813869], '(00)3',
|
| 1000 |
+
[395956690, 395956693], '3(00)',
|
| 1001 |
+
[396031670, 396031673], '3(00)',
|
| 1002 |
+
[397076433, 397076436], '3(00)',
|
| 1003 |
+
[397470601, 397470604], '3(00)',
|
| 1004 |
+
[398289458, 398289461], '3(00)',
|
| 1005 |
+
#
|
| 1006 |
+
[368714778, 368714783], '04(010)',
|
| 1007 |
+
[437953499, 437953504], '04(010)',
|
| 1008 |
+
[526196233, 526196238], '032(00)',
|
| 1009 |
+
[744719566, 744719571], '(010)40',
|
| 1010 |
+
[750375857, 750375862], '032(00)',
|
| 1011 |
+
[958241932, 958241937], '04(010)',
|
| 1012 |
+
[983377342, 983377347], '(00)410',
|
| 1013 |
+
[1003780080, 1003780085], '04(010)',
|
| 1014 |
+
[1070232754, 1070232759], '(00)230',
|
| 1015 |
+
[1209834865, 1209834870], '032(00)',
|
| 1016 |
+
[1257209100, 1257209105], '(00)410',
|
| 1017 |
+
[1368002233, 1368002238], '(00)230'
|
| 1018 |
+
]
|
.venv/lib/python3.11/site-packages/mpmath/identification.py
ADDED
|
@@ -0,0 +1,844 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Implements the PSLQ algorithm for integer relation detection,
|
| 3 |
+
and derivative algorithms for constant recognition.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from .libmp.backend import xrange
|
| 7 |
+
from .libmp import int_types, sqrt_fixed
|
| 8 |
+
|
| 9 |
+
# round to nearest integer (can be done more elegantly...)
|
| 10 |
+
def round_fixed(x, prec):
|
| 11 |
+
return ((x + (1<<(prec-1))) >> prec) << prec
|
| 12 |
+
|
| 13 |
+
class IdentificationMethods(object):
|
| 14 |
+
pass
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def pslq(ctx, x, tol=None, maxcoeff=1000, maxsteps=100, verbose=False):
|
| 18 |
+
r"""
|
| 19 |
+
Given a vector of real numbers `x = [x_0, x_1, ..., x_n]`, ``pslq(x)``
|
| 20 |
+
uses the PSLQ algorithm to find a list of integers
|
| 21 |
+
`[c_0, c_1, ..., c_n]` such that
|
| 22 |
+
|
| 23 |
+
.. math ::
|
| 24 |
+
|
| 25 |
+
|c_1 x_1 + c_2 x_2 + ... + c_n x_n| < \mathrm{tol}
|
| 26 |
+
|
| 27 |
+
and such that `\max |c_k| < \mathrm{maxcoeff}`. If no such vector
|
| 28 |
+
exists, :func:`~mpmath.pslq` returns ``None``. The tolerance defaults to
|
| 29 |
+
3/4 of the working precision.
|
| 30 |
+
|
| 31 |
+
**Examples**
|
| 32 |
+
|
| 33 |
+
Find rational approximations for `\pi`::
|
| 34 |
+
|
| 35 |
+
>>> from mpmath import *
|
| 36 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 37 |
+
>>> pslq([-1, pi], tol=0.01)
|
| 38 |
+
[22, 7]
|
| 39 |
+
>>> pslq([-1, pi], tol=0.001)
|
| 40 |
+
[355, 113]
|
| 41 |
+
>>> mpf(22)/7; mpf(355)/113; +pi
|
| 42 |
+
3.14285714285714
|
| 43 |
+
3.14159292035398
|
| 44 |
+
3.14159265358979
|
| 45 |
+
|
| 46 |
+
Pi is not a rational number with denominator less than 1000::
|
| 47 |
+
|
| 48 |
+
>>> pslq([-1, pi])
|
| 49 |
+
>>>
|
| 50 |
+
|
| 51 |
+
To within the standard precision, it can however be approximated
|
| 52 |
+
by at least one rational number with denominator less than `10^{12}`::
|
| 53 |
+
|
| 54 |
+
>>> p, q = pslq([-1, pi], maxcoeff=10**12)
|
| 55 |
+
>>> print(p); print(q)
|
| 56 |
+
238410049439
|
| 57 |
+
75888275702
|
| 58 |
+
>>> mpf(p)/q
|
| 59 |
+
3.14159265358979
|
| 60 |
+
|
| 61 |
+
The PSLQ algorithm can be applied to long vectors. For example,
|
| 62 |
+
we can investigate the rational (in)dependence of integer square
|
| 63 |
+
roots::
|
| 64 |
+
|
| 65 |
+
>>> mp.dps = 30
|
| 66 |
+
>>> pslq([sqrt(n) for n in range(2, 5+1)])
|
| 67 |
+
>>>
|
| 68 |
+
>>> pslq([sqrt(n) for n in range(2, 6+1)])
|
| 69 |
+
>>>
|
| 70 |
+
>>> pslq([sqrt(n) for n in range(2, 8+1)])
|
| 71 |
+
[2, 0, 0, 0, 0, 0, -1]
|
| 72 |
+
|
| 73 |
+
**Machin formulas**
|
| 74 |
+
|
| 75 |
+
A famous formula for `\pi` is Machin's,
|
| 76 |
+
|
| 77 |
+
.. math ::
|
| 78 |
+
|
| 79 |
+
\frac{\pi}{4} = 4 \operatorname{acot} 5 - \operatorname{acot} 239
|
| 80 |
+
|
| 81 |
+
There are actually infinitely many formulas of this type. Two
|
| 82 |
+
others are
|
| 83 |
+
|
| 84 |
+
.. math ::
|
| 85 |
+
|
| 86 |
+
\frac{\pi}{4} = \operatorname{acot} 1
|
| 87 |
+
|
| 88 |
+
\frac{\pi}{4} = 12 \operatorname{acot} 49 + 32 \operatorname{acot} 57
|
| 89 |
+
+ 5 \operatorname{acot} 239 + 12 \operatorname{acot} 110443
|
| 90 |
+
|
| 91 |
+
We can easily verify the formulas using the PSLQ algorithm::
|
| 92 |
+
|
| 93 |
+
>>> mp.dps = 30
|
| 94 |
+
>>> pslq([pi/4, acot(1)])
|
| 95 |
+
[1, -1]
|
| 96 |
+
>>> pslq([pi/4, acot(5), acot(239)])
|
| 97 |
+
[1, -4, 1]
|
| 98 |
+
>>> pslq([pi/4, acot(49), acot(57), acot(239), acot(110443)])
|
| 99 |
+
[1, -12, -32, 5, -12]
|
| 100 |
+
|
| 101 |
+
We could try to generate a custom Machin-like formula by running
|
| 102 |
+
the PSLQ algorithm with a few inverse cotangent values, for example
|
| 103 |
+
acot(2), acot(3) ... acot(10). Unfortunately, there is a linear
|
| 104 |
+
dependence among these values, resulting in only that dependence
|
| 105 |
+
being detected, with a zero coefficient for `\pi`::
|
| 106 |
+
|
| 107 |
+
>>> pslq([pi] + [acot(n) for n in range(2,11)])
|
| 108 |
+
[0, 1, -1, 0, 0, 0, -1, 0, 0, 0]
|
| 109 |
+
|
| 110 |
+
We get better luck by removing linearly dependent terms::
|
| 111 |
+
|
| 112 |
+
>>> pslq([pi] + [acot(n) for n in range(2,11) if n not in (3, 5)])
|
| 113 |
+
[1, -8, 0, 0, 4, 0, 0, 0]
|
| 114 |
+
|
| 115 |
+
In other words, we found the following formula::
|
| 116 |
+
|
| 117 |
+
>>> 8*acot(2) - 4*acot(7)
|
| 118 |
+
3.14159265358979323846264338328
|
| 119 |
+
>>> +pi
|
| 120 |
+
3.14159265358979323846264338328
|
| 121 |
+
|
| 122 |
+
**Algorithm**
|
| 123 |
+
|
| 124 |
+
This is a fairly direct translation to Python of the pseudocode given by
|
| 125 |
+
David Bailey, "The PSLQ Integer Relation Algorithm":
|
| 126 |
+
http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html
|
| 127 |
+
|
| 128 |
+
The present implementation uses fixed-point instead of floating-point
|
| 129 |
+
arithmetic, since this is significantly (about 7x) faster.
|
| 130 |
+
"""
|
| 131 |
+
|
| 132 |
+
n = len(x)
|
| 133 |
+
if n < 2:
|
| 134 |
+
raise ValueError("n cannot be less than 2")
|
| 135 |
+
|
| 136 |
+
# At too low precision, the algorithm becomes meaningless
|
| 137 |
+
prec = ctx.prec
|
| 138 |
+
if prec < 53:
|
| 139 |
+
raise ValueError("prec cannot be less than 53")
|
| 140 |
+
|
| 141 |
+
if verbose and prec // max(2,n) < 5:
|
| 142 |
+
print("Warning: precision for PSLQ may be too low")
|
| 143 |
+
|
| 144 |
+
target = int(prec * 0.75)
|
| 145 |
+
|
| 146 |
+
if tol is None:
|
| 147 |
+
tol = ctx.mpf(2)**(-target)
|
| 148 |
+
else:
|
| 149 |
+
tol = ctx.convert(tol)
|
| 150 |
+
|
| 151 |
+
extra = 60
|
| 152 |
+
prec += extra
|
| 153 |
+
|
| 154 |
+
if verbose:
|
| 155 |
+
print("PSLQ using prec %i and tol %s" % (prec, ctx.nstr(tol)))
|
| 156 |
+
|
| 157 |
+
tol = ctx.to_fixed(tol, prec)
|
| 158 |
+
assert tol
|
| 159 |
+
|
| 160 |
+
# Convert to fixed-point numbers. The dummy None is added so we can
|
| 161 |
+
# use 1-based indexing. (This just allows us to be consistent with
|
| 162 |
+
# Bailey's indexing. The algorithm is 100 lines long, so debugging
|
| 163 |
+
# a single wrong index can be painful.)
|
| 164 |
+
x = [None] + [ctx.to_fixed(ctx.mpf(xk), prec) for xk in x]
|
| 165 |
+
|
| 166 |
+
# Sanity check on magnitudes
|
| 167 |
+
minx = min(abs(xx) for xx in x[1:])
|
| 168 |
+
if not minx:
|
| 169 |
+
raise ValueError("PSLQ requires a vector of nonzero numbers")
|
| 170 |
+
if minx < tol//100:
|
| 171 |
+
if verbose:
|
| 172 |
+
print("STOPPING: (one number is too small)")
|
| 173 |
+
return None
|
| 174 |
+
|
| 175 |
+
g = sqrt_fixed((4<<prec)//3, prec)
|
| 176 |
+
A = {}
|
| 177 |
+
B = {}
|
| 178 |
+
H = {}
|
| 179 |
+
# Initialization
|
| 180 |
+
# step 1
|
| 181 |
+
for i in xrange(1, n+1):
|
| 182 |
+
for j in xrange(1, n+1):
|
| 183 |
+
A[i,j] = B[i,j] = (i==j) << prec
|
| 184 |
+
H[i,j] = 0
|
| 185 |
+
# step 2
|
| 186 |
+
s = [None] + [0] * n
|
| 187 |
+
for k in xrange(1, n+1):
|
| 188 |
+
t = 0
|
| 189 |
+
for j in xrange(k, n+1):
|
| 190 |
+
t += (x[j]**2 >> prec)
|
| 191 |
+
s[k] = sqrt_fixed(t, prec)
|
| 192 |
+
t = s[1]
|
| 193 |
+
y = x[:]
|
| 194 |
+
for k in xrange(1, n+1):
|
| 195 |
+
y[k] = (x[k] << prec) // t
|
| 196 |
+
s[k] = (s[k] << prec) // t
|
| 197 |
+
# step 3
|
| 198 |
+
for i in xrange(1, n+1):
|
| 199 |
+
for j in xrange(i+1, n):
|
| 200 |
+
H[i,j] = 0
|
| 201 |
+
if i <= n-1:
|
| 202 |
+
if s[i]:
|
| 203 |
+
H[i,i] = (s[i+1] << prec) // s[i]
|
| 204 |
+
else:
|
| 205 |
+
H[i,i] = 0
|
| 206 |
+
for j in range(1, i):
|
| 207 |
+
sjj1 = s[j]*s[j+1]
|
| 208 |
+
if sjj1:
|
| 209 |
+
H[i,j] = ((-y[i]*y[j])<<prec)//sjj1
|
| 210 |
+
else:
|
| 211 |
+
H[i,j] = 0
|
| 212 |
+
# step 4
|
| 213 |
+
for i in xrange(2, n+1):
|
| 214 |
+
for j in xrange(i-1, 0, -1):
|
| 215 |
+
#t = floor(H[i,j]/H[j,j] + 0.5)
|
| 216 |
+
if H[j,j]:
|
| 217 |
+
t = round_fixed((H[i,j] << prec)//H[j,j], prec)
|
| 218 |
+
else:
|
| 219 |
+
#t = 0
|
| 220 |
+
continue
|
| 221 |
+
y[j] = y[j] + (t*y[i] >> prec)
|
| 222 |
+
for k in xrange(1, j+1):
|
| 223 |
+
H[i,k] = H[i,k] - (t*H[j,k] >> prec)
|
| 224 |
+
for k in xrange(1, n+1):
|
| 225 |
+
A[i,k] = A[i,k] - (t*A[j,k] >> prec)
|
| 226 |
+
B[k,j] = B[k,j] + (t*B[k,i] >> prec)
|
| 227 |
+
# Main algorithm
|
| 228 |
+
for REP in range(maxsteps):
|
| 229 |
+
# Step 1
|
| 230 |
+
m = -1
|
| 231 |
+
szmax = -1
|
| 232 |
+
for i in range(1, n):
|
| 233 |
+
h = H[i,i]
|
| 234 |
+
sz = (g**i * abs(h)) >> (prec*(i-1))
|
| 235 |
+
if sz > szmax:
|
| 236 |
+
m = i
|
| 237 |
+
szmax = sz
|
| 238 |
+
# Step 2
|
| 239 |
+
y[m], y[m+1] = y[m+1], y[m]
|
| 240 |
+
for i in xrange(1,n+1): H[m,i], H[m+1,i] = H[m+1,i], H[m,i]
|
| 241 |
+
for i in xrange(1,n+1): A[m,i], A[m+1,i] = A[m+1,i], A[m,i]
|
| 242 |
+
for i in xrange(1,n+1): B[i,m], B[i,m+1] = B[i,m+1], B[i,m]
|
| 243 |
+
# Step 3
|
| 244 |
+
if m <= n - 2:
|
| 245 |
+
t0 = sqrt_fixed((H[m,m]**2 + H[m,m+1]**2)>>prec, prec)
|
| 246 |
+
# A zero element probably indicates that the precision has
|
| 247 |
+
# been exhausted. XXX: this could be spurious, due to
|
| 248 |
+
# using fixed-point arithmetic
|
| 249 |
+
if not t0:
|
| 250 |
+
break
|
| 251 |
+
t1 = (H[m,m] << prec) // t0
|
| 252 |
+
t2 = (H[m,m+1] << prec) // t0
|
| 253 |
+
for i in xrange(m, n+1):
|
| 254 |
+
t3 = H[i,m]
|
| 255 |
+
t4 = H[i,m+1]
|
| 256 |
+
H[i,m] = (t1*t3+t2*t4) >> prec
|
| 257 |
+
H[i,m+1] = (-t2*t3+t1*t4) >> prec
|
| 258 |
+
# Step 4
|
| 259 |
+
for i in xrange(m+1, n+1):
|
| 260 |
+
for j in xrange(min(i-1, m+1), 0, -1):
|
| 261 |
+
try:
|
| 262 |
+
t = round_fixed((H[i,j] << prec)//H[j,j], prec)
|
| 263 |
+
# Precision probably exhausted
|
| 264 |
+
except ZeroDivisionError:
|
| 265 |
+
break
|
| 266 |
+
y[j] = y[j] + ((t*y[i]) >> prec)
|
| 267 |
+
for k in xrange(1, j+1):
|
| 268 |
+
H[i,k] = H[i,k] - (t*H[j,k] >> prec)
|
| 269 |
+
for k in xrange(1, n+1):
|
| 270 |
+
A[i,k] = A[i,k] - (t*A[j,k] >> prec)
|
| 271 |
+
B[k,j] = B[k,j] + (t*B[k,i] >> prec)
|
| 272 |
+
# Until a relation is found, the error typically decreases
|
| 273 |
+
# slowly (e.g. a factor 1-10) with each step TODO: we could
|
| 274 |
+
# compare err from two successive iterations. If there is a
|
| 275 |
+
# large drop (several orders of magnitude), that indicates a
|
| 276 |
+
# "high quality" relation was detected. Reporting this to
|
| 277 |
+
# the user somehow might be useful.
|
| 278 |
+
best_err = maxcoeff<<prec
|
| 279 |
+
for i in xrange(1, n+1):
|
| 280 |
+
err = abs(y[i])
|
| 281 |
+
# Maybe we are done?
|
| 282 |
+
if err < tol:
|
| 283 |
+
# We are done if the coefficients are acceptable
|
| 284 |
+
vec = [int(round_fixed(B[j,i], prec) >> prec) for j in \
|
| 285 |
+
range(1,n+1)]
|
| 286 |
+
if max(abs(v) for v in vec) < maxcoeff:
|
| 287 |
+
if verbose:
|
| 288 |
+
print("FOUND relation at iter %i/%i, error: %s" % \
|
| 289 |
+
(REP, maxsteps, ctx.nstr(err / ctx.mpf(2)**prec, 1)))
|
| 290 |
+
return vec
|
| 291 |
+
best_err = min(err, best_err)
|
| 292 |
+
# Calculate a lower bound for the norm. We could do this
|
| 293 |
+
# more exactly (using the Euclidean norm) but there is probably
|
| 294 |
+
# no practical benefit.
|
| 295 |
+
recnorm = max(abs(h) for h in H.values())
|
| 296 |
+
if recnorm:
|
| 297 |
+
norm = ((1 << (2*prec)) // recnorm) >> prec
|
| 298 |
+
norm //= 100
|
| 299 |
+
else:
|
| 300 |
+
norm = ctx.inf
|
| 301 |
+
if verbose:
|
| 302 |
+
print("%i/%i: Error: %8s Norm: %s" % \
|
| 303 |
+
(REP, maxsteps, ctx.nstr(best_err / ctx.mpf(2)**prec, 1), norm))
|
| 304 |
+
if norm >= maxcoeff:
|
| 305 |
+
break
|
| 306 |
+
if verbose:
|
| 307 |
+
print("CANCELLING after step %i/%i." % (REP, maxsteps))
|
| 308 |
+
print("Could not find an integer relation. Norm bound: %s" % norm)
|
| 309 |
+
return None
|
| 310 |
+
|
| 311 |
+
def findpoly(ctx, x, n=1, **kwargs):
|
| 312 |
+
r"""
|
| 313 |
+
``findpoly(x, n)`` returns the coefficients of an integer
|
| 314 |
+
polynomial `P` of degree at most `n` such that `P(x) \approx 0`.
|
| 315 |
+
If no polynomial having `x` as a root can be found,
|
| 316 |
+
:func:`~mpmath.findpoly` returns ``None``.
|
| 317 |
+
|
| 318 |
+
:func:`~mpmath.findpoly` works by successively calling :func:`~mpmath.pslq` with
|
| 319 |
+
the vectors `[1, x]`, `[1, x, x^2]`, `[1, x, x^2, x^3]`, ...,
|
| 320 |
+
`[1, x, x^2, .., x^n]` as input. Keyword arguments given to
|
| 321 |
+
:func:`~mpmath.findpoly` are forwarded verbatim to :func:`~mpmath.pslq`. In
|
| 322 |
+
particular, you can specify a tolerance for `P(x)` with ``tol``
|
| 323 |
+
and a maximum permitted coefficient size with ``maxcoeff``.
|
| 324 |
+
|
| 325 |
+
For large values of `n`, it is recommended to run :func:`~mpmath.findpoly`
|
| 326 |
+
at high precision; preferably 50 digits or more.
|
| 327 |
+
|
| 328 |
+
**Examples**
|
| 329 |
+
|
| 330 |
+
By default (degree `n = 1`), :func:`~mpmath.findpoly` simply finds a linear
|
| 331 |
+
polynomial with a rational root::
|
| 332 |
+
|
| 333 |
+
>>> from mpmath import *
|
| 334 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 335 |
+
>>> findpoly(0.7)
|
| 336 |
+
[-10, 7]
|
| 337 |
+
|
| 338 |
+
The generated coefficient list is valid input to ``polyval`` and
|
| 339 |
+
``polyroots``::
|
| 340 |
+
|
| 341 |
+
>>> nprint(polyval(findpoly(phi, 2), phi), 1)
|
| 342 |
+
-2.0e-16
|
| 343 |
+
>>> for r in polyroots(findpoly(phi, 2)):
|
| 344 |
+
... print(r)
|
| 345 |
+
...
|
| 346 |
+
-0.618033988749895
|
| 347 |
+
1.61803398874989
|
| 348 |
+
|
| 349 |
+
Numbers of the form `m + n \sqrt p` for integers `(m, n, p)` are
|
| 350 |
+
solutions to quadratic equations. As we find here, `1+\sqrt 2`
|
| 351 |
+
is a root of the polynomial `x^2 - 2x - 1`::
|
| 352 |
+
|
| 353 |
+
>>> findpoly(1+sqrt(2), 2)
|
| 354 |
+
[1, -2, -1]
|
| 355 |
+
>>> findroot(lambda x: x**2 - 2*x - 1, 1)
|
| 356 |
+
2.4142135623731
|
| 357 |
+
|
| 358 |
+
Despite only containing square roots, the following number results
|
| 359 |
+
in a polynomial of degree 4::
|
| 360 |
+
|
| 361 |
+
>>> findpoly(sqrt(2)+sqrt(3), 4)
|
| 362 |
+
[1, 0, -10, 0, 1]
|
| 363 |
+
|
| 364 |
+
In fact, `x^4 - 10x^2 + 1` is the *minimal polynomial* of
|
| 365 |
+
`r = \sqrt 2 + \sqrt 3`, meaning that a rational polynomial of
|
| 366 |
+
lower degree having `r` as a root does not exist. Given sufficient
|
| 367 |
+
precision, :func:`~mpmath.findpoly` will usually find the correct
|
| 368 |
+
minimal polynomial of a given algebraic number.
|
| 369 |
+
|
| 370 |
+
**Non-algebraic numbers**
|
| 371 |
+
|
| 372 |
+
If :func:`~mpmath.findpoly` fails to find a polynomial with given
|
| 373 |
+
coefficient size and tolerance constraints, that means no such
|
| 374 |
+
polynomial exists.
|
| 375 |
+
|
| 376 |
+
We can verify that `\pi` is not an algebraic number of degree 3 with
|
| 377 |
+
coefficients less than 1000::
|
| 378 |
+
|
| 379 |
+
>>> mp.dps = 15
|
| 380 |
+
>>> findpoly(pi, 3)
|
| 381 |
+
>>>
|
| 382 |
+
|
| 383 |
+
It is always possible to find an algebraic approximation of a number
|
| 384 |
+
using one (or several) of the following methods:
|
| 385 |
+
|
| 386 |
+
1. Increasing the permitted degree
|
| 387 |
+
2. Allowing larger coefficients
|
| 388 |
+
3. Reducing the tolerance
|
| 389 |
+
|
| 390 |
+
One example of each method is shown below::
|
| 391 |
+
|
| 392 |
+
>>> mp.dps = 15
|
| 393 |
+
>>> findpoly(pi, 4)
|
| 394 |
+
[95, -545, 863, -183, -298]
|
| 395 |
+
>>> findpoly(pi, 3, maxcoeff=10000)
|
| 396 |
+
[836, -1734, -2658, -457]
|
| 397 |
+
>>> findpoly(pi, 3, tol=1e-7)
|
| 398 |
+
[-4, 22, -29, -2]
|
| 399 |
+
|
| 400 |
+
It is unknown whether Euler's constant is transcendental (or even
|
| 401 |
+
irrational). We can use :func:`~mpmath.findpoly` to check that if is
|
| 402 |
+
an algebraic number, its minimal polynomial must have degree
|
| 403 |
+
at least 7 and a coefficient of magnitude at least 1000000::
|
| 404 |
+
|
| 405 |
+
>>> mp.dps = 200
|
| 406 |
+
>>> findpoly(euler, 6, maxcoeff=10**6, tol=1e-100, maxsteps=1000)
|
| 407 |
+
>>>
|
| 408 |
+
|
| 409 |
+
Note that the high precision and strict tolerance is necessary
|
| 410 |
+
for such high-degree runs, since otherwise unwanted low-accuracy
|
| 411 |
+
approximations will be detected. It may also be necessary to set
|
| 412 |
+
maxsteps high to prevent a premature exit (before the coefficient
|
| 413 |
+
bound has been reached). Running with ``verbose=True`` to get an
|
| 414 |
+
idea what is happening can be useful.
|
| 415 |
+
"""
|
| 416 |
+
x = ctx.mpf(x)
|
| 417 |
+
if n < 1:
|
| 418 |
+
raise ValueError("n cannot be less than 1")
|
| 419 |
+
if x == 0:
|
| 420 |
+
return [1, 0]
|
| 421 |
+
xs = [ctx.mpf(1)]
|
| 422 |
+
for i in range(1,n+1):
|
| 423 |
+
xs.append(x**i)
|
| 424 |
+
a = ctx.pslq(xs, **kwargs)
|
| 425 |
+
if a is not None:
|
| 426 |
+
return a[::-1]
|
| 427 |
+
|
| 428 |
+
def fracgcd(p, q):
|
| 429 |
+
x, y = p, q
|
| 430 |
+
while y:
|
| 431 |
+
x, y = y, x % y
|
| 432 |
+
if x != 1:
|
| 433 |
+
p //= x
|
| 434 |
+
q //= x
|
| 435 |
+
if q == 1:
|
| 436 |
+
return p
|
| 437 |
+
return p, q
|
| 438 |
+
|
| 439 |
+
def pslqstring(r, constants):
|
| 440 |
+
q = r[0]
|
| 441 |
+
r = r[1:]
|
| 442 |
+
s = []
|
| 443 |
+
for i in range(len(r)):
|
| 444 |
+
p = r[i]
|
| 445 |
+
if p:
|
| 446 |
+
z = fracgcd(-p,q)
|
| 447 |
+
cs = constants[i][1]
|
| 448 |
+
if cs == '1':
|
| 449 |
+
cs = ''
|
| 450 |
+
else:
|
| 451 |
+
cs = '*' + cs
|
| 452 |
+
if isinstance(z, int_types):
|
| 453 |
+
if z > 0: term = str(z) + cs
|
| 454 |
+
else: term = ("(%s)" % z) + cs
|
| 455 |
+
else:
|
| 456 |
+
term = ("(%s/%s)" % z) + cs
|
| 457 |
+
s.append(term)
|
| 458 |
+
s = ' + '.join(s)
|
| 459 |
+
if '+' in s or '*' in s:
|
| 460 |
+
s = '(' + s + ')'
|
| 461 |
+
return s or '0'
|
| 462 |
+
|
| 463 |
+
def prodstring(r, constants):
|
| 464 |
+
q = r[0]
|
| 465 |
+
r = r[1:]
|
| 466 |
+
num = []
|
| 467 |
+
den = []
|
| 468 |
+
for i in range(len(r)):
|
| 469 |
+
p = r[i]
|
| 470 |
+
if p:
|
| 471 |
+
z = fracgcd(-p,q)
|
| 472 |
+
cs = constants[i][1]
|
| 473 |
+
if isinstance(z, int_types):
|
| 474 |
+
if abs(z) == 1: t = cs
|
| 475 |
+
else: t = '%s**%s' % (cs, abs(z))
|
| 476 |
+
([num,den][z<0]).append(t)
|
| 477 |
+
else:
|
| 478 |
+
t = '%s**(%s/%s)' % (cs, abs(z[0]), z[1])
|
| 479 |
+
([num,den][z[0]<0]).append(t)
|
| 480 |
+
num = '*'.join(num)
|
| 481 |
+
den = '*'.join(den)
|
| 482 |
+
if num and den: return "(%s)/(%s)" % (num, den)
|
| 483 |
+
if num: return num
|
| 484 |
+
if den: return "1/(%s)" % den
|
| 485 |
+
|
| 486 |
+
def quadraticstring(ctx,t,a,b,c):
|
| 487 |
+
if c < 0:
|
| 488 |
+
a,b,c = -a,-b,-c
|
| 489 |
+
u1 = (-b+ctx.sqrt(b**2-4*a*c))/(2*c)
|
| 490 |
+
u2 = (-b-ctx.sqrt(b**2-4*a*c))/(2*c)
|
| 491 |
+
if abs(u1-t) < abs(u2-t):
|
| 492 |
+
if b: s = '((%s+sqrt(%s))/%s)' % (-b,b**2-4*a*c,2*c)
|
| 493 |
+
else: s = '(sqrt(%s)/%s)' % (-4*a*c,2*c)
|
| 494 |
+
else:
|
| 495 |
+
if b: s = '((%s-sqrt(%s))/%s)' % (-b,b**2-4*a*c,2*c)
|
| 496 |
+
else: s = '(-sqrt(%s)/%s)' % (-4*a*c,2*c)
|
| 497 |
+
return s
|
| 498 |
+
|
| 499 |
+
# Transformation y = f(x,c), with inverse function x = f(y,c)
|
| 500 |
+
# The third entry indicates whether the transformation is
|
| 501 |
+
# redundant when c = 1
|
| 502 |
+
transforms = [
|
| 503 |
+
(lambda ctx,x,c: x*c, '$y/$c', 0),
|
| 504 |
+
(lambda ctx,x,c: x/c, '$c*$y', 1),
|
| 505 |
+
(lambda ctx,x,c: c/x, '$c/$y', 0),
|
| 506 |
+
(lambda ctx,x,c: (x*c)**2, 'sqrt($y)/$c', 0),
|
| 507 |
+
(lambda ctx,x,c: (x/c)**2, '$c*sqrt($y)', 1),
|
| 508 |
+
(lambda ctx,x,c: (c/x)**2, '$c/sqrt($y)', 0),
|
| 509 |
+
(lambda ctx,x,c: c*x**2, 'sqrt($y)/sqrt($c)', 1),
|
| 510 |
+
(lambda ctx,x,c: x**2/c, 'sqrt($c)*sqrt($y)', 1),
|
| 511 |
+
(lambda ctx,x,c: c/x**2, 'sqrt($c)/sqrt($y)', 1),
|
| 512 |
+
(lambda ctx,x,c: ctx.sqrt(x*c), '$y**2/$c', 0),
|
| 513 |
+
(lambda ctx,x,c: ctx.sqrt(x/c), '$c*$y**2', 1),
|
| 514 |
+
(lambda ctx,x,c: ctx.sqrt(c/x), '$c/$y**2', 0),
|
| 515 |
+
(lambda ctx,x,c: c*ctx.sqrt(x), '$y**2/$c**2', 1),
|
| 516 |
+
(lambda ctx,x,c: ctx.sqrt(x)/c, '$c**2*$y**2', 1),
|
| 517 |
+
(lambda ctx,x,c: c/ctx.sqrt(x), '$c**2/$y**2', 1),
|
| 518 |
+
(lambda ctx,x,c: ctx.exp(x*c), 'log($y)/$c', 0),
|
| 519 |
+
(lambda ctx,x,c: ctx.exp(x/c), '$c*log($y)', 1),
|
| 520 |
+
(lambda ctx,x,c: ctx.exp(c/x), '$c/log($y)', 0),
|
| 521 |
+
(lambda ctx,x,c: c*ctx.exp(x), 'log($y/$c)', 1),
|
| 522 |
+
(lambda ctx,x,c: ctx.exp(x)/c, 'log($c*$y)', 1),
|
| 523 |
+
(lambda ctx,x,c: c/ctx.exp(x), 'log($c/$y)', 0),
|
| 524 |
+
(lambda ctx,x,c: ctx.ln(x*c), 'exp($y)/$c', 0),
|
| 525 |
+
(lambda ctx,x,c: ctx.ln(x/c), '$c*exp($y)', 1),
|
| 526 |
+
(lambda ctx,x,c: ctx.ln(c/x), '$c/exp($y)', 0),
|
| 527 |
+
(lambda ctx,x,c: c*ctx.ln(x), 'exp($y/$c)', 1),
|
| 528 |
+
(lambda ctx,x,c: ctx.ln(x)/c, 'exp($c*$y)', 1),
|
| 529 |
+
(lambda ctx,x,c: c/ctx.ln(x), 'exp($c/$y)', 0),
|
| 530 |
+
]
|
| 531 |
+
|
| 532 |
+
def identify(ctx, x, constants=[], tol=None, maxcoeff=1000, full=False,
|
| 533 |
+
verbose=False):
|
| 534 |
+
r"""
|
| 535 |
+
Given a real number `x`, ``identify(x)`` attempts to find an exact
|
| 536 |
+
formula for `x`. This formula is returned as a string. If no match
|
| 537 |
+
is found, ``None`` is returned. With ``full=True``, a list of
|
| 538 |
+
matching formulas is returned.
|
| 539 |
+
|
| 540 |
+
As a simple example, :func:`~mpmath.identify` will find an algebraic
|
| 541 |
+
formula for the golden ratio::
|
| 542 |
+
|
| 543 |
+
>>> from mpmath import *
|
| 544 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 545 |
+
>>> identify(phi)
|
| 546 |
+
'((1+sqrt(5))/2)'
|
| 547 |
+
|
| 548 |
+
:func:`~mpmath.identify` can identify simple algebraic numbers and simple
|
| 549 |
+
combinations of given base constants, as well as certain basic
|
| 550 |
+
transformations thereof. More specifically, :func:`~mpmath.identify`
|
| 551 |
+
looks for the following:
|
| 552 |
+
|
| 553 |
+
1. Fractions
|
| 554 |
+
2. Quadratic algebraic numbers
|
| 555 |
+
3. Rational linear combinations of the base constants
|
| 556 |
+
4. Any of the above after first transforming `x` into `f(x)` where
|
| 557 |
+
`f(x)` is `1/x`, `\sqrt x`, `x^2`, `\log x` or `\exp x`, either
|
| 558 |
+
directly or with `x` or `f(x)` multiplied or divided by one of
|
| 559 |
+
the base constants
|
| 560 |
+
5. Products of fractional powers of the base constants and
|
| 561 |
+
small integers
|
| 562 |
+
|
| 563 |
+
Base constants can be given as a list of strings representing mpmath
|
| 564 |
+
expressions (:func:`~mpmath.identify` will ``eval`` the strings to numerical
|
| 565 |
+
values and use the original strings for the output), or as a dict of
|
| 566 |
+
formula:value pairs.
|
| 567 |
+
|
| 568 |
+
In order not to produce spurious results, :func:`~mpmath.identify` should
|
| 569 |
+
be used with high precision; preferably 50 digits or more.
|
| 570 |
+
|
| 571 |
+
**Examples**
|
| 572 |
+
|
| 573 |
+
Simple identifications can be performed safely at standard
|
| 574 |
+
precision. Here the default recognition of rational, algebraic,
|
| 575 |
+
and exp/log of algebraic numbers is demonstrated::
|
| 576 |
+
|
| 577 |
+
>>> mp.dps = 15
|
| 578 |
+
>>> identify(0.22222222222222222)
|
| 579 |
+
'(2/9)'
|
| 580 |
+
>>> identify(1.9662210973805663)
|
| 581 |
+
'sqrt(((24+sqrt(48))/8))'
|
| 582 |
+
>>> identify(4.1132503787829275)
|
| 583 |
+
'exp((sqrt(8)/2))'
|
| 584 |
+
>>> identify(0.881373587019543)
|
| 585 |
+
'log(((2+sqrt(8))/2))'
|
| 586 |
+
|
| 587 |
+
By default, :func:`~mpmath.identify` does not recognize `\pi`. At standard
|
| 588 |
+
precision it finds a not too useful approximation. At slightly
|
| 589 |
+
increased precision, this approximation is no longer accurate
|
| 590 |
+
enough and :func:`~mpmath.identify` more correctly returns ``None``::
|
| 591 |
+
|
| 592 |
+
>>> identify(pi)
|
| 593 |
+
'(2**(176/117)*3**(20/117)*5**(35/39))/(7**(92/117))'
|
| 594 |
+
>>> mp.dps = 30
|
| 595 |
+
>>> identify(pi)
|
| 596 |
+
>>>
|
| 597 |
+
|
| 598 |
+
Numbers such as `\pi`, and simple combinations of user-defined
|
| 599 |
+
constants, can be identified if they are provided explicitly::
|
| 600 |
+
|
| 601 |
+
>>> identify(3*pi-2*e, ['pi', 'e'])
|
| 602 |
+
'(3*pi + (-2)*e)'
|
| 603 |
+
|
| 604 |
+
Here is an example using a dict of constants. Note that the
|
| 605 |
+
constants need not be "atomic"; :func:`~mpmath.identify` can just
|
| 606 |
+
as well express the given number in terms of expressions
|
| 607 |
+
given by formulas::
|
| 608 |
+
|
| 609 |
+
>>> identify(pi+e, {'a':pi+2, 'b':2*e})
|
| 610 |
+
'((-2) + 1*a + (1/2)*b)'
|
| 611 |
+
|
| 612 |
+
Next, we attempt some identifications with a set of base constants.
|
| 613 |
+
It is necessary to increase the precision a bit.
|
| 614 |
+
|
| 615 |
+
>>> mp.dps = 50
|
| 616 |
+
>>> base = ['sqrt(2)','pi','log(2)']
|
| 617 |
+
>>> identify(0.25, base)
|
| 618 |
+
'(1/4)'
|
| 619 |
+
>>> identify(3*pi + 2*sqrt(2) + 5*log(2)/7, base)
|
| 620 |
+
'(2*sqrt(2) + 3*pi + (5/7)*log(2))'
|
| 621 |
+
>>> identify(exp(pi+2), base)
|
| 622 |
+
'exp((2 + 1*pi))'
|
| 623 |
+
>>> identify(1/(3+sqrt(2)), base)
|
| 624 |
+
'((3/7) + (-1/7)*sqrt(2))'
|
| 625 |
+
>>> identify(sqrt(2)/(3*pi+4), base)
|
| 626 |
+
'sqrt(2)/(4 + 3*pi)'
|
| 627 |
+
>>> identify(5**(mpf(1)/3)*pi*log(2)**2, base)
|
| 628 |
+
'5**(1/3)*pi*log(2)**2'
|
| 629 |
+
|
| 630 |
+
An example of an erroneous solution being found when too low
|
| 631 |
+
precision is used::
|
| 632 |
+
|
| 633 |
+
>>> mp.dps = 15
|
| 634 |
+
>>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)'])
|
| 635 |
+
'((11/25) + (-158/75)*pi + (76/75)*e + (44/15)*sqrt(2))'
|
| 636 |
+
>>> mp.dps = 50
|
| 637 |
+
>>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)'])
|
| 638 |
+
'1/(3*pi + (-4)*e + 2*sqrt(2))'
|
| 639 |
+
|
| 640 |
+
**Finding approximate solutions**
|
| 641 |
+
|
| 642 |
+
The tolerance ``tol`` defaults to 3/4 of the working precision.
|
| 643 |
+
Lowering the tolerance is useful for finding approximate matches.
|
| 644 |
+
We can for example try to generate approximations for pi::
|
| 645 |
+
|
| 646 |
+
>>> mp.dps = 15
|
| 647 |
+
>>> identify(pi, tol=1e-2)
|
| 648 |
+
'(22/7)'
|
| 649 |
+
>>> identify(pi, tol=1e-3)
|
| 650 |
+
'(355/113)'
|
| 651 |
+
>>> identify(pi, tol=1e-10)
|
| 652 |
+
'(5**(339/269))/(2**(64/269)*3**(13/269)*7**(92/269))'
|
| 653 |
+
|
| 654 |
+
With ``full=True``, and by supplying a few base constants,
|
| 655 |
+
``identify`` can generate almost endless lists of approximations
|
| 656 |
+
for any number (the output below has been truncated to show only
|
| 657 |
+
the first few)::
|
| 658 |
+
|
| 659 |
+
>>> for p in identify(pi, ['e', 'catalan'], tol=1e-5, full=True):
|
| 660 |
+
... print(p)
|
| 661 |
+
... # doctest: +ELLIPSIS
|
| 662 |
+
e/log((6 + (-4/3)*e))
|
| 663 |
+
(3**3*5*e*catalan**2)/(2*7**2)
|
| 664 |
+
sqrt(((-13) + 1*e + 22*catalan))
|
| 665 |
+
log(((-6) + 24*e + 4*catalan)/e)
|
| 666 |
+
exp(catalan*((-1/5) + (8/15)*e))
|
| 667 |
+
catalan*(6 + (-6)*e + 15*catalan)
|
| 668 |
+
sqrt((5 + 26*e + (-3)*catalan))/e
|
| 669 |
+
e*sqrt(((-27) + 2*e + 25*catalan))
|
| 670 |
+
log(((-1) + (-11)*e + 59*catalan))
|
| 671 |
+
((3/20) + (21/20)*e + (3/20)*catalan)
|
| 672 |
+
...
|
| 673 |
+
|
| 674 |
+
The numerical values are roughly as close to `\pi` as permitted by the
|
| 675 |
+
specified tolerance:
|
| 676 |
+
|
| 677 |
+
>>> e/log(6-4*e/3)
|
| 678 |
+
3.14157719846001
|
| 679 |
+
>>> 135*e*catalan**2/98
|
| 680 |
+
3.14166950419369
|
| 681 |
+
>>> sqrt(e-13+22*catalan)
|
| 682 |
+
3.14158000062992
|
| 683 |
+
>>> log(24*e-6+4*catalan)-1
|
| 684 |
+
3.14158791577159
|
| 685 |
+
|
| 686 |
+
**Symbolic processing**
|
| 687 |
+
|
| 688 |
+
The output formula can be evaluated as a Python expression.
|
| 689 |
+
Note however that if fractions (like '2/3') are present in
|
| 690 |
+
the formula, Python's :func:`~mpmath.eval()` may erroneously perform
|
| 691 |
+
integer division. Note also that the output is not necessarily
|
| 692 |
+
in the algebraically simplest form::
|
| 693 |
+
|
| 694 |
+
>>> identify(sqrt(2))
|
| 695 |
+
'(sqrt(8)/2)'
|
| 696 |
+
|
| 697 |
+
As a solution to both problems, consider using SymPy's
|
| 698 |
+
:func:`~mpmath.sympify` to convert the formula into a symbolic expression.
|
| 699 |
+
SymPy can be used to pretty-print or further simplify the formula
|
| 700 |
+
symbolically::
|
| 701 |
+
|
| 702 |
+
>>> from sympy import sympify # doctest: +SKIP
|
| 703 |
+
>>> sympify(identify(sqrt(2))) # doctest: +SKIP
|
| 704 |
+
2**(1/2)
|
| 705 |
+
|
| 706 |
+
Sometimes :func:`~mpmath.identify` can simplify an expression further than
|
| 707 |
+
a symbolic algorithm::
|
| 708 |
+
|
| 709 |
+
>>> from sympy import simplify # doctest: +SKIP
|
| 710 |
+
>>> x = sympify('-1/(-3/2+(1/2)*5**(1/2))*(3/2-1/2*5**(1/2))**(1/2)') # doctest: +SKIP
|
| 711 |
+
>>> x # doctest: +SKIP
|
| 712 |
+
(3/2 - 5**(1/2)/2)**(-1/2)
|
| 713 |
+
>>> x = simplify(x) # doctest: +SKIP
|
| 714 |
+
>>> x # doctest: +SKIP
|
| 715 |
+
2/(6 - 2*5**(1/2))**(1/2)
|
| 716 |
+
>>> mp.dps = 30 # doctest: +SKIP
|
| 717 |
+
>>> x = sympify(identify(x.evalf(30))) # doctest: +SKIP
|
| 718 |
+
>>> x # doctest: +SKIP
|
| 719 |
+
1/2 + 5**(1/2)/2
|
| 720 |
+
|
| 721 |
+
(In fact, this functionality is available directly in SymPy as the
|
| 722 |
+
function :func:`~mpmath.nsimplify`, which is essentially a wrapper for
|
| 723 |
+
:func:`~mpmath.identify`.)
|
| 724 |
+
|
| 725 |
+
**Miscellaneous issues and limitations**
|
| 726 |
+
|
| 727 |
+
The input `x` must be a real number. All base constants must be
|
| 728 |
+
positive real numbers and must not be rationals or rational linear
|
| 729 |
+
combinations of each other.
|
| 730 |
+
|
| 731 |
+
The worst-case computation time grows quickly with the number of
|
| 732 |
+
base constants. Already with 3 or 4 base constants,
|
| 733 |
+
:func:`~mpmath.identify` may require several seconds to finish. To search
|
| 734 |
+
for relations among a large number of constants, you should
|
| 735 |
+
consider using :func:`~mpmath.pslq` directly.
|
| 736 |
+
|
| 737 |
+
The extended transformations are applied to x, not the constants
|
| 738 |
+
separately. As a result, ``identify`` will for example be able to
|
| 739 |
+
recognize ``exp(2*pi+3)`` with ``pi`` given as a base constant, but
|
| 740 |
+
not ``2*exp(pi)+3``. It will be able to recognize the latter if
|
| 741 |
+
``exp(pi)`` is given explicitly as a base constant.
|
| 742 |
+
|
| 743 |
+
"""
|
| 744 |
+
|
| 745 |
+
solutions = []
|
| 746 |
+
|
| 747 |
+
def addsolution(s):
|
| 748 |
+
if verbose: print("Found: ", s)
|
| 749 |
+
solutions.append(s)
|
| 750 |
+
|
| 751 |
+
x = ctx.mpf(x)
|
| 752 |
+
|
| 753 |
+
# Further along, x will be assumed positive
|
| 754 |
+
if x == 0:
|
| 755 |
+
if full: return ['0']
|
| 756 |
+
else: return '0'
|
| 757 |
+
if x < 0:
|
| 758 |
+
sol = ctx.identify(-x, constants, tol, maxcoeff, full, verbose)
|
| 759 |
+
if sol is None:
|
| 760 |
+
return sol
|
| 761 |
+
if full:
|
| 762 |
+
return ["-(%s)"%s for s in sol]
|
| 763 |
+
else:
|
| 764 |
+
return "-(%s)" % sol
|
| 765 |
+
|
| 766 |
+
if tol:
|
| 767 |
+
tol = ctx.mpf(tol)
|
| 768 |
+
else:
|
| 769 |
+
tol = ctx.eps**0.7
|
| 770 |
+
M = maxcoeff
|
| 771 |
+
|
| 772 |
+
if constants:
|
| 773 |
+
if isinstance(constants, dict):
|
| 774 |
+
constants = [(ctx.mpf(v), name) for (name, v) in sorted(constants.items())]
|
| 775 |
+
else:
|
| 776 |
+
namespace = dict((name, getattr(ctx,name)) for name in dir(ctx))
|
| 777 |
+
constants = [(eval(p, namespace), p) for p in constants]
|
| 778 |
+
else:
|
| 779 |
+
constants = []
|
| 780 |
+
|
| 781 |
+
# We always want to find at least rational terms
|
| 782 |
+
if 1 not in [value for (name, value) in constants]:
|
| 783 |
+
constants = [(ctx.mpf(1), '1')] + constants
|
| 784 |
+
|
| 785 |
+
# PSLQ with simple algebraic and functional transformations
|
| 786 |
+
for ft, ftn, red in transforms:
|
| 787 |
+
for c, cn in constants:
|
| 788 |
+
if red and cn == '1':
|
| 789 |
+
continue
|
| 790 |
+
t = ft(ctx,x,c)
|
| 791 |
+
# Prevent exponential transforms from wreaking havoc
|
| 792 |
+
if abs(t) > M**2 or abs(t) < tol:
|
| 793 |
+
continue
|
| 794 |
+
# Linear combination of base constants
|
| 795 |
+
r = ctx.pslq([t] + [a[0] for a in constants], tol, M)
|
| 796 |
+
s = None
|
| 797 |
+
if r is not None and max(abs(uw) for uw in r) <= M and r[0]:
|
| 798 |
+
s = pslqstring(r, constants)
|
| 799 |
+
# Quadratic algebraic numbers
|
| 800 |
+
else:
|
| 801 |
+
q = ctx.pslq([ctx.one, t, t**2], tol, M)
|
| 802 |
+
if q is not None and len(q) == 3 and q[2]:
|
| 803 |
+
aa, bb, cc = q
|
| 804 |
+
if max(abs(aa),abs(bb),abs(cc)) <= M:
|
| 805 |
+
s = quadraticstring(ctx,t,aa,bb,cc)
|
| 806 |
+
if s:
|
| 807 |
+
if cn == '1' and ('/$c' in ftn):
|
| 808 |
+
s = ftn.replace('$y', s).replace('/$c', '')
|
| 809 |
+
else:
|
| 810 |
+
s = ftn.replace('$y', s).replace('$c', cn)
|
| 811 |
+
addsolution(s)
|
| 812 |
+
if not full: return solutions[0]
|
| 813 |
+
|
| 814 |
+
if verbose:
|
| 815 |
+
print(".")
|
| 816 |
+
|
| 817 |
+
# Check for a direct multiplicative formula
|
| 818 |
+
if x != 1:
|
| 819 |
+
# Allow fractional powers of fractions
|
| 820 |
+
ilogs = [2,3,5,7]
|
| 821 |
+
# Watch out for existing fractional powers of fractions
|
| 822 |
+
logs = []
|
| 823 |
+
for a, s in constants:
|
| 824 |
+
if not sum(bool(ctx.findpoly(ctx.ln(a)/ctx.ln(i),1)) for i in ilogs):
|
| 825 |
+
logs.append((ctx.ln(a), s))
|
| 826 |
+
logs = [(ctx.ln(i),str(i)) for i in ilogs] + logs
|
| 827 |
+
r = ctx.pslq([ctx.ln(x)] + [a[0] for a in logs], tol, M)
|
| 828 |
+
if r is not None and max(abs(uw) for uw in r) <= M and r[0]:
|
| 829 |
+
addsolution(prodstring(r, logs))
|
| 830 |
+
if not full: return solutions[0]
|
| 831 |
+
|
| 832 |
+
if full:
|
| 833 |
+
return sorted(solutions, key=len)
|
| 834 |
+
else:
|
| 835 |
+
return None
|
| 836 |
+
|
| 837 |
+
IdentificationMethods.pslq = pslq
|
| 838 |
+
IdentificationMethods.findpoly = findpoly
|
| 839 |
+
IdentificationMethods.identify = identify
|
| 840 |
+
|
| 841 |
+
|
| 842 |
+
if __name__ == '__main__':
|
| 843 |
+
import doctest
|
| 844 |
+
doctest.testmod()
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__init__.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .libmpf import (prec_to_dps, dps_to_prec, repr_dps,
|
| 2 |
+
round_down, round_up, round_floor, round_ceiling, round_nearest,
|
| 3 |
+
to_pickable, from_pickable, ComplexResult,
|
| 4 |
+
fzero, fnzero, fone, fnone, ftwo, ften, fhalf, fnan, finf, fninf,
|
| 5 |
+
math_float_inf, round_int, normalize, normalize1,
|
| 6 |
+
from_man_exp, from_int, to_man_exp, to_int, mpf_ceil, mpf_floor,
|
| 7 |
+
mpf_nint, mpf_frac,
|
| 8 |
+
from_float, from_npfloat, from_Decimal, to_float, from_rational, to_rational, to_fixed,
|
| 9 |
+
mpf_rand, mpf_eq, mpf_hash, mpf_cmp, mpf_lt, mpf_le, mpf_gt, mpf_ge,
|
| 10 |
+
mpf_pos, mpf_neg, mpf_abs, mpf_sign, mpf_add, mpf_sub, mpf_sum,
|
| 11 |
+
mpf_mul, mpf_mul_int, mpf_shift, mpf_frexp,
|
| 12 |
+
mpf_div, mpf_rdiv_int, mpf_mod, mpf_pow_int,
|
| 13 |
+
mpf_perturb,
|
| 14 |
+
to_digits_exp, to_str, str_to_man_exp, from_str, from_bstr, to_bstr,
|
| 15 |
+
mpf_sqrt, mpf_hypot)
|
| 16 |
+
|
| 17 |
+
from .libmpc import (mpc_one, mpc_zero, mpc_two, mpc_half,
|
| 18 |
+
mpc_is_inf, mpc_is_infnan, mpc_to_str, mpc_to_complex, mpc_hash,
|
| 19 |
+
mpc_conjugate, mpc_is_nonzero, mpc_add, mpc_add_mpf,
|
| 20 |
+
mpc_sub, mpc_sub_mpf, mpc_pos, mpc_neg, mpc_shift, mpc_abs,
|
| 21 |
+
mpc_arg, mpc_floor, mpc_ceil, mpc_nint, mpc_frac, mpc_mul, mpc_square,
|
| 22 |
+
mpc_mul_mpf, mpc_mul_imag_mpf, mpc_mul_int,
|
| 23 |
+
mpc_div, mpc_div_mpf, mpc_reciprocal, mpc_mpf_div,
|
| 24 |
+
complex_int_pow, mpc_pow, mpc_pow_mpf, mpc_pow_int,
|
| 25 |
+
mpc_sqrt, mpc_nthroot, mpc_cbrt, mpc_exp, mpc_log, mpc_cos, mpc_sin,
|
| 26 |
+
mpc_tan, mpc_cos_pi, mpc_sin_pi, mpc_cosh, mpc_sinh, mpc_tanh,
|
| 27 |
+
mpc_atan, mpc_acos, mpc_asin, mpc_asinh, mpc_acosh, mpc_atanh,
|
| 28 |
+
mpc_fibonacci, mpf_expj, mpf_expjpi, mpc_expj, mpc_expjpi,
|
| 29 |
+
mpc_cos_sin, mpc_cos_sin_pi)
|
| 30 |
+
|
| 31 |
+
from .libelefun import (ln2_fixed, mpf_ln2, ln10_fixed, mpf_ln10,
|
| 32 |
+
pi_fixed, mpf_pi, e_fixed, mpf_e, phi_fixed, mpf_phi,
|
| 33 |
+
degree_fixed, mpf_degree,
|
| 34 |
+
mpf_pow, mpf_nthroot, mpf_cbrt, log_int_fixed, agm_fixed,
|
| 35 |
+
mpf_log, mpf_log_hypot, mpf_exp, mpf_cos_sin, mpf_cos, mpf_sin, mpf_tan,
|
| 36 |
+
mpf_cos_sin_pi, mpf_cos_pi, mpf_sin_pi, mpf_cosh_sinh,
|
| 37 |
+
mpf_cosh, mpf_sinh, mpf_tanh, mpf_atan, mpf_atan2, mpf_asin,
|
| 38 |
+
mpf_acos, mpf_asinh, mpf_acosh, mpf_atanh, mpf_fibonacci)
|
| 39 |
+
|
| 40 |
+
from .libhyper import (NoConvergence, make_hyp_summator,
|
| 41 |
+
mpf_erf, mpf_erfc, mpf_ei, mpc_ei, mpf_e1, mpc_e1, mpf_expint,
|
| 42 |
+
mpf_ci_si, mpf_ci, mpf_si, mpc_ci, mpc_si, mpf_besseljn,
|
| 43 |
+
mpc_besseljn, mpf_agm, mpf_agm1, mpc_agm, mpc_agm1,
|
| 44 |
+
mpf_ellipk, mpc_ellipk, mpf_ellipe, mpc_ellipe)
|
| 45 |
+
|
| 46 |
+
from .gammazeta import (catalan_fixed, mpf_catalan,
|
| 47 |
+
khinchin_fixed, mpf_khinchin, glaisher_fixed, mpf_glaisher,
|
| 48 |
+
apery_fixed, mpf_apery, euler_fixed, mpf_euler, mertens_fixed,
|
| 49 |
+
mpf_mertens, twinprime_fixed, mpf_twinprime,
|
| 50 |
+
mpf_bernoulli, bernfrac, mpf_gamma_int,
|
| 51 |
+
mpf_factorial, mpc_factorial, mpf_gamma, mpc_gamma,
|
| 52 |
+
mpf_loggamma, mpc_loggamma, mpf_rgamma, mpc_rgamma,
|
| 53 |
+
mpf_harmonic, mpc_harmonic, mpf_psi0, mpc_psi0,
|
| 54 |
+
mpf_psi, mpc_psi, mpf_zeta_int, mpf_zeta, mpc_zeta,
|
| 55 |
+
mpf_altzeta, mpc_altzeta, mpf_zetasum, mpc_zetasum)
|
| 56 |
+
|
| 57 |
+
from .libmpi import (mpi_str,
|
| 58 |
+
mpi_from_str, mpi_to_str,
|
| 59 |
+
mpi_eq, mpi_ne,
|
| 60 |
+
mpi_lt, mpi_le, mpi_gt, mpi_ge,
|
| 61 |
+
mpi_add, mpi_sub, mpi_delta, mpi_mid,
|
| 62 |
+
mpi_pos, mpi_neg, mpi_abs, mpi_mul, mpi_div, mpi_exp,
|
| 63 |
+
mpi_log, mpi_sqrt, mpi_pow_int, mpi_pow, mpi_cos_sin,
|
| 64 |
+
mpi_cos, mpi_sin, mpi_tan, mpi_cot,
|
| 65 |
+
mpi_atan, mpi_atan2,
|
| 66 |
+
mpci_pos, mpci_neg, mpci_add, mpci_sub, mpci_mul, mpci_div, mpci_pow,
|
| 67 |
+
mpci_abs, mpci_pow, mpci_exp, mpci_log, mpci_cos, mpci_sin,
|
| 68 |
+
mpi_gamma, mpci_gamma, mpi_loggamma, mpci_loggamma,
|
| 69 |
+
mpi_rgamma, mpci_rgamma, mpi_factorial, mpci_factorial)
|
| 70 |
+
|
| 71 |
+
from .libintmath import (trailing, bitcount, numeral, bin_to_radix,
|
| 72 |
+
isqrt, isqrt_small, isqrt_fast, sqrt_fixed, sqrtrem, ifib, ifac,
|
| 73 |
+
list_primes, isprime, moebius, gcd, eulernum, stirling1, stirling2)
|
| 74 |
+
|
| 75 |
+
from .backend import (gmpy, sage, BACKEND, STRICT, MPZ, MPZ_TYPE,
|
| 76 |
+
MPZ_ZERO, MPZ_ONE, MPZ_TWO, MPZ_THREE, MPZ_FIVE, int_types,
|
| 77 |
+
HASH_MODULUS, HASH_BITS)
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (10.4 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/backend.cpython-311.pyc
ADDED
|
Binary file (2.82 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/gammazeta.cpython-311.pyc
ADDED
|
Binary file (89 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libelefun.cpython-311.pyc
ADDED
|
Binary file (54.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libhyper.cpython-311.pyc
ADDED
|
Binary file (52.9 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libintmath.cpython-311.pyc
ADDED
|
Binary file (22.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libmpc.cpython-311.pyc
ADDED
|
Binary file (43.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libmpf.cpython-311.pyc
ADDED
|
Binary file (52.5 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/__pycache__/libmpi.cpython-311.pyc
ADDED
|
Binary file (43.4 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/mpmath/libmp/backend.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
#----------------------------------------------------------------------------#
|
| 5 |
+
# Support GMPY for high-speed large integer arithmetic. #
|
| 6 |
+
# #
|
| 7 |
+
# To allow an external module to handle arithmetic, we need to make sure #
|
| 8 |
+
# that all high-precision variables are declared of the correct type. MPZ #
|
| 9 |
+
# is the constructor for the high-precision type. It defaults to Python's #
|
| 10 |
+
# long type but can be assinged another type, typically gmpy.mpz. #
|
| 11 |
+
# #
|
| 12 |
+
# MPZ must be used for the mantissa component of an mpf and must be used #
|
| 13 |
+
# for internal fixed-point operations. #
|
| 14 |
+
# #
|
| 15 |
+
# Side-effects #
|
| 16 |
+
# 1) "is" cannot be used to test for special values. Must use "==". #
|
| 17 |
+
# 2) There are bugs in GMPY prior to v1.02 so we must use v1.03 or later. #
|
| 18 |
+
#----------------------------------------------------------------------------#
|
| 19 |
+
|
| 20 |
+
# So we can import it from this module
|
| 21 |
+
gmpy = None
|
| 22 |
+
sage = None
|
| 23 |
+
sage_utils = None
|
| 24 |
+
|
| 25 |
+
if sys.version_info[0] < 3:
|
| 26 |
+
python3 = False
|
| 27 |
+
else:
|
| 28 |
+
python3 = True
|
| 29 |
+
|
| 30 |
+
BACKEND = 'python'
|
| 31 |
+
|
| 32 |
+
if not python3:
|
| 33 |
+
MPZ = long
|
| 34 |
+
xrange = xrange
|
| 35 |
+
basestring = basestring
|
| 36 |
+
|
| 37 |
+
def exec_(_code_, _globs_=None, _locs_=None):
|
| 38 |
+
"""Execute code in a namespace."""
|
| 39 |
+
if _globs_ is None:
|
| 40 |
+
frame = sys._getframe(1)
|
| 41 |
+
_globs_ = frame.f_globals
|
| 42 |
+
if _locs_ is None:
|
| 43 |
+
_locs_ = frame.f_locals
|
| 44 |
+
del frame
|
| 45 |
+
elif _locs_ is None:
|
| 46 |
+
_locs_ = _globs_
|
| 47 |
+
exec("""exec _code_ in _globs_, _locs_""")
|
| 48 |
+
else:
|
| 49 |
+
MPZ = int
|
| 50 |
+
xrange = range
|
| 51 |
+
basestring = str
|
| 52 |
+
|
| 53 |
+
import builtins
|
| 54 |
+
exec_ = getattr(builtins, "exec")
|
| 55 |
+
|
| 56 |
+
# Define constants for calculating hash on Python 3.2.
|
| 57 |
+
if sys.version_info >= (3, 2):
|
| 58 |
+
HASH_MODULUS = sys.hash_info.modulus
|
| 59 |
+
if sys.hash_info.width == 32:
|
| 60 |
+
HASH_BITS = 31
|
| 61 |
+
else:
|
| 62 |
+
HASH_BITS = 61
|
| 63 |
+
else:
|
| 64 |
+
HASH_MODULUS = None
|
| 65 |
+
HASH_BITS = None
|
| 66 |
+
|
| 67 |
+
if 'MPMATH_NOGMPY' not in os.environ:
|
| 68 |
+
try:
|
| 69 |
+
try:
|
| 70 |
+
import gmpy2 as gmpy
|
| 71 |
+
except ImportError:
|
| 72 |
+
try:
|
| 73 |
+
import gmpy
|
| 74 |
+
except ImportError:
|
| 75 |
+
raise ImportError
|
| 76 |
+
if gmpy.version() >= '1.03':
|
| 77 |
+
BACKEND = 'gmpy'
|
| 78 |
+
MPZ = gmpy.mpz
|
| 79 |
+
except:
|
| 80 |
+
pass
|
| 81 |
+
|
| 82 |
+
if ('MPMATH_NOSAGE' not in os.environ and 'SAGE_ROOT' in os.environ or
|
| 83 |
+
'MPMATH_SAGE' in os.environ):
|
| 84 |
+
try:
|
| 85 |
+
import sage.all
|
| 86 |
+
import sage.libs.mpmath.utils as _sage_utils
|
| 87 |
+
sage = sage.all
|
| 88 |
+
sage_utils = _sage_utils
|
| 89 |
+
BACKEND = 'sage'
|
| 90 |
+
MPZ = sage.Integer
|
| 91 |
+
except:
|
| 92 |
+
pass
|
| 93 |
+
|
| 94 |
+
if 'MPMATH_STRICT' in os.environ:
|
| 95 |
+
STRICT = True
|
| 96 |
+
else:
|
| 97 |
+
STRICT = False
|
| 98 |
+
|
| 99 |
+
MPZ_TYPE = type(MPZ(0))
|
| 100 |
+
MPZ_ZERO = MPZ(0)
|
| 101 |
+
MPZ_ONE = MPZ(1)
|
| 102 |
+
MPZ_TWO = MPZ(2)
|
| 103 |
+
MPZ_THREE = MPZ(3)
|
| 104 |
+
MPZ_FIVE = MPZ(5)
|
| 105 |
+
|
| 106 |
+
try:
|
| 107 |
+
if BACKEND == 'python':
|
| 108 |
+
int_types = (int, long)
|
| 109 |
+
else:
|
| 110 |
+
int_types = (int, long, MPZ_TYPE)
|
| 111 |
+
except NameError:
|
| 112 |
+
if BACKEND == 'python':
|
| 113 |
+
int_types = (int,)
|
| 114 |
+
else:
|
| 115 |
+
int_types = (int, MPZ_TYPE)
|
.venv/lib/python3.11/site-packages/mpmath/libmp/gammazeta.py
ADDED
|
@@ -0,0 +1,2167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
-----------------------------------------------------------------------
|
| 3 |
+
This module implements gamma- and zeta-related functions:
|
| 4 |
+
|
| 5 |
+
* Bernoulli numbers
|
| 6 |
+
* Factorials
|
| 7 |
+
* The gamma function
|
| 8 |
+
* Polygamma functions
|
| 9 |
+
* Harmonic numbers
|
| 10 |
+
* The Riemann zeta function
|
| 11 |
+
* Constants related to these functions
|
| 12 |
+
|
| 13 |
+
-----------------------------------------------------------------------
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
import sys
|
| 18 |
+
|
| 19 |
+
from .backend import xrange
|
| 20 |
+
from .backend import MPZ, MPZ_ZERO, MPZ_ONE, MPZ_THREE, gmpy
|
| 21 |
+
|
| 22 |
+
from .libintmath import list_primes, ifac, ifac2, moebius
|
| 23 |
+
|
| 24 |
+
from .libmpf import (\
|
| 25 |
+
round_floor, round_ceiling, round_down, round_up,
|
| 26 |
+
round_nearest, round_fast,
|
| 27 |
+
lshift, sqrt_fixed, isqrt_fast,
|
| 28 |
+
fzero, fone, fnone, fhalf, ftwo, finf, fninf, fnan,
|
| 29 |
+
from_int, to_int, to_fixed, from_man_exp, from_rational,
|
| 30 |
+
mpf_pos, mpf_neg, mpf_abs, mpf_add, mpf_sub,
|
| 31 |
+
mpf_mul, mpf_mul_int, mpf_div, mpf_sqrt, mpf_pow_int,
|
| 32 |
+
mpf_rdiv_int,
|
| 33 |
+
mpf_perturb, mpf_le, mpf_lt, mpf_gt, mpf_shift,
|
| 34 |
+
negative_rnd, reciprocal_rnd,
|
| 35 |
+
bitcount, to_float, mpf_floor, mpf_sign, ComplexResult
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
from .libelefun import (\
|
| 39 |
+
constant_memo,
|
| 40 |
+
def_mpf_constant,
|
| 41 |
+
mpf_pi, pi_fixed, ln2_fixed, log_int_fixed, mpf_ln2,
|
| 42 |
+
mpf_exp, mpf_log, mpf_pow, mpf_cosh,
|
| 43 |
+
mpf_cos_sin, mpf_cosh_sinh, mpf_cos_sin_pi, mpf_cos_pi, mpf_sin_pi,
|
| 44 |
+
ln_sqrt2pi_fixed, mpf_ln_sqrt2pi, sqrtpi_fixed, mpf_sqrtpi,
|
| 45 |
+
cos_sin_fixed, exp_fixed
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
from .libmpc import (\
|
| 49 |
+
mpc_zero, mpc_one, mpc_half, mpc_two,
|
| 50 |
+
mpc_abs, mpc_shift, mpc_pos, mpc_neg,
|
| 51 |
+
mpc_add, mpc_sub, mpc_mul, mpc_div,
|
| 52 |
+
mpc_add_mpf, mpc_mul_mpf, mpc_div_mpf, mpc_mpf_div,
|
| 53 |
+
mpc_mul_int, mpc_pow_int,
|
| 54 |
+
mpc_log, mpc_exp, mpc_pow,
|
| 55 |
+
mpc_cos_pi, mpc_sin_pi,
|
| 56 |
+
mpc_reciprocal, mpc_square,
|
| 57 |
+
mpc_sub_mpf
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
# Catalan's constant is computed using Lupas's rapidly convergent series
|
| 63 |
+
# (listed on http://mathworld.wolfram.com/CatalansConstant.html)
|
| 64 |
+
# oo
|
| 65 |
+
# ___ n-1 8n 2 3 2
|
| 66 |
+
# 1 \ (-1) 2 (40n - 24n + 3) [(2n)!] (n!)
|
| 67 |
+
# K = --- ) -----------------------------------------
|
| 68 |
+
# 64 /___ 3 2
|
| 69 |
+
# n (2n-1) [(4n)!]
|
| 70 |
+
# n = 1
|
| 71 |
+
|
| 72 |
+
@constant_memo
|
| 73 |
+
def catalan_fixed(prec):
|
| 74 |
+
prec = prec + 20
|
| 75 |
+
a = one = MPZ_ONE << prec
|
| 76 |
+
s, t, n = 0, 1, 1
|
| 77 |
+
while t:
|
| 78 |
+
a *= 32 * n**3 * (2*n-1)
|
| 79 |
+
a //= (3-16*n+16*n**2)**2
|
| 80 |
+
t = a * (-1)**(n-1) * (40*n**2-24*n+3) // (n**3 * (2*n-1))
|
| 81 |
+
s += t
|
| 82 |
+
n += 1
|
| 83 |
+
return s >> (20 + 6)
|
| 84 |
+
|
| 85 |
+
# Khinchin's constant is relatively difficult to compute. Here
|
| 86 |
+
# we use the rational zeta series
|
| 87 |
+
|
| 88 |
+
# oo 2*n-1
|
| 89 |
+
# ___ ___
|
| 90 |
+
# \ ` zeta(2*n)-1 \ ` (-1)^(k+1)
|
| 91 |
+
# log(K)*log(2) = ) ------------ ) ----------
|
| 92 |
+
# /___. n /___. k
|
| 93 |
+
# n = 1 k = 1
|
| 94 |
+
|
| 95 |
+
# which adds half a digit per term. The essential trick for achieving
|
| 96 |
+
# reasonable efficiency is to recycle both the values of the zeta
|
| 97 |
+
# function (essentially Bernoulli numbers) and the partial terms of
|
| 98 |
+
# the inner sum.
|
| 99 |
+
|
| 100 |
+
# An alternative might be to use K = 2*exp[1/log(2) X] where
|
| 101 |
+
|
| 102 |
+
# / 1 1 [ pi*x*(1-x^2) ]
|
| 103 |
+
# X = | ------ log [ ------------ ].
|
| 104 |
+
# / 0 x(1+x) [ sin(pi*x) ]
|
| 105 |
+
|
| 106 |
+
# and integrate numerically. In practice, this seems to be slightly
|
| 107 |
+
# slower than the zeta series at high precision.
|
| 108 |
+
|
| 109 |
+
@constant_memo
|
| 110 |
+
def khinchin_fixed(prec):
|
| 111 |
+
wp = int(prec + prec**0.5 + 15)
|
| 112 |
+
s = MPZ_ZERO
|
| 113 |
+
fac = from_int(4)
|
| 114 |
+
t = ONE = MPZ_ONE << wp
|
| 115 |
+
pi = mpf_pi(wp)
|
| 116 |
+
pipow = twopi2 = mpf_shift(mpf_mul(pi, pi, wp), 2)
|
| 117 |
+
n = 1
|
| 118 |
+
while 1:
|
| 119 |
+
zeta2n = mpf_abs(mpf_bernoulli(2*n, wp))
|
| 120 |
+
zeta2n = mpf_mul(zeta2n, pipow, wp)
|
| 121 |
+
zeta2n = mpf_div(zeta2n, fac, wp)
|
| 122 |
+
zeta2n = to_fixed(zeta2n, wp)
|
| 123 |
+
term = (((zeta2n - ONE) * t) // n) >> wp
|
| 124 |
+
if term < 100:
|
| 125 |
+
break
|
| 126 |
+
#if not n % 10:
|
| 127 |
+
# print n, math.log(int(abs(term)))
|
| 128 |
+
s += term
|
| 129 |
+
t += ONE//(2*n+1) - ONE//(2*n)
|
| 130 |
+
n += 1
|
| 131 |
+
fac = mpf_mul_int(fac, (2*n)*(2*n-1), wp)
|
| 132 |
+
pipow = mpf_mul(pipow, twopi2, wp)
|
| 133 |
+
s = (s << wp) // ln2_fixed(wp)
|
| 134 |
+
K = mpf_exp(from_man_exp(s, -wp), wp)
|
| 135 |
+
K = to_fixed(K, prec)
|
| 136 |
+
return K
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
# Glaisher's constant is defined as A = exp(1/2 - zeta'(-1)).
|
| 140 |
+
# One way to compute it would be to perform direct numerical
|
| 141 |
+
# differentiation, but computing arbitrary Riemann zeta function
|
| 142 |
+
# values at high precision is expensive. We instead use the formula
|
| 143 |
+
|
| 144 |
+
# A = exp((6 (-zeta'(2))/pi^2 + log 2 pi + gamma)/12)
|
| 145 |
+
|
| 146 |
+
# and compute zeta'(2) from the series representation
|
| 147 |
+
|
| 148 |
+
# oo
|
| 149 |
+
# ___
|
| 150 |
+
# \ log k
|
| 151 |
+
# -zeta'(2) = ) -----
|
| 152 |
+
# /___ 2
|
| 153 |
+
# k
|
| 154 |
+
# k = 2
|
| 155 |
+
|
| 156 |
+
# This series converges exceptionally slowly, but can be accelerated
|
| 157 |
+
# using Euler-Maclaurin formula. The important insight is that the
|
| 158 |
+
# E-M integral can be done in closed form and that the high order
|
| 159 |
+
# are given by
|
| 160 |
+
|
| 161 |
+
# n / \
|
| 162 |
+
# d | log x | a + b log x
|
| 163 |
+
# --- | ----- | = -----------
|
| 164 |
+
# n | 2 | 2 + n
|
| 165 |
+
# dx \ x / x
|
| 166 |
+
|
| 167 |
+
# where a and b are integers given by a simple recurrence. Note
|
| 168 |
+
# that just one logarithm is needed. However, lots of integer
|
| 169 |
+
# logarithms are required for the initial summation.
|
| 170 |
+
|
| 171 |
+
# This algorithm could possibly be turned into a faster algorithm
|
| 172 |
+
# for general evaluation of zeta(s) or zeta'(s); this should be
|
| 173 |
+
# looked into.
|
| 174 |
+
|
| 175 |
+
@constant_memo
|
| 176 |
+
def glaisher_fixed(prec):
|
| 177 |
+
wp = prec + 30
|
| 178 |
+
# Number of direct terms to sum before applying the Euler-Maclaurin
|
| 179 |
+
# formula to the tail. TODO: choose more intelligently
|
| 180 |
+
N = int(0.33*prec + 5)
|
| 181 |
+
ONE = MPZ_ONE << wp
|
| 182 |
+
# Euler-Maclaurin, step 1: sum log(k)/k**2 for k from 2 to N-1
|
| 183 |
+
s = MPZ_ZERO
|
| 184 |
+
for k in range(2, N):
|
| 185 |
+
#print k, N
|
| 186 |
+
s += log_int_fixed(k, wp) // k**2
|
| 187 |
+
logN = log_int_fixed(N, wp)
|
| 188 |
+
#logN = to_fixed(mpf_log(from_int(N), wp+20), wp)
|
| 189 |
+
# E-M step 2: integral of log(x)/x**2 from N to inf
|
| 190 |
+
s += (ONE + logN) // N
|
| 191 |
+
# E-M step 3: endpoint correction term f(N)/2
|
| 192 |
+
s += logN // (N**2 * 2)
|
| 193 |
+
# E-M step 4: the series of derivatives
|
| 194 |
+
pN = N**3
|
| 195 |
+
a = 1
|
| 196 |
+
b = -2
|
| 197 |
+
j = 3
|
| 198 |
+
fac = from_int(2)
|
| 199 |
+
k = 1
|
| 200 |
+
while 1:
|
| 201 |
+
# D(2*k-1) * B(2*k) / fac(2*k) [D(n) = nth derivative]
|
| 202 |
+
D = ((a << wp) + b*logN) // pN
|
| 203 |
+
D = from_man_exp(D, -wp)
|
| 204 |
+
B = mpf_bernoulli(2*k, wp)
|
| 205 |
+
term = mpf_mul(B, D, wp)
|
| 206 |
+
term = mpf_div(term, fac, wp)
|
| 207 |
+
term = to_fixed(term, wp)
|
| 208 |
+
if abs(term) < 100:
|
| 209 |
+
break
|
| 210 |
+
#if not k % 10:
|
| 211 |
+
# print k, math.log(int(abs(term)), 10)
|
| 212 |
+
s -= term
|
| 213 |
+
# Advance derivative twice
|
| 214 |
+
a, b, pN, j = b-a*j, -j*b, pN*N, j+1
|
| 215 |
+
a, b, pN, j = b-a*j, -j*b, pN*N, j+1
|
| 216 |
+
k += 1
|
| 217 |
+
fac = mpf_mul_int(fac, (2*k)*(2*k-1), wp)
|
| 218 |
+
# A = exp((6*s/pi**2 + log(2*pi) + euler)/12)
|
| 219 |
+
pi = pi_fixed(wp)
|
| 220 |
+
s *= 6
|
| 221 |
+
s = (s << wp) // (pi**2 >> wp)
|
| 222 |
+
s += euler_fixed(wp)
|
| 223 |
+
s += to_fixed(mpf_log(from_man_exp(2*pi, -wp), wp), wp)
|
| 224 |
+
s //= 12
|
| 225 |
+
A = mpf_exp(from_man_exp(s, -wp), wp)
|
| 226 |
+
return to_fixed(A, prec)
|
| 227 |
+
|
| 228 |
+
# Apery's constant can be computed using the very rapidly convergent
|
| 229 |
+
# series
|
| 230 |
+
# oo
|
| 231 |
+
# ___ 2 10
|
| 232 |
+
# \ n 205 n + 250 n + 77 (n!)
|
| 233 |
+
# zeta(3) = ) (-1) ------------------- ----------
|
| 234 |
+
# /___ 64 5
|
| 235 |
+
# n = 0 ((2n+1)!)
|
| 236 |
+
|
| 237 |
+
@constant_memo
|
| 238 |
+
def apery_fixed(prec):
|
| 239 |
+
prec += 20
|
| 240 |
+
d = MPZ_ONE << prec
|
| 241 |
+
term = MPZ(77) << prec
|
| 242 |
+
n = 1
|
| 243 |
+
s = MPZ_ZERO
|
| 244 |
+
while term:
|
| 245 |
+
s += term
|
| 246 |
+
d *= (n**10)
|
| 247 |
+
d //= (((2*n+1)**5) * (2*n)**5)
|
| 248 |
+
term = (-1)**n * (205*(n**2) + 250*n + 77) * d
|
| 249 |
+
n += 1
|
| 250 |
+
return s >> (20 + 6)
|
| 251 |
+
|
| 252 |
+
"""
|
| 253 |
+
Euler's constant (gamma) is computed using the Brent-McMillan formula,
|
| 254 |
+
gamma ~= I(n)/J(n) - log(n), where
|
| 255 |
+
|
| 256 |
+
I(n) = sum_{k=0,1,2,...} (n**k / k!)**2 * H(k)
|
| 257 |
+
J(n) = sum_{k=0,1,2,...} (n**k / k!)**2
|
| 258 |
+
H(k) = 1 + 1/2 + 1/3 + ... + 1/k
|
| 259 |
+
|
| 260 |
+
The error is bounded by O(exp(-4n)). Choosing n to be a power
|
| 261 |
+
of two, 2**p, the logarithm becomes particularly easy to calculate.[1]
|
| 262 |
+
|
| 263 |
+
We use the formulation of Algorithm 3.9 in [2] to make the summation
|
| 264 |
+
more efficient.
|
| 265 |
+
|
| 266 |
+
Reference:
|
| 267 |
+
[1] Xavier Gourdon & Pascal Sebah, The Euler constant: gamma
|
| 268 |
+
http://numbers.computation.free.fr/Constants/Gamma/gamma.pdf
|
| 269 |
+
|
| 270 |
+
[2] [BorweinBailey]_
|
| 271 |
+
"""
|
| 272 |
+
|
| 273 |
+
@constant_memo
|
| 274 |
+
def euler_fixed(prec):
|
| 275 |
+
extra = 30
|
| 276 |
+
prec += extra
|
| 277 |
+
# choose p such that exp(-4*(2**p)) < 2**-n
|
| 278 |
+
p = int(math.log((prec/4) * math.log(2), 2)) + 1
|
| 279 |
+
n = 2**p
|
| 280 |
+
A = U = -p*ln2_fixed(prec)
|
| 281 |
+
B = V = MPZ_ONE << prec
|
| 282 |
+
k = 1
|
| 283 |
+
while 1:
|
| 284 |
+
B = B*n**2//k**2
|
| 285 |
+
A = (A*n**2//k + B)//k
|
| 286 |
+
U += A
|
| 287 |
+
V += B
|
| 288 |
+
if max(abs(A), abs(B)) < 100:
|
| 289 |
+
break
|
| 290 |
+
k += 1
|
| 291 |
+
return (U<<(prec-extra))//V
|
| 292 |
+
|
| 293 |
+
# Use zeta accelerated formulas for the Mertens and twin
|
| 294 |
+
# prime constants; see
|
| 295 |
+
# http://mathworld.wolfram.com/MertensConstant.html
|
| 296 |
+
# http://mathworld.wolfram.com/TwinPrimesConstant.html
|
| 297 |
+
|
| 298 |
+
@constant_memo
|
| 299 |
+
def mertens_fixed(prec):
|
| 300 |
+
wp = prec + 20
|
| 301 |
+
m = 2
|
| 302 |
+
s = mpf_euler(wp)
|
| 303 |
+
while 1:
|
| 304 |
+
t = mpf_zeta_int(m, wp)
|
| 305 |
+
if t == fone:
|
| 306 |
+
break
|
| 307 |
+
t = mpf_log(t, wp)
|
| 308 |
+
t = mpf_mul_int(t, moebius(m), wp)
|
| 309 |
+
t = mpf_div(t, from_int(m), wp)
|
| 310 |
+
s = mpf_add(s, t)
|
| 311 |
+
m += 1
|
| 312 |
+
return to_fixed(s, prec)
|
| 313 |
+
|
| 314 |
+
@constant_memo
|
| 315 |
+
def twinprime_fixed(prec):
|
| 316 |
+
def I(n):
|
| 317 |
+
return sum(moebius(d)<<(n//d) for d in xrange(1,n+1) if not n%d)//n
|
| 318 |
+
wp = 2*prec + 30
|
| 319 |
+
res = fone
|
| 320 |
+
primes = [from_rational(1,p,wp) for p in [2,3,5,7]]
|
| 321 |
+
ppowers = [mpf_mul(p,p,wp) for p in primes]
|
| 322 |
+
n = 2
|
| 323 |
+
while 1:
|
| 324 |
+
a = mpf_zeta_int(n, wp)
|
| 325 |
+
for i in range(4):
|
| 326 |
+
a = mpf_mul(a, mpf_sub(fone, ppowers[i]), wp)
|
| 327 |
+
ppowers[i] = mpf_mul(ppowers[i], primes[i], wp)
|
| 328 |
+
a = mpf_pow_int(a, -I(n), wp)
|
| 329 |
+
if mpf_pos(a, prec+10, 'n') == fone:
|
| 330 |
+
break
|
| 331 |
+
#from libmpf import to_str
|
| 332 |
+
#print n, to_str(mpf_sub(fone, a), 6)
|
| 333 |
+
res = mpf_mul(res, a, wp)
|
| 334 |
+
n += 1
|
| 335 |
+
res = mpf_mul(res, from_int(3*15*35), wp)
|
| 336 |
+
res = mpf_div(res, from_int(4*16*36), wp)
|
| 337 |
+
return to_fixed(res, prec)
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
mpf_euler = def_mpf_constant(euler_fixed)
|
| 341 |
+
mpf_apery = def_mpf_constant(apery_fixed)
|
| 342 |
+
mpf_khinchin = def_mpf_constant(khinchin_fixed)
|
| 343 |
+
mpf_glaisher = def_mpf_constant(glaisher_fixed)
|
| 344 |
+
mpf_catalan = def_mpf_constant(catalan_fixed)
|
| 345 |
+
mpf_mertens = def_mpf_constant(mertens_fixed)
|
| 346 |
+
mpf_twinprime = def_mpf_constant(twinprime_fixed)
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
#-----------------------------------------------------------------------#
|
| 350 |
+
# #
|
| 351 |
+
# Bernoulli numbers #
|
| 352 |
+
# #
|
| 353 |
+
#-----------------------------------------------------------------------#
|
| 354 |
+
|
| 355 |
+
MAX_BERNOULLI_CACHE = 3000
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
r"""
|
| 359 |
+
Small Bernoulli numbers and factorials are used in numerous summations,
|
| 360 |
+
so it is critical for speed that sequential computation is fast and that
|
| 361 |
+
values are cached up to a fairly high threshold.
|
| 362 |
+
|
| 363 |
+
On the other hand, we also want to support fast computation of isolated
|
| 364 |
+
large numbers. Currently, no such acceleration is provided for integer
|
| 365 |
+
factorials (though it is for large floating-point factorials, which are
|
| 366 |
+
computed via gamma if the precision is low enough).
|
| 367 |
+
|
| 368 |
+
For sequential computation of Bernoulli numbers, we use Ramanujan's formula
|
| 369 |
+
|
| 370 |
+
/ n + 3 \
|
| 371 |
+
B = (A(n) - S(n)) / | |
|
| 372 |
+
n \ n /
|
| 373 |
+
|
| 374 |
+
where A(n) = (n+3)/3 when n = 0 or 2 (mod 6), A(n) = -(n+3)/6
|
| 375 |
+
when n = 4 (mod 6), and
|
| 376 |
+
|
| 377 |
+
[n/6]
|
| 378 |
+
___
|
| 379 |
+
\ / n + 3 \
|
| 380 |
+
S(n) = ) | | * B
|
| 381 |
+
/___ \ n - 6*k / n-6*k
|
| 382 |
+
k = 1
|
| 383 |
+
|
| 384 |
+
For isolated large Bernoulli numbers, we use the Riemann zeta function
|
| 385 |
+
to calculate a numerical value for B_n. The von Staudt-Clausen theorem
|
| 386 |
+
can then be used to optionally find the exact value of the
|
| 387 |
+
numerator and denominator.
|
| 388 |
+
"""
|
| 389 |
+
|
| 390 |
+
bernoulli_cache = {}
|
| 391 |
+
f3 = from_int(3)
|
| 392 |
+
f6 = from_int(6)
|
| 393 |
+
|
| 394 |
+
def bernoulli_size(n):
|
| 395 |
+
"""Accurately estimate the size of B_n (even n > 2 only)"""
|
| 396 |
+
lgn = math.log(n,2)
|
| 397 |
+
return int(2.326 + 0.5*lgn + n*(lgn - 4.094))
|
| 398 |
+
|
| 399 |
+
BERNOULLI_PREC_CUTOFF = bernoulli_size(MAX_BERNOULLI_CACHE)
|
| 400 |
+
|
| 401 |
+
def mpf_bernoulli(n, prec, rnd=None):
|
| 402 |
+
"""Computation of Bernoulli numbers (numerically)"""
|
| 403 |
+
if n < 2:
|
| 404 |
+
if n < 0:
|
| 405 |
+
raise ValueError("Bernoulli numbers only defined for n >= 0")
|
| 406 |
+
if n == 0:
|
| 407 |
+
return fone
|
| 408 |
+
if n == 1:
|
| 409 |
+
return mpf_neg(fhalf)
|
| 410 |
+
# For odd n > 1, the Bernoulli numbers are zero
|
| 411 |
+
if n & 1:
|
| 412 |
+
return fzero
|
| 413 |
+
# If precision is extremely high, we can save time by computing
|
| 414 |
+
# the Bernoulli number at a lower precision that is sufficient to
|
| 415 |
+
# obtain the exact fraction, round to the exact fraction, and
|
| 416 |
+
# convert the fraction back to an mpf value at the original precision
|
| 417 |
+
if prec > BERNOULLI_PREC_CUTOFF and prec > bernoulli_size(n)*1.1 + 1000:
|
| 418 |
+
p, q = bernfrac(n)
|
| 419 |
+
return from_rational(p, q, prec, rnd or round_floor)
|
| 420 |
+
if n > MAX_BERNOULLI_CACHE:
|
| 421 |
+
return mpf_bernoulli_huge(n, prec, rnd)
|
| 422 |
+
wp = prec + 30
|
| 423 |
+
# Reuse nearby precisions
|
| 424 |
+
wp += 32 - (prec & 31)
|
| 425 |
+
cached = bernoulli_cache.get(wp)
|
| 426 |
+
if cached:
|
| 427 |
+
numbers, state = cached
|
| 428 |
+
if n in numbers:
|
| 429 |
+
if not rnd:
|
| 430 |
+
return numbers[n]
|
| 431 |
+
return mpf_pos(numbers[n], prec, rnd)
|
| 432 |
+
m, bin, bin1 = state
|
| 433 |
+
if n - m > 10:
|
| 434 |
+
return mpf_bernoulli_huge(n, prec, rnd)
|
| 435 |
+
else:
|
| 436 |
+
if n > 10:
|
| 437 |
+
return mpf_bernoulli_huge(n, prec, rnd)
|
| 438 |
+
numbers = {0:fone}
|
| 439 |
+
m, bin, bin1 = state = [2, MPZ(10), MPZ_ONE]
|
| 440 |
+
bernoulli_cache[wp] = (numbers, state)
|
| 441 |
+
while m <= n:
|
| 442 |
+
#print m
|
| 443 |
+
case = m % 6
|
| 444 |
+
# Accurately estimate size of B_m so we can use
|
| 445 |
+
# fixed point math without using too much precision
|
| 446 |
+
szbm = bernoulli_size(m)
|
| 447 |
+
s = 0
|
| 448 |
+
sexp = max(0, szbm) - wp
|
| 449 |
+
if m < 6:
|
| 450 |
+
a = MPZ_ZERO
|
| 451 |
+
else:
|
| 452 |
+
a = bin1
|
| 453 |
+
for j in xrange(1, m//6+1):
|
| 454 |
+
usign, uman, uexp, ubc = u = numbers[m-6*j]
|
| 455 |
+
if usign:
|
| 456 |
+
uman = -uman
|
| 457 |
+
s += lshift(a*uman, uexp-sexp)
|
| 458 |
+
# Update inner binomial coefficient
|
| 459 |
+
j6 = 6*j
|
| 460 |
+
a *= ((m-5-j6)*(m-4-j6)*(m-3-j6)*(m-2-j6)*(m-1-j6)*(m-j6))
|
| 461 |
+
a //= ((4+j6)*(5+j6)*(6+j6)*(7+j6)*(8+j6)*(9+j6))
|
| 462 |
+
if case == 0: b = mpf_rdiv_int(m+3, f3, wp)
|
| 463 |
+
if case == 2: b = mpf_rdiv_int(m+3, f3, wp)
|
| 464 |
+
if case == 4: b = mpf_rdiv_int(-m-3, f6, wp)
|
| 465 |
+
s = from_man_exp(s, sexp, wp)
|
| 466 |
+
b = mpf_div(mpf_sub(b, s, wp), from_int(bin), wp)
|
| 467 |
+
numbers[m] = b
|
| 468 |
+
m += 2
|
| 469 |
+
# Update outer binomial coefficient
|
| 470 |
+
bin = bin * ((m+2)*(m+3)) // (m*(m-1))
|
| 471 |
+
if m > 6:
|
| 472 |
+
bin1 = bin1 * ((2+m)*(3+m)) // ((m-7)*(m-6))
|
| 473 |
+
state[:] = [m, bin, bin1]
|
| 474 |
+
return numbers[n]
|
| 475 |
+
|
| 476 |
+
def mpf_bernoulli_huge(n, prec, rnd=None):
|
| 477 |
+
wp = prec + 10
|
| 478 |
+
piprec = wp + int(math.log(n,2))
|
| 479 |
+
v = mpf_gamma_int(n+1, wp)
|
| 480 |
+
v = mpf_mul(v, mpf_zeta_int(n, wp), wp)
|
| 481 |
+
v = mpf_mul(v, mpf_pow_int(mpf_pi(piprec), -n, wp))
|
| 482 |
+
v = mpf_shift(v, 1-n)
|
| 483 |
+
if not n & 3:
|
| 484 |
+
v = mpf_neg(v)
|
| 485 |
+
return mpf_pos(v, prec, rnd or round_fast)
|
| 486 |
+
|
| 487 |
+
def bernfrac(n):
|
| 488 |
+
r"""
|
| 489 |
+
Returns a tuple of integers `(p, q)` such that `p/q = B_n` exactly,
|
| 490 |
+
where `B_n` denotes the `n`-th Bernoulli number. The fraction is
|
| 491 |
+
always reduced to lowest terms. Note that for `n > 1` and `n` odd,
|
| 492 |
+
`B_n = 0`, and `(0, 1)` is returned.
|
| 493 |
+
|
| 494 |
+
**Examples**
|
| 495 |
+
|
| 496 |
+
The first few Bernoulli numbers are exactly::
|
| 497 |
+
|
| 498 |
+
>>> from mpmath import *
|
| 499 |
+
>>> for n in range(15):
|
| 500 |
+
... p, q = bernfrac(n)
|
| 501 |
+
... print("%s %s/%s" % (n, p, q))
|
| 502 |
+
...
|
| 503 |
+
0 1/1
|
| 504 |
+
1 -1/2
|
| 505 |
+
2 1/6
|
| 506 |
+
3 0/1
|
| 507 |
+
4 -1/30
|
| 508 |
+
5 0/1
|
| 509 |
+
6 1/42
|
| 510 |
+
7 0/1
|
| 511 |
+
8 -1/30
|
| 512 |
+
9 0/1
|
| 513 |
+
10 5/66
|
| 514 |
+
11 0/1
|
| 515 |
+
12 -691/2730
|
| 516 |
+
13 0/1
|
| 517 |
+
14 7/6
|
| 518 |
+
|
| 519 |
+
This function works for arbitrarily large `n`::
|
| 520 |
+
|
| 521 |
+
>>> p, q = bernfrac(10**4)
|
| 522 |
+
>>> print(q)
|
| 523 |
+
2338224387510
|
| 524 |
+
>>> print(len(str(p)))
|
| 525 |
+
27692
|
| 526 |
+
>>> mp.dps = 15
|
| 527 |
+
>>> print(mpf(p) / q)
|
| 528 |
+
-9.04942396360948e+27677
|
| 529 |
+
>>> print(bernoulli(10**4))
|
| 530 |
+
-9.04942396360948e+27677
|
| 531 |
+
|
| 532 |
+
.. note ::
|
| 533 |
+
|
| 534 |
+
:func:`~mpmath.bernoulli` computes a floating-point approximation
|
| 535 |
+
directly, without computing the exact fraction first.
|
| 536 |
+
This is much faster for large `n`.
|
| 537 |
+
|
| 538 |
+
**Algorithm**
|
| 539 |
+
|
| 540 |
+
:func:`~mpmath.bernfrac` works by computing the value of `B_n` numerically
|
| 541 |
+
and then using the von Staudt-Clausen theorem [1] to reconstruct
|
| 542 |
+
the exact fraction. For large `n`, this is significantly faster than
|
| 543 |
+
computing `B_1, B_2, \ldots, B_2` recursively with exact arithmetic.
|
| 544 |
+
The implementation has been tested for `n = 10^m` up to `m = 6`.
|
| 545 |
+
|
| 546 |
+
In practice, :func:`~mpmath.bernfrac` appears to be about three times
|
| 547 |
+
slower than the specialized program calcbn.exe [2]
|
| 548 |
+
|
| 549 |
+
**References**
|
| 550 |
+
|
| 551 |
+
1. MathWorld, von Staudt-Clausen Theorem:
|
| 552 |
+
http://mathworld.wolfram.com/vonStaudt-ClausenTheorem.html
|
| 553 |
+
|
| 554 |
+
2. The Bernoulli Number Page:
|
| 555 |
+
http://www.bernoulli.org/
|
| 556 |
+
|
| 557 |
+
"""
|
| 558 |
+
n = int(n)
|
| 559 |
+
if n < 3:
|
| 560 |
+
return [(1, 1), (-1, 2), (1, 6)][n]
|
| 561 |
+
if n & 1:
|
| 562 |
+
return (0, 1)
|
| 563 |
+
q = 1
|
| 564 |
+
for k in list_primes(n+1):
|
| 565 |
+
if not (n % (k-1)):
|
| 566 |
+
q *= k
|
| 567 |
+
prec = bernoulli_size(n) + int(math.log(q,2)) + 20
|
| 568 |
+
b = mpf_bernoulli(n, prec)
|
| 569 |
+
p = mpf_mul(b, from_int(q))
|
| 570 |
+
pint = to_int(p, round_nearest)
|
| 571 |
+
return (pint, q)
|
| 572 |
+
|
| 573 |
+
|
| 574 |
+
#-----------------------------------------------------------------------#
|
| 575 |
+
# #
|
| 576 |
+
# Polygamma functions #
|
| 577 |
+
# #
|
| 578 |
+
#-----------------------------------------------------------------------#
|
| 579 |
+
|
| 580 |
+
r"""
|
| 581 |
+
For all polygamma (psi) functions, we use the Euler-Maclaurin summation
|
| 582 |
+
formula. It looks slightly different in the m = 0 and m > 0 cases.
|
| 583 |
+
|
| 584 |
+
For m = 0, we have
|
| 585 |
+
oo
|
| 586 |
+
___ B
|
| 587 |
+
(0) 1 \ 2 k -2 k
|
| 588 |
+
psi (z) ~ log z + --- - ) ------ z
|
| 589 |
+
2 z /___ (2 k)!
|
| 590 |
+
k = 1
|
| 591 |
+
|
| 592 |
+
Experiment shows that the minimum term of the asymptotic series
|
| 593 |
+
reaches 2^(-p) when Re(z) > 0.11*p. So we simply use the recurrence
|
| 594 |
+
for psi (equivalent, in fact, to summing to the first few terms
|
| 595 |
+
directly before applying E-M) to obtain z large enough.
|
| 596 |
+
|
| 597 |
+
Since, very crudely, log z ~= 1 for Re(z) > 1, we can use
|
| 598 |
+
fixed-point arithmetic (if z is extremely large, log(z) itself
|
| 599 |
+
is a sufficient approximation, so we can stop there already).
|
| 600 |
+
|
| 601 |
+
For Re(z) << 0, we could use recurrence, but this is of course
|
| 602 |
+
inefficient for large negative z, so there we use the
|
| 603 |
+
reflection formula instead.
|
| 604 |
+
|
| 605 |
+
For m > 0, we have
|
| 606 |
+
|
| 607 |
+
N - 1
|
| 608 |
+
___
|
| 609 |
+
~~~(m) [ \ 1 ] 1 1
|
| 610 |
+
psi (z) ~ [ ) -------- ] + ---------- + -------- +
|
| 611 |
+
[ /___ m+1 ] m+1 m
|
| 612 |
+
k = 1 (z+k) ] 2 (z+N) m (z+N)
|
| 613 |
+
|
| 614 |
+
oo
|
| 615 |
+
___ B
|
| 616 |
+
\ 2 k (m+1) (m+2) ... (m+2k-1)
|
| 617 |
+
+ ) ------ ------------------------
|
| 618 |
+
/___ (2 k)! m + 2 k
|
| 619 |
+
k = 1 (z+N)
|
| 620 |
+
|
| 621 |
+
where ~~~ denotes the function rescaled by 1/((-1)^(m+1) m!).
|
| 622 |
+
|
| 623 |
+
Here again N is chosen to make z+N large enough for the minimum
|
| 624 |
+
term in the last series to become smaller than eps.
|
| 625 |
+
|
| 626 |
+
TODO: the current estimation of N for m > 0 is *very suboptimal*.
|
| 627 |
+
|
| 628 |
+
TODO: implement the reflection formula for m > 0, Re(z) << 0.
|
| 629 |
+
It is generally a combination of multiple cotangents. Need to
|
| 630 |
+
figure out a reasonably simple way to generate these formulas
|
| 631 |
+
on the fly.
|
| 632 |
+
|
| 633 |
+
TODO: maybe use exact algorithms to compute psi for integral
|
| 634 |
+
and certain rational arguments, as this can be much more
|
| 635 |
+
efficient. (On the other hand, the availability of these
|
| 636 |
+
special values provides a convenient way to test the general
|
| 637 |
+
algorithm.)
|
| 638 |
+
"""
|
| 639 |
+
|
| 640 |
+
# Harmonic numbers are just shifted digamma functions
|
| 641 |
+
# We should calculate these exactly when x is an integer
|
| 642 |
+
# and when doing so is faster.
|
| 643 |
+
|
| 644 |
+
def mpf_harmonic(x, prec, rnd):
|
| 645 |
+
if x in (fzero, fnan, finf):
|
| 646 |
+
return x
|
| 647 |
+
a = mpf_psi0(mpf_add(fone, x, prec+5), prec)
|
| 648 |
+
return mpf_add(a, mpf_euler(prec+5, rnd), prec, rnd)
|
| 649 |
+
|
| 650 |
+
def mpc_harmonic(z, prec, rnd):
|
| 651 |
+
if z[1] == fzero:
|
| 652 |
+
return (mpf_harmonic(z[0], prec, rnd), fzero)
|
| 653 |
+
a = mpc_psi0(mpc_add_mpf(z, fone, prec+5), prec)
|
| 654 |
+
return mpc_add_mpf(a, mpf_euler(prec+5, rnd), prec, rnd)
|
| 655 |
+
|
| 656 |
+
def mpf_psi0(x, prec, rnd=round_fast):
|
| 657 |
+
"""
|
| 658 |
+
Computation of the digamma function (psi function of order 0)
|
| 659 |
+
of a real argument.
|
| 660 |
+
"""
|
| 661 |
+
sign, man, exp, bc = x
|
| 662 |
+
wp = prec + 10
|
| 663 |
+
if not man:
|
| 664 |
+
if x == finf: return x
|
| 665 |
+
if x == fninf or x == fnan: return fnan
|
| 666 |
+
if x == fzero or (exp >= 0 and sign):
|
| 667 |
+
raise ValueError("polygamma pole")
|
| 668 |
+
# Near 0 -- fixed-point arithmetic becomes bad
|
| 669 |
+
if exp+bc < -5:
|
| 670 |
+
v = mpf_psi0(mpf_add(x, fone, prec, rnd), prec, rnd)
|
| 671 |
+
return mpf_sub(v, mpf_div(fone, x, wp, rnd), prec, rnd)
|
| 672 |
+
# Reflection formula
|
| 673 |
+
if sign and exp+bc > 3:
|
| 674 |
+
c, s = mpf_cos_sin_pi(x, wp)
|
| 675 |
+
q = mpf_mul(mpf_div(c, s, wp), mpf_pi(wp), wp)
|
| 676 |
+
p = mpf_psi0(mpf_sub(fone, x, wp), wp)
|
| 677 |
+
return mpf_sub(p, q, prec, rnd)
|
| 678 |
+
# The logarithmic term is accurate enough
|
| 679 |
+
if (not sign) and bc + exp > wp:
|
| 680 |
+
return mpf_log(mpf_sub(x, fone, wp), prec, rnd)
|
| 681 |
+
# Initial recurrence to obtain a large enough x
|
| 682 |
+
m = to_int(x)
|
| 683 |
+
n = int(0.11*wp) + 2
|
| 684 |
+
s = MPZ_ZERO
|
| 685 |
+
x = to_fixed(x, wp)
|
| 686 |
+
one = MPZ_ONE << wp
|
| 687 |
+
if m < n:
|
| 688 |
+
for k in xrange(m, n):
|
| 689 |
+
s -= (one << wp) // x
|
| 690 |
+
x += one
|
| 691 |
+
x -= one
|
| 692 |
+
# Logarithmic term
|
| 693 |
+
s += to_fixed(mpf_log(from_man_exp(x, -wp, wp), wp), wp)
|
| 694 |
+
# Endpoint term in Euler-Maclaurin expansion
|
| 695 |
+
s += (one << wp) // (2*x)
|
| 696 |
+
# Euler-Maclaurin remainder sum
|
| 697 |
+
x2 = (x*x) >> wp
|
| 698 |
+
t = one
|
| 699 |
+
prev = 0
|
| 700 |
+
k = 1
|
| 701 |
+
while 1:
|
| 702 |
+
t = (t*x2) >> wp
|
| 703 |
+
bsign, bman, bexp, bbc = mpf_bernoulli(2*k, wp)
|
| 704 |
+
offset = (bexp + 2*wp)
|
| 705 |
+
if offset >= 0: term = (bman << offset) // (t*(2*k))
|
| 706 |
+
else: term = (bman >> (-offset)) // (t*(2*k))
|
| 707 |
+
if k & 1: s -= term
|
| 708 |
+
else: s += term
|
| 709 |
+
if k > 2 and term >= prev:
|
| 710 |
+
break
|
| 711 |
+
prev = term
|
| 712 |
+
k += 1
|
| 713 |
+
return from_man_exp(s, -wp, wp, rnd)
|
| 714 |
+
|
| 715 |
+
def mpc_psi0(z, prec, rnd=round_fast):
|
| 716 |
+
"""
|
| 717 |
+
Computation of the digamma function (psi function of order 0)
|
| 718 |
+
of a complex argument.
|
| 719 |
+
"""
|
| 720 |
+
re, im = z
|
| 721 |
+
# Fall back to the real case
|
| 722 |
+
if im == fzero:
|
| 723 |
+
return (mpf_psi0(re, prec, rnd), fzero)
|
| 724 |
+
wp = prec + 20
|
| 725 |
+
sign, man, exp, bc = re
|
| 726 |
+
# Reflection formula
|
| 727 |
+
if sign and exp+bc > 3:
|
| 728 |
+
c = mpc_cos_pi(z, wp)
|
| 729 |
+
s = mpc_sin_pi(z, wp)
|
| 730 |
+
q = mpc_mul_mpf(mpc_div(c, s, wp), mpf_pi(wp), wp)
|
| 731 |
+
p = mpc_psi0(mpc_sub(mpc_one, z, wp), wp)
|
| 732 |
+
return mpc_sub(p, q, prec, rnd)
|
| 733 |
+
# Just the logarithmic term
|
| 734 |
+
if (not sign) and bc + exp > wp:
|
| 735 |
+
return mpc_log(mpc_sub(z, mpc_one, wp), prec, rnd)
|
| 736 |
+
# Initial recurrence to obtain a large enough z
|
| 737 |
+
w = to_int(re)
|
| 738 |
+
n = int(0.11*wp) + 2
|
| 739 |
+
s = mpc_zero
|
| 740 |
+
if w < n:
|
| 741 |
+
for k in xrange(w, n):
|
| 742 |
+
s = mpc_sub(s, mpc_reciprocal(z, wp), wp)
|
| 743 |
+
z = mpc_add_mpf(z, fone, wp)
|
| 744 |
+
z = mpc_sub(z, mpc_one, wp)
|
| 745 |
+
# Logarithmic and endpoint term
|
| 746 |
+
s = mpc_add(s, mpc_log(z, wp), wp)
|
| 747 |
+
s = mpc_add(s, mpc_div(mpc_half, z, wp), wp)
|
| 748 |
+
# Euler-Maclaurin remainder sum
|
| 749 |
+
z2 = mpc_square(z, wp)
|
| 750 |
+
t = mpc_one
|
| 751 |
+
prev = mpc_zero
|
| 752 |
+
szprev = fzero
|
| 753 |
+
k = 1
|
| 754 |
+
eps = mpf_shift(fone, -wp+2)
|
| 755 |
+
while 1:
|
| 756 |
+
t = mpc_mul(t, z2, wp)
|
| 757 |
+
bern = mpf_bernoulli(2*k, wp)
|
| 758 |
+
term = mpc_mpf_div(bern, mpc_mul_int(t, 2*k, wp), wp)
|
| 759 |
+
s = mpc_sub(s, term, wp)
|
| 760 |
+
szterm = mpc_abs(term, 10)
|
| 761 |
+
if k > 2 and (mpf_le(szterm, eps) or mpf_le(szprev, szterm)):
|
| 762 |
+
break
|
| 763 |
+
prev = term
|
| 764 |
+
szprev = szterm
|
| 765 |
+
k += 1
|
| 766 |
+
return s
|
| 767 |
+
|
| 768 |
+
# Currently unoptimized
|
| 769 |
+
def mpf_psi(m, x, prec, rnd=round_fast):
|
| 770 |
+
"""
|
| 771 |
+
Computation of the polygamma function of arbitrary integer order
|
| 772 |
+
m >= 0, for a real argument x.
|
| 773 |
+
"""
|
| 774 |
+
if m == 0:
|
| 775 |
+
return mpf_psi0(x, prec, rnd=round_fast)
|
| 776 |
+
return mpc_psi(m, (x, fzero), prec, rnd)[0]
|
| 777 |
+
|
| 778 |
+
def mpc_psi(m, z, prec, rnd=round_fast):
|
| 779 |
+
"""
|
| 780 |
+
Computation of the polygamma function of arbitrary integer order
|
| 781 |
+
m >= 0, for a complex argument z.
|
| 782 |
+
"""
|
| 783 |
+
if m == 0:
|
| 784 |
+
return mpc_psi0(z, prec, rnd)
|
| 785 |
+
re, im = z
|
| 786 |
+
wp = prec + 20
|
| 787 |
+
sign, man, exp, bc = re
|
| 788 |
+
if not im[1]:
|
| 789 |
+
if im in (finf, fninf, fnan):
|
| 790 |
+
return (fnan, fnan)
|
| 791 |
+
if not man:
|
| 792 |
+
if re == finf and im == fzero:
|
| 793 |
+
return (fzero, fzero)
|
| 794 |
+
if re == fnan:
|
| 795 |
+
return (fnan, fnan)
|
| 796 |
+
# Recurrence
|
| 797 |
+
w = to_int(re)
|
| 798 |
+
n = int(0.4*wp + 4*m)
|
| 799 |
+
s = mpc_zero
|
| 800 |
+
if w < n:
|
| 801 |
+
for k in xrange(w, n):
|
| 802 |
+
t = mpc_pow_int(z, -m-1, wp)
|
| 803 |
+
s = mpc_add(s, t, wp)
|
| 804 |
+
z = mpc_add_mpf(z, fone, wp)
|
| 805 |
+
zm = mpc_pow_int(z, -m, wp)
|
| 806 |
+
z2 = mpc_pow_int(z, -2, wp)
|
| 807 |
+
# 1/m*(z+N)^m
|
| 808 |
+
integral_term = mpc_div_mpf(zm, from_int(m), wp)
|
| 809 |
+
s = mpc_add(s, integral_term, wp)
|
| 810 |
+
# 1/2*(z+N)^(-(m+1))
|
| 811 |
+
s = mpc_add(s, mpc_mul_mpf(mpc_div(zm, z, wp), fhalf, wp), wp)
|
| 812 |
+
a = m + 1
|
| 813 |
+
b = 2
|
| 814 |
+
k = 1
|
| 815 |
+
# Important: we want to sum up to the *relative* error,
|
| 816 |
+
# not the absolute error, because psi^(m)(z) might be tiny
|
| 817 |
+
magn = mpc_abs(s, 10)
|
| 818 |
+
magn = magn[2]+magn[3]
|
| 819 |
+
eps = mpf_shift(fone, magn-wp+2)
|
| 820 |
+
while 1:
|
| 821 |
+
zm = mpc_mul(zm, z2, wp)
|
| 822 |
+
bern = mpf_bernoulli(2*k, wp)
|
| 823 |
+
scal = mpf_mul_int(bern, a, wp)
|
| 824 |
+
scal = mpf_div(scal, from_int(b), wp)
|
| 825 |
+
term = mpc_mul_mpf(zm, scal, wp)
|
| 826 |
+
s = mpc_add(s, term, wp)
|
| 827 |
+
szterm = mpc_abs(term, 10)
|
| 828 |
+
if k > 2 and mpf_le(szterm, eps):
|
| 829 |
+
break
|
| 830 |
+
#print k, to_str(szterm, 10), to_str(eps, 10)
|
| 831 |
+
a *= (m+2*k)*(m+2*k+1)
|
| 832 |
+
b *= (2*k+1)*(2*k+2)
|
| 833 |
+
k += 1
|
| 834 |
+
# Scale and sign factor
|
| 835 |
+
v = mpc_mul_mpf(s, mpf_gamma(from_int(m+1), wp), prec, rnd)
|
| 836 |
+
if not (m & 1):
|
| 837 |
+
v = mpf_neg(v[0]), mpf_neg(v[1])
|
| 838 |
+
return v
|
| 839 |
+
|
| 840 |
+
|
| 841 |
+
#-----------------------------------------------------------------------#
|
| 842 |
+
# #
|
| 843 |
+
# Riemann zeta function #
|
| 844 |
+
# #
|
| 845 |
+
#-----------------------------------------------------------------------#
|
| 846 |
+
|
| 847 |
+
r"""
|
| 848 |
+
We use zeta(s) = eta(s) / (1 - 2**(1-s)) and Borwein's approximation
|
| 849 |
+
|
| 850 |
+
n-1
|
| 851 |
+
___ k
|
| 852 |
+
-1 \ (-1) (d_k - d_n)
|
| 853 |
+
eta(s) ~= ---- ) ------------------
|
| 854 |
+
d_n /___ s
|
| 855 |
+
k = 0 (k + 1)
|
| 856 |
+
where
|
| 857 |
+
k
|
| 858 |
+
___ i
|
| 859 |
+
\ (n + i - 1)! 4
|
| 860 |
+
d_k = n ) ---------------.
|
| 861 |
+
/___ (n - i)! (2i)!
|
| 862 |
+
i = 0
|
| 863 |
+
|
| 864 |
+
If s = a + b*I, the absolute error for eta(s) is bounded by
|
| 865 |
+
|
| 866 |
+
3 (1 + 2|b|)
|
| 867 |
+
------------ * exp(|b| pi/2)
|
| 868 |
+
n
|
| 869 |
+
(3+sqrt(8))
|
| 870 |
+
|
| 871 |
+
Disregarding the linear term, we have approximately,
|
| 872 |
+
|
| 873 |
+
log(err) ~= log(exp(1.58*|b|)) - log(5.8**n)
|
| 874 |
+
log(err) ~= 1.58*|b| - log(5.8)*n
|
| 875 |
+
log(err) ~= 1.58*|b| - 1.76*n
|
| 876 |
+
log2(err) ~= 2.28*|b| - 2.54*n
|
| 877 |
+
|
| 878 |
+
So for p bits, we should choose n > (p + 2.28*|b|) / 2.54.
|
| 879 |
+
|
| 880 |
+
References:
|
| 881 |
+
-----------
|
| 882 |
+
|
| 883 |
+
Peter Borwein, "An Efficient Algorithm for the Riemann Zeta Function"
|
| 884 |
+
http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P117.ps
|
| 885 |
+
|
| 886 |
+
http://en.wikipedia.org/wiki/Dirichlet_eta_function
|
| 887 |
+
"""
|
| 888 |
+
|
| 889 |
+
borwein_cache = {}
|
| 890 |
+
|
| 891 |
+
def borwein_coefficients(n):
|
| 892 |
+
if n in borwein_cache:
|
| 893 |
+
return borwein_cache[n]
|
| 894 |
+
ds = [MPZ_ZERO] * (n+1)
|
| 895 |
+
d = MPZ_ONE
|
| 896 |
+
s = ds[0] = MPZ_ONE
|
| 897 |
+
for i in range(1, n+1):
|
| 898 |
+
d = d * 4 * (n+i-1) * (n-i+1)
|
| 899 |
+
d //= ((2*i) * ((2*i)-1))
|
| 900 |
+
s += d
|
| 901 |
+
ds[i] = s
|
| 902 |
+
borwein_cache[n] = ds
|
| 903 |
+
return ds
|
| 904 |
+
|
| 905 |
+
ZETA_INT_CACHE_MAX_PREC = 1000
|
| 906 |
+
zeta_int_cache = {}
|
| 907 |
+
|
| 908 |
+
def mpf_zeta_int(s, prec, rnd=round_fast):
|
| 909 |
+
"""
|
| 910 |
+
Optimized computation of zeta(s) for an integer s.
|
| 911 |
+
"""
|
| 912 |
+
wp = prec + 20
|
| 913 |
+
s = int(s)
|
| 914 |
+
if s in zeta_int_cache and zeta_int_cache[s][0] >= wp:
|
| 915 |
+
return mpf_pos(zeta_int_cache[s][1], prec, rnd)
|
| 916 |
+
if s < 2:
|
| 917 |
+
if s == 1:
|
| 918 |
+
raise ValueError("zeta(1) pole")
|
| 919 |
+
if not s:
|
| 920 |
+
return mpf_neg(fhalf)
|
| 921 |
+
return mpf_div(mpf_bernoulli(-s+1, wp), from_int(s-1), prec, rnd)
|
| 922 |
+
# 2^-s term vanishes?
|
| 923 |
+
if s >= wp:
|
| 924 |
+
return mpf_perturb(fone, 0, prec, rnd)
|
| 925 |
+
# 5^-s term vanishes?
|
| 926 |
+
elif s >= wp*0.431:
|
| 927 |
+
t = one = 1 << wp
|
| 928 |
+
t += 1 << (wp - s)
|
| 929 |
+
t += one // (MPZ_THREE ** s)
|
| 930 |
+
t += 1 << max(0, wp - s*2)
|
| 931 |
+
return from_man_exp(t, -wp, prec, rnd)
|
| 932 |
+
else:
|
| 933 |
+
# Fast enough to sum directly?
|
| 934 |
+
# Even better, we use the Euler product (idea stolen from pari)
|
| 935 |
+
m = (float(wp)/(s-1) + 1)
|
| 936 |
+
if m < 30:
|
| 937 |
+
needed_terms = int(2.0**m + 1)
|
| 938 |
+
if needed_terms < int(wp/2.54 + 5) / 10:
|
| 939 |
+
t = fone
|
| 940 |
+
for k in list_primes(needed_terms):
|
| 941 |
+
#print k, needed_terms
|
| 942 |
+
powprec = int(wp - s*math.log(k,2))
|
| 943 |
+
if powprec < 2:
|
| 944 |
+
break
|
| 945 |
+
a = mpf_sub(fone, mpf_pow_int(from_int(k), -s, powprec), wp)
|
| 946 |
+
t = mpf_mul(t, a, wp)
|
| 947 |
+
return mpf_div(fone, t, wp)
|
| 948 |
+
# Use Borwein's algorithm
|
| 949 |
+
n = int(wp/2.54 + 5)
|
| 950 |
+
d = borwein_coefficients(n)
|
| 951 |
+
t = MPZ_ZERO
|
| 952 |
+
s = MPZ(s)
|
| 953 |
+
for k in xrange(n):
|
| 954 |
+
t += (((-1)**k * (d[k] - d[n])) << wp) // (k+1)**s
|
| 955 |
+
t = (t << wp) // (-d[n])
|
| 956 |
+
t = (t << wp) // ((1 << wp) - (1 << (wp+1-s)))
|
| 957 |
+
if (s in zeta_int_cache and zeta_int_cache[s][0] < wp) or (s not in zeta_int_cache):
|
| 958 |
+
zeta_int_cache[s] = (wp, from_man_exp(t, -wp-wp))
|
| 959 |
+
return from_man_exp(t, -wp-wp, prec, rnd)
|
| 960 |
+
|
| 961 |
+
def mpf_zeta(s, prec, rnd=round_fast, alt=0):
|
| 962 |
+
sign, man, exp, bc = s
|
| 963 |
+
if not man:
|
| 964 |
+
if s == fzero:
|
| 965 |
+
if alt:
|
| 966 |
+
return fhalf
|
| 967 |
+
else:
|
| 968 |
+
return mpf_neg(fhalf)
|
| 969 |
+
if s == finf:
|
| 970 |
+
return fone
|
| 971 |
+
return fnan
|
| 972 |
+
wp = prec + 20
|
| 973 |
+
# First term vanishes?
|
| 974 |
+
if (not sign) and (exp + bc > (math.log(wp,2) + 2)):
|
| 975 |
+
return mpf_perturb(fone, alt, prec, rnd)
|
| 976 |
+
# Optimize for integer arguments
|
| 977 |
+
elif exp >= 0:
|
| 978 |
+
if alt:
|
| 979 |
+
if s == fone:
|
| 980 |
+
return mpf_ln2(prec, rnd)
|
| 981 |
+
z = mpf_zeta_int(to_int(s), wp, negative_rnd[rnd])
|
| 982 |
+
q = mpf_sub(fone, mpf_pow(ftwo, mpf_sub(fone, s, wp), wp), wp)
|
| 983 |
+
return mpf_mul(z, q, prec, rnd)
|
| 984 |
+
else:
|
| 985 |
+
return mpf_zeta_int(to_int(s), prec, rnd)
|
| 986 |
+
# Negative: use the reflection formula
|
| 987 |
+
# Borwein only proves the accuracy bound for x >= 1/2. However, based on
|
| 988 |
+
# tests, the accuracy without reflection is quite good even some distance
|
| 989 |
+
# to the left of 1/2. XXX: verify this.
|
| 990 |
+
if sign:
|
| 991 |
+
# XXX: could use the separate refl. formula for Dirichlet eta
|
| 992 |
+
if alt:
|
| 993 |
+
q = mpf_sub(fone, mpf_pow(ftwo, mpf_sub(fone, s, wp), wp), wp)
|
| 994 |
+
return mpf_mul(mpf_zeta(s, wp), q, prec, rnd)
|
| 995 |
+
# XXX: -1 should be done exactly
|
| 996 |
+
y = mpf_sub(fone, s, 10*wp)
|
| 997 |
+
a = mpf_gamma(y, wp)
|
| 998 |
+
b = mpf_zeta(y, wp)
|
| 999 |
+
c = mpf_sin_pi(mpf_shift(s, -1), wp)
|
| 1000 |
+
wp2 = wp + max(0,exp+bc)
|
| 1001 |
+
pi = mpf_pi(wp+wp2)
|
| 1002 |
+
d = mpf_div(mpf_pow(mpf_shift(pi, 1), s, wp2), pi, wp2)
|
| 1003 |
+
return mpf_mul(a,mpf_mul(b,mpf_mul(c,d,wp),wp),prec,rnd)
|
| 1004 |
+
|
| 1005 |
+
# Near pole
|
| 1006 |
+
r = mpf_sub(fone, s, wp)
|
| 1007 |
+
asign, aman, aexp, abc = mpf_abs(r)
|
| 1008 |
+
pole_dist = -2*(aexp+abc)
|
| 1009 |
+
if pole_dist > wp:
|
| 1010 |
+
if alt:
|
| 1011 |
+
return mpf_ln2(prec, rnd)
|
| 1012 |
+
else:
|
| 1013 |
+
q = mpf_neg(mpf_div(fone, r, wp))
|
| 1014 |
+
return mpf_add(q, mpf_euler(wp), prec, rnd)
|
| 1015 |
+
else:
|
| 1016 |
+
wp += max(0, pole_dist)
|
| 1017 |
+
|
| 1018 |
+
t = MPZ_ZERO
|
| 1019 |
+
#wp += 16 - (prec & 15)
|
| 1020 |
+
# Use Borwein's algorithm
|
| 1021 |
+
n = int(wp/2.54 + 5)
|
| 1022 |
+
d = borwein_coefficients(n)
|
| 1023 |
+
t = MPZ_ZERO
|
| 1024 |
+
sf = to_fixed(s, wp)
|
| 1025 |
+
ln2 = ln2_fixed(wp)
|
| 1026 |
+
for k in xrange(n):
|
| 1027 |
+
u = (-sf*log_int_fixed(k+1, wp, ln2)) >> wp
|
| 1028 |
+
#esign, eman, eexp, ebc = mpf_exp(u, wp)
|
| 1029 |
+
#offset = eexp + wp
|
| 1030 |
+
#if offset >= 0:
|
| 1031 |
+
# w = ((d[k] - d[n]) * eman) << offset
|
| 1032 |
+
#else:
|
| 1033 |
+
# w = ((d[k] - d[n]) * eman) >> (-offset)
|
| 1034 |
+
eman = exp_fixed(u, wp, ln2)
|
| 1035 |
+
w = (d[k] - d[n]) * eman
|
| 1036 |
+
if k & 1:
|
| 1037 |
+
t -= w
|
| 1038 |
+
else:
|
| 1039 |
+
t += w
|
| 1040 |
+
t = t // (-d[n])
|
| 1041 |
+
t = from_man_exp(t, -wp, wp)
|
| 1042 |
+
if alt:
|
| 1043 |
+
return mpf_pos(t, prec, rnd)
|
| 1044 |
+
else:
|
| 1045 |
+
q = mpf_sub(fone, mpf_pow(ftwo, mpf_sub(fone, s, wp), wp), wp)
|
| 1046 |
+
return mpf_div(t, q, prec, rnd)
|
| 1047 |
+
|
| 1048 |
+
def mpc_zeta(s, prec, rnd=round_fast, alt=0, force=False):
|
| 1049 |
+
re, im = s
|
| 1050 |
+
if im == fzero:
|
| 1051 |
+
return mpf_zeta(re, prec, rnd, alt), fzero
|
| 1052 |
+
|
| 1053 |
+
# slow for large s
|
| 1054 |
+
if (not force) and mpf_gt(mpc_abs(s, 10), from_int(prec)):
|
| 1055 |
+
raise NotImplementedError
|
| 1056 |
+
|
| 1057 |
+
wp = prec + 20
|
| 1058 |
+
|
| 1059 |
+
# Near pole
|
| 1060 |
+
r = mpc_sub(mpc_one, s, wp)
|
| 1061 |
+
asign, aman, aexp, abc = mpc_abs(r, 10)
|
| 1062 |
+
pole_dist = -2*(aexp+abc)
|
| 1063 |
+
if pole_dist > wp:
|
| 1064 |
+
if alt:
|
| 1065 |
+
q = mpf_ln2(wp)
|
| 1066 |
+
y = mpf_mul(q, mpf_euler(wp), wp)
|
| 1067 |
+
g = mpf_shift(mpf_mul(q, q, wp), -1)
|
| 1068 |
+
g = mpf_sub(y, g)
|
| 1069 |
+
z = mpc_mul_mpf(r, mpf_neg(g), wp)
|
| 1070 |
+
z = mpc_add_mpf(z, q, wp)
|
| 1071 |
+
return mpc_pos(z, prec, rnd)
|
| 1072 |
+
else:
|
| 1073 |
+
q = mpc_neg(mpc_div(mpc_one, r, wp))
|
| 1074 |
+
q = mpc_add_mpf(q, mpf_euler(wp), wp)
|
| 1075 |
+
return mpc_pos(q, prec, rnd)
|
| 1076 |
+
else:
|
| 1077 |
+
wp += max(0, pole_dist)
|
| 1078 |
+
|
| 1079 |
+
# Reflection formula. To be rigorous, we should reflect to the left of
|
| 1080 |
+
# re = 1/2 (see comments for mpf_zeta), but this leads to unnecessary
|
| 1081 |
+
# slowdown for interesting values of s
|
| 1082 |
+
if mpf_lt(re, fzero):
|
| 1083 |
+
# XXX: could use the separate refl. formula for Dirichlet eta
|
| 1084 |
+
if alt:
|
| 1085 |
+
q = mpc_sub(mpc_one, mpc_pow(mpc_two, mpc_sub(mpc_one, s, wp),
|
| 1086 |
+
wp), wp)
|
| 1087 |
+
return mpc_mul(mpc_zeta(s, wp), q, prec, rnd)
|
| 1088 |
+
# XXX: -1 should be done exactly
|
| 1089 |
+
y = mpc_sub(mpc_one, s, 10*wp)
|
| 1090 |
+
a = mpc_gamma(y, wp)
|
| 1091 |
+
b = mpc_zeta(y, wp)
|
| 1092 |
+
c = mpc_sin_pi(mpc_shift(s, -1), wp)
|
| 1093 |
+
rsign, rman, rexp, rbc = re
|
| 1094 |
+
isign, iman, iexp, ibc = im
|
| 1095 |
+
mag = max(rexp+rbc, iexp+ibc)
|
| 1096 |
+
wp2 = wp + max(0, mag)
|
| 1097 |
+
pi = mpf_pi(wp+wp2)
|
| 1098 |
+
pi2 = (mpf_shift(pi, 1), fzero)
|
| 1099 |
+
d = mpc_div_mpf(mpc_pow(pi2, s, wp2), pi, wp2)
|
| 1100 |
+
return mpc_mul(a,mpc_mul(b,mpc_mul(c,d,wp),wp),prec,rnd)
|
| 1101 |
+
n = int(wp/2.54 + 5)
|
| 1102 |
+
n += int(0.9*abs(to_int(im)))
|
| 1103 |
+
d = borwein_coefficients(n)
|
| 1104 |
+
ref = to_fixed(re, wp)
|
| 1105 |
+
imf = to_fixed(im, wp)
|
| 1106 |
+
tre = MPZ_ZERO
|
| 1107 |
+
tim = MPZ_ZERO
|
| 1108 |
+
one = MPZ_ONE << wp
|
| 1109 |
+
one_2wp = MPZ_ONE << (2*wp)
|
| 1110 |
+
critical_line = re == fhalf
|
| 1111 |
+
ln2 = ln2_fixed(wp)
|
| 1112 |
+
pi2 = pi_fixed(wp-1)
|
| 1113 |
+
wp2 = wp+wp
|
| 1114 |
+
for k in xrange(n):
|
| 1115 |
+
log = log_int_fixed(k+1, wp, ln2)
|
| 1116 |
+
# A square root is much cheaper than an exp
|
| 1117 |
+
if critical_line:
|
| 1118 |
+
w = one_2wp // isqrt_fast((k+1) << wp2)
|
| 1119 |
+
else:
|
| 1120 |
+
w = exp_fixed((-ref*log) >> wp, wp)
|
| 1121 |
+
if k & 1:
|
| 1122 |
+
w *= (d[n] - d[k])
|
| 1123 |
+
else:
|
| 1124 |
+
w *= (d[k] - d[n])
|
| 1125 |
+
wre, wim = cos_sin_fixed((-imf*log)>>wp, wp, pi2)
|
| 1126 |
+
tre += (w * wre) >> wp
|
| 1127 |
+
tim += (w * wim) >> wp
|
| 1128 |
+
tre //= (-d[n])
|
| 1129 |
+
tim //= (-d[n])
|
| 1130 |
+
tre = from_man_exp(tre, -wp, wp)
|
| 1131 |
+
tim = from_man_exp(tim, -wp, wp)
|
| 1132 |
+
if alt:
|
| 1133 |
+
return mpc_pos((tre, tim), prec, rnd)
|
| 1134 |
+
else:
|
| 1135 |
+
q = mpc_sub(mpc_one, mpc_pow(mpc_two, r, wp), wp)
|
| 1136 |
+
return mpc_div((tre, tim), q, prec, rnd)
|
| 1137 |
+
|
| 1138 |
+
def mpf_altzeta(s, prec, rnd=round_fast):
|
| 1139 |
+
return mpf_zeta(s, prec, rnd, 1)
|
| 1140 |
+
|
| 1141 |
+
def mpc_altzeta(s, prec, rnd=round_fast):
|
| 1142 |
+
return mpc_zeta(s, prec, rnd, 1)
|
| 1143 |
+
|
| 1144 |
+
# Not optimized currently
|
| 1145 |
+
mpf_zetasum = None
|
| 1146 |
+
|
| 1147 |
+
|
| 1148 |
+
def pow_fixed(x, n, wp):
|
| 1149 |
+
if n == 1:
|
| 1150 |
+
return x
|
| 1151 |
+
y = MPZ_ONE << wp
|
| 1152 |
+
while n:
|
| 1153 |
+
if n & 1:
|
| 1154 |
+
y = (y*x) >> wp
|
| 1155 |
+
n -= 1
|
| 1156 |
+
x = (x*x) >> wp
|
| 1157 |
+
n //= 2
|
| 1158 |
+
return y
|
| 1159 |
+
|
| 1160 |
+
# TODO: optimize / cleanup interface / unify with list_primes
|
| 1161 |
+
sieve_cache = []
|
| 1162 |
+
primes_cache = []
|
| 1163 |
+
mult_cache = []
|
| 1164 |
+
|
| 1165 |
+
def primesieve(n):
|
| 1166 |
+
global sieve_cache, primes_cache, mult_cache
|
| 1167 |
+
if n < len(sieve_cache):
|
| 1168 |
+
sieve = sieve_cache#[:n+1]
|
| 1169 |
+
primes = primes_cache[:primes_cache.index(max(sieve))+1]
|
| 1170 |
+
mult = mult_cache#[:n+1]
|
| 1171 |
+
return sieve, primes, mult
|
| 1172 |
+
sieve = [0] * (n+1)
|
| 1173 |
+
mult = [0] * (n+1)
|
| 1174 |
+
primes = list_primes(n)
|
| 1175 |
+
for p in primes:
|
| 1176 |
+
#sieve[p::p] = p
|
| 1177 |
+
for k in xrange(p,n+1,p):
|
| 1178 |
+
sieve[k] = p
|
| 1179 |
+
for i, p in enumerate(sieve):
|
| 1180 |
+
if i >= 2:
|
| 1181 |
+
m = 1
|
| 1182 |
+
n = i // p
|
| 1183 |
+
while not n % p:
|
| 1184 |
+
n //= p
|
| 1185 |
+
m += 1
|
| 1186 |
+
mult[i] = m
|
| 1187 |
+
sieve_cache = sieve
|
| 1188 |
+
primes_cache = primes
|
| 1189 |
+
mult_cache = mult
|
| 1190 |
+
return sieve, primes, mult
|
| 1191 |
+
|
| 1192 |
+
def zetasum_sieved(critical_line, sre, sim, a, n, wp):
|
| 1193 |
+
if a < 1:
|
| 1194 |
+
raise ValueError("a cannot be less than 1")
|
| 1195 |
+
sieve, primes, mult = primesieve(a+n)
|
| 1196 |
+
basic_powers = {}
|
| 1197 |
+
one = MPZ_ONE << wp
|
| 1198 |
+
one_2wp = MPZ_ONE << (2*wp)
|
| 1199 |
+
wp2 = wp+wp
|
| 1200 |
+
ln2 = ln2_fixed(wp)
|
| 1201 |
+
pi2 = pi_fixed(wp-1)
|
| 1202 |
+
for p in primes:
|
| 1203 |
+
if p*2 > a+n:
|
| 1204 |
+
break
|
| 1205 |
+
log = log_int_fixed(p, wp, ln2)
|
| 1206 |
+
cos, sin = cos_sin_fixed((-sim*log)>>wp, wp, pi2)
|
| 1207 |
+
if critical_line:
|
| 1208 |
+
u = one_2wp // isqrt_fast(p<<wp2)
|
| 1209 |
+
else:
|
| 1210 |
+
u = exp_fixed((-sre*log)>>wp, wp)
|
| 1211 |
+
pre = (u*cos) >> wp
|
| 1212 |
+
pim = (u*sin) >> wp
|
| 1213 |
+
basic_powers[p] = [(pre, pim)]
|
| 1214 |
+
tre, tim = pre, pim
|
| 1215 |
+
for m in range(1,int(math.log(a+n,p)+0.01)+1):
|
| 1216 |
+
tre, tim = ((pre*tre-pim*tim)>>wp), ((pim*tre+pre*tim)>>wp)
|
| 1217 |
+
basic_powers[p].append((tre,tim))
|
| 1218 |
+
xre = MPZ_ZERO
|
| 1219 |
+
xim = MPZ_ZERO
|
| 1220 |
+
if a == 1:
|
| 1221 |
+
xre += one
|
| 1222 |
+
aa = max(a,2)
|
| 1223 |
+
for k in xrange(aa, a+n+1):
|
| 1224 |
+
p = sieve[k]
|
| 1225 |
+
if p in basic_powers:
|
| 1226 |
+
m = mult[k]
|
| 1227 |
+
tre, tim = basic_powers[p][m-1]
|
| 1228 |
+
while 1:
|
| 1229 |
+
k //= p**m
|
| 1230 |
+
if k == 1:
|
| 1231 |
+
break
|
| 1232 |
+
p = sieve[k]
|
| 1233 |
+
m = mult[k]
|
| 1234 |
+
pre, pim = basic_powers[p][m-1]
|
| 1235 |
+
tre, tim = ((pre*tre-pim*tim)>>wp), ((pim*tre+pre*tim)>>wp)
|
| 1236 |
+
else:
|
| 1237 |
+
log = log_int_fixed(k, wp, ln2)
|
| 1238 |
+
cos, sin = cos_sin_fixed((-sim*log)>>wp, wp, pi2)
|
| 1239 |
+
if critical_line:
|
| 1240 |
+
u = one_2wp // isqrt_fast(k<<wp2)
|
| 1241 |
+
else:
|
| 1242 |
+
u = exp_fixed((-sre*log)>>wp, wp)
|
| 1243 |
+
tre = (u*cos) >> wp
|
| 1244 |
+
tim = (u*sin) >> wp
|
| 1245 |
+
xre += tre
|
| 1246 |
+
xim += tim
|
| 1247 |
+
return xre, xim
|
| 1248 |
+
|
| 1249 |
+
# Set to something large to disable
|
| 1250 |
+
ZETASUM_SIEVE_CUTOFF = 10
|
| 1251 |
+
|
| 1252 |
+
def mpc_zetasum(s, a, n, derivatives, reflect, prec):
|
| 1253 |
+
"""
|
| 1254 |
+
Fast version of mp._zetasum, assuming s = complex, a = integer.
|
| 1255 |
+
"""
|
| 1256 |
+
|
| 1257 |
+
wp = prec + 10
|
| 1258 |
+
derivatives = list(derivatives)
|
| 1259 |
+
have_derivatives = derivatives != [0]
|
| 1260 |
+
have_one_derivative = len(derivatives) == 1
|
| 1261 |
+
|
| 1262 |
+
# parse s
|
| 1263 |
+
sre, sim = s
|
| 1264 |
+
critical_line = (sre == fhalf)
|
| 1265 |
+
sre = to_fixed(sre, wp)
|
| 1266 |
+
sim = to_fixed(sim, wp)
|
| 1267 |
+
|
| 1268 |
+
if a > 0 and n > ZETASUM_SIEVE_CUTOFF and not have_derivatives \
|
| 1269 |
+
and not reflect and (n < 4e7 or sys.maxsize > 2**32):
|
| 1270 |
+
re, im = zetasum_sieved(critical_line, sre, sim, a, n, wp)
|
| 1271 |
+
xs = [(from_man_exp(re, -wp, prec, 'n'), from_man_exp(im, -wp, prec, 'n'))]
|
| 1272 |
+
return xs, []
|
| 1273 |
+
|
| 1274 |
+
maxd = max(derivatives)
|
| 1275 |
+
if not have_one_derivative:
|
| 1276 |
+
derivatives = range(maxd+1)
|
| 1277 |
+
|
| 1278 |
+
# x_d = 0, y_d = 0
|
| 1279 |
+
xre = [MPZ_ZERO for d in derivatives]
|
| 1280 |
+
xim = [MPZ_ZERO for d in derivatives]
|
| 1281 |
+
if reflect:
|
| 1282 |
+
yre = [MPZ_ZERO for d in derivatives]
|
| 1283 |
+
yim = [MPZ_ZERO for d in derivatives]
|
| 1284 |
+
else:
|
| 1285 |
+
yre = yim = []
|
| 1286 |
+
|
| 1287 |
+
one = MPZ_ONE << wp
|
| 1288 |
+
one_2wp = MPZ_ONE << (2*wp)
|
| 1289 |
+
|
| 1290 |
+
ln2 = ln2_fixed(wp)
|
| 1291 |
+
pi2 = pi_fixed(wp-1)
|
| 1292 |
+
wp2 = wp+wp
|
| 1293 |
+
|
| 1294 |
+
for w in xrange(a, a+n+1):
|
| 1295 |
+
log = log_int_fixed(w, wp, ln2)
|
| 1296 |
+
cos, sin = cos_sin_fixed((-sim*log)>>wp, wp, pi2)
|
| 1297 |
+
if critical_line:
|
| 1298 |
+
u = one_2wp // isqrt_fast(w<<wp2)
|
| 1299 |
+
else:
|
| 1300 |
+
u = exp_fixed((-sre*log)>>wp, wp)
|
| 1301 |
+
xterm_re = (u * cos) >> wp
|
| 1302 |
+
xterm_im = (u * sin) >> wp
|
| 1303 |
+
if reflect:
|
| 1304 |
+
reciprocal = (one_2wp // (u*w))
|
| 1305 |
+
yterm_re = (reciprocal * cos) >> wp
|
| 1306 |
+
yterm_im = (reciprocal * sin) >> wp
|
| 1307 |
+
|
| 1308 |
+
if have_derivatives:
|
| 1309 |
+
if have_one_derivative:
|
| 1310 |
+
log = pow_fixed(log, maxd, wp)
|
| 1311 |
+
xre[0] += (xterm_re * log) >> wp
|
| 1312 |
+
xim[0] += (xterm_im * log) >> wp
|
| 1313 |
+
if reflect:
|
| 1314 |
+
yre[0] += (yterm_re * log) >> wp
|
| 1315 |
+
yim[0] += (yterm_im * log) >> wp
|
| 1316 |
+
else:
|
| 1317 |
+
t = MPZ_ONE << wp
|
| 1318 |
+
for d in derivatives:
|
| 1319 |
+
xre[d] += (xterm_re * t) >> wp
|
| 1320 |
+
xim[d] += (xterm_im * t) >> wp
|
| 1321 |
+
if reflect:
|
| 1322 |
+
yre[d] += (yterm_re * t) >> wp
|
| 1323 |
+
yim[d] += (yterm_im * t) >> wp
|
| 1324 |
+
t = (t * log) >> wp
|
| 1325 |
+
else:
|
| 1326 |
+
xre[0] += xterm_re
|
| 1327 |
+
xim[0] += xterm_im
|
| 1328 |
+
if reflect:
|
| 1329 |
+
yre[0] += yterm_re
|
| 1330 |
+
yim[0] += yterm_im
|
| 1331 |
+
if have_derivatives:
|
| 1332 |
+
if have_one_derivative:
|
| 1333 |
+
if maxd % 2:
|
| 1334 |
+
xre[0] = -xre[0]
|
| 1335 |
+
xim[0] = -xim[0]
|
| 1336 |
+
if reflect:
|
| 1337 |
+
yre[0] = -yre[0]
|
| 1338 |
+
yim[0] = -yim[0]
|
| 1339 |
+
else:
|
| 1340 |
+
xre = [(-1)**d * xre[d] for d in derivatives]
|
| 1341 |
+
xim = [(-1)**d * xim[d] for d in derivatives]
|
| 1342 |
+
if reflect:
|
| 1343 |
+
yre = [(-1)**d * yre[d] for d in derivatives]
|
| 1344 |
+
yim = [(-1)**d * yim[d] for d in derivatives]
|
| 1345 |
+
xs = [(from_man_exp(xa, -wp, prec, 'n'), from_man_exp(xb, -wp, prec, 'n'))
|
| 1346 |
+
for (xa, xb) in zip(xre, xim)]
|
| 1347 |
+
ys = [(from_man_exp(ya, -wp, prec, 'n'), from_man_exp(yb, -wp, prec, 'n'))
|
| 1348 |
+
for (ya, yb) in zip(yre, yim)]
|
| 1349 |
+
return xs, ys
|
| 1350 |
+
|
| 1351 |
+
|
| 1352 |
+
#-----------------------------------------------------------------------#
|
| 1353 |
+
# #
|
| 1354 |
+
# The gamma function (NEW IMPLEMENTATION) #
|
| 1355 |
+
# #
|
| 1356 |
+
#-----------------------------------------------------------------------#
|
| 1357 |
+
|
| 1358 |
+
# Higher means faster, but more precomputation time
|
| 1359 |
+
MAX_GAMMA_TAYLOR_PREC = 5000
|
| 1360 |
+
# Need to derive higher bounds for Taylor series to go higher
|
| 1361 |
+
assert MAX_GAMMA_TAYLOR_PREC < 15000
|
| 1362 |
+
|
| 1363 |
+
# Use Stirling's series if abs(x) > beta*prec
|
| 1364 |
+
# Important: must be large enough for convergence!
|
| 1365 |
+
GAMMA_STIRLING_BETA = 0.2
|
| 1366 |
+
|
| 1367 |
+
SMALL_FACTORIAL_CACHE_SIZE = 150
|
| 1368 |
+
|
| 1369 |
+
gamma_taylor_cache = {}
|
| 1370 |
+
gamma_stirling_cache = {}
|
| 1371 |
+
|
| 1372 |
+
small_factorial_cache = [from_int(ifac(n)) for \
|
| 1373 |
+
n in range(SMALL_FACTORIAL_CACHE_SIZE+1)]
|
| 1374 |
+
|
| 1375 |
+
def zeta_array(N, prec):
|
| 1376 |
+
"""
|
| 1377 |
+
zeta(n) = A * pi**n / n! + B
|
| 1378 |
+
|
| 1379 |
+
where A is a rational number (A = Bernoulli number
|
| 1380 |
+
for n even) and B is an infinite sum over powers of exp(2*pi).
|
| 1381 |
+
(B = 0 for n even).
|
| 1382 |
+
|
| 1383 |
+
TODO: this is currently only used for gamma, but could
|
| 1384 |
+
be very useful elsewhere.
|
| 1385 |
+
"""
|
| 1386 |
+
extra = 30
|
| 1387 |
+
wp = prec+extra
|
| 1388 |
+
zeta_values = [MPZ_ZERO] * (N+2)
|
| 1389 |
+
pi = pi_fixed(wp)
|
| 1390 |
+
# STEP 1:
|
| 1391 |
+
one = MPZ_ONE << wp
|
| 1392 |
+
zeta_values[0] = -one//2
|
| 1393 |
+
f_2pi = mpf_shift(mpf_pi(wp),1)
|
| 1394 |
+
exp_2pi_k = exp_2pi = mpf_exp(f_2pi, wp)
|
| 1395 |
+
# Compute exponential series
|
| 1396 |
+
# Store values of 1/(exp(2*pi*k)-1),
|
| 1397 |
+
# exp(2*pi*k)/(exp(2*pi*k)-1)**2, 1/(exp(2*pi*k)-1)**2
|
| 1398 |
+
# pi*k*exp(2*pi*k)/(exp(2*pi*k)-1)**2
|
| 1399 |
+
exps3 = []
|
| 1400 |
+
k = 1
|
| 1401 |
+
while 1:
|
| 1402 |
+
tp = wp - 9*k
|
| 1403 |
+
if tp < 1:
|
| 1404 |
+
break
|
| 1405 |
+
# 1/(exp(2*pi*k-1)
|
| 1406 |
+
q1 = mpf_div(fone, mpf_sub(exp_2pi_k, fone, tp), tp)
|
| 1407 |
+
# pi*k*exp(2*pi*k)/(exp(2*pi*k)-1)**2
|
| 1408 |
+
q2 = mpf_mul(exp_2pi_k, mpf_mul(q1,q1,tp), tp)
|
| 1409 |
+
q1 = to_fixed(q1, wp)
|
| 1410 |
+
q2 = to_fixed(q2, wp)
|
| 1411 |
+
q2 = (k * q2 * pi) >> wp
|
| 1412 |
+
exps3.append((q1, q2))
|
| 1413 |
+
# Multiply for next round
|
| 1414 |
+
exp_2pi_k = mpf_mul(exp_2pi_k, exp_2pi, wp)
|
| 1415 |
+
k += 1
|
| 1416 |
+
# Exponential sum
|
| 1417 |
+
for n in xrange(3, N+1, 2):
|
| 1418 |
+
s = MPZ_ZERO
|
| 1419 |
+
k = 1
|
| 1420 |
+
for e1, e2 in exps3:
|
| 1421 |
+
if n%4 == 3:
|
| 1422 |
+
t = e1 // k**n
|
| 1423 |
+
else:
|
| 1424 |
+
U = (n-1)//4
|
| 1425 |
+
t = (e1 + e2//U) // k**n
|
| 1426 |
+
if not t:
|
| 1427 |
+
break
|
| 1428 |
+
s += t
|
| 1429 |
+
k += 1
|
| 1430 |
+
zeta_values[n] = -2*s
|
| 1431 |
+
# Even zeta values
|
| 1432 |
+
B = [mpf_abs(mpf_bernoulli(k,wp)) for k in xrange(N+2)]
|
| 1433 |
+
pi_pow = fpi = mpf_pow_int(mpf_shift(mpf_pi(wp), 1), 2, wp)
|
| 1434 |
+
pi_pow = mpf_div(pi_pow, from_int(4), wp)
|
| 1435 |
+
for n in xrange(2,N+2,2):
|
| 1436 |
+
z = mpf_mul(B[n], pi_pow, wp)
|
| 1437 |
+
zeta_values[n] = to_fixed(z, wp)
|
| 1438 |
+
pi_pow = mpf_mul(pi_pow, fpi, wp)
|
| 1439 |
+
pi_pow = mpf_div(pi_pow, from_int((n+1)*(n+2)), wp)
|
| 1440 |
+
# Zeta sum
|
| 1441 |
+
reciprocal_pi = (one << wp) // pi
|
| 1442 |
+
for n in xrange(3, N+1, 4):
|
| 1443 |
+
U = (n-3)//4
|
| 1444 |
+
s = zeta_values[4*U+4]*(4*U+7)//4
|
| 1445 |
+
for k in xrange(1, U+1):
|
| 1446 |
+
s -= (zeta_values[4*k] * zeta_values[4*U+4-4*k]) >> wp
|
| 1447 |
+
zeta_values[n] += (2*s*reciprocal_pi) >> wp
|
| 1448 |
+
for n in xrange(5, N+1, 4):
|
| 1449 |
+
U = (n-1)//4
|
| 1450 |
+
s = zeta_values[4*U+2]*(2*U+1)
|
| 1451 |
+
for k in xrange(1, 2*U+1):
|
| 1452 |
+
s += ((-1)**k*2*k* zeta_values[2*k] * zeta_values[4*U+2-2*k])>>wp
|
| 1453 |
+
zeta_values[n] += ((s*reciprocal_pi)>>wp)//(2*U)
|
| 1454 |
+
return [x>>extra for x in zeta_values]
|
| 1455 |
+
|
| 1456 |
+
def gamma_taylor_coefficients(inprec):
|
| 1457 |
+
"""
|
| 1458 |
+
Gives the Taylor coefficients of 1/gamma(1+x) as
|
| 1459 |
+
a list of fixed-point numbers. Enough coefficients are returned
|
| 1460 |
+
to ensure that the series converges to the given precision
|
| 1461 |
+
when x is in [0.5, 1.5].
|
| 1462 |
+
"""
|
| 1463 |
+
# Reuse nearby cache values (small case)
|
| 1464 |
+
if inprec < 400:
|
| 1465 |
+
prec = inprec + (10-(inprec%10))
|
| 1466 |
+
elif inprec < 1000:
|
| 1467 |
+
prec = inprec + (30-(inprec%30))
|
| 1468 |
+
else:
|
| 1469 |
+
prec = inprec
|
| 1470 |
+
if prec in gamma_taylor_cache:
|
| 1471 |
+
return gamma_taylor_cache[prec], prec
|
| 1472 |
+
|
| 1473 |
+
# Experimentally determined bounds
|
| 1474 |
+
if prec < 1000:
|
| 1475 |
+
N = int(prec**0.76 + 2)
|
| 1476 |
+
else:
|
| 1477 |
+
# Valid to at least 15000 bits
|
| 1478 |
+
N = int(prec**0.787 + 2)
|
| 1479 |
+
|
| 1480 |
+
# Reuse higher precision values
|
| 1481 |
+
for cprec in gamma_taylor_cache:
|
| 1482 |
+
if cprec > prec:
|
| 1483 |
+
coeffs = [x>>(cprec-prec) for x in gamma_taylor_cache[cprec][-N:]]
|
| 1484 |
+
if inprec < 1000:
|
| 1485 |
+
gamma_taylor_cache[prec] = coeffs
|
| 1486 |
+
return coeffs, prec
|
| 1487 |
+
|
| 1488 |
+
# Cache at a higher precision (large case)
|
| 1489 |
+
if prec > 1000:
|
| 1490 |
+
prec = int(prec * 1.2)
|
| 1491 |
+
|
| 1492 |
+
wp = prec + 20
|
| 1493 |
+
A = [0] * N
|
| 1494 |
+
A[0] = MPZ_ZERO
|
| 1495 |
+
A[1] = MPZ_ONE << wp
|
| 1496 |
+
A[2] = euler_fixed(wp)
|
| 1497 |
+
# SLOW, reference implementation
|
| 1498 |
+
#zeta_values = [0,0]+[to_fixed(mpf_zeta_int(k,wp),wp) for k in xrange(2,N)]
|
| 1499 |
+
zeta_values = zeta_array(N, wp)
|
| 1500 |
+
for k in xrange(3, N):
|
| 1501 |
+
a = (-A[2]*A[k-1])>>wp
|
| 1502 |
+
for j in xrange(2,k):
|
| 1503 |
+
a += ((-1)**j * zeta_values[j] * A[k-j]) >> wp
|
| 1504 |
+
a //= (1-k)
|
| 1505 |
+
A[k] = a
|
| 1506 |
+
A = [a>>20 for a in A]
|
| 1507 |
+
A = A[::-1]
|
| 1508 |
+
A = A[:-1]
|
| 1509 |
+
gamma_taylor_cache[prec] = A
|
| 1510 |
+
#return A, prec
|
| 1511 |
+
return gamma_taylor_coefficients(inprec)
|
| 1512 |
+
|
| 1513 |
+
def gamma_fixed_taylor(xmpf, x, wp, prec, rnd, type):
|
| 1514 |
+
# Determine nearest multiple of N/2
|
| 1515 |
+
#n = int(x >> (wp-1))
|
| 1516 |
+
#steps = (n-1)>>1
|
| 1517 |
+
nearest_int = ((x >> (wp-1)) + MPZ_ONE) >> 1
|
| 1518 |
+
one = MPZ_ONE << wp
|
| 1519 |
+
coeffs, cwp = gamma_taylor_coefficients(wp)
|
| 1520 |
+
if nearest_int > 0:
|
| 1521 |
+
r = one
|
| 1522 |
+
for i in xrange(nearest_int-1):
|
| 1523 |
+
x -= one
|
| 1524 |
+
r = (r*x) >> wp
|
| 1525 |
+
x -= one
|
| 1526 |
+
p = MPZ_ZERO
|
| 1527 |
+
for c in coeffs:
|
| 1528 |
+
p = c + ((x*p)>>wp)
|
| 1529 |
+
p >>= (cwp-wp)
|
| 1530 |
+
if type == 0:
|
| 1531 |
+
return from_man_exp((r<<wp)//p, -wp, prec, rnd)
|
| 1532 |
+
if type == 2:
|
| 1533 |
+
return mpf_shift(from_rational(p, (r<<wp), prec, rnd), wp)
|
| 1534 |
+
if type == 3:
|
| 1535 |
+
return mpf_log(mpf_abs(from_man_exp((r<<wp)//p, -wp)), prec, rnd)
|
| 1536 |
+
else:
|
| 1537 |
+
r = one
|
| 1538 |
+
for i in xrange(-nearest_int):
|
| 1539 |
+
r = (r*x) >> wp
|
| 1540 |
+
x += one
|
| 1541 |
+
p = MPZ_ZERO
|
| 1542 |
+
for c in coeffs:
|
| 1543 |
+
p = c + ((x*p)>>wp)
|
| 1544 |
+
p >>= (cwp-wp)
|
| 1545 |
+
if wp - bitcount(abs(x)) > 10:
|
| 1546 |
+
# pass very close to 0, so do floating-point multiply
|
| 1547 |
+
g = mpf_add(xmpf, from_int(-nearest_int)) # exact
|
| 1548 |
+
r = from_man_exp(p*r,-wp-wp)
|
| 1549 |
+
r = mpf_mul(r, g, wp)
|
| 1550 |
+
if type == 0:
|
| 1551 |
+
return mpf_div(fone, r, prec, rnd)
|
| 1552 |
+
if type == 2:
|
| 1553 |
+
return mpf_pos(r, prec, rnd)
|
| 1554 |
+
if type == 3:
|
| 1555 |
+
return mpf_log(mpf_abs(mpf_div(fone, r, wp)), prec, rnd)
|
| 1556 |
+
else:
|
| 1557 |
+
r = from_man_exp(x*p*r,-3*wp)
|
| 1558 |
+
if type == 0: return mpf_div(fone, r, prec, rnd)
|
| 1559 |
+
if type == 2: return mpf_pos(r, prec, rnd)
|
| 1560 |
+
if type == 3: return mpf_neg(mpf_log(mpf_abs(r), prec, rnd))
|
| 1561 |
+
|
| 1562 |
+
def stirling_coefficient(n):
|
| 1563 |
+
if n in gamma_stirling_cache:
|
| 1564 |
+
return gamma_stirling_cache[n]
|
| 1565 |
+
p, q = bernfrac(n)
|
| 1566 |
+
q *= MPZ(n*(n-1))
|
| 1567 |
+
gamma_stirling_cache[n] = p, q, bitcount(abs(p)), bitcount(q)
|
| 1568 |
+
return gamma_stirling_cache[n]
|
| 1569 |
+
|
| 1570 |
+
def real_stirling_series(x, prec):
|
| 1571 |
+
"""
|
| 1572 |
+
Sums the rational part of Stirling's expansion,
|
| 1573 |
+
|
| 1574 |
+
log(sqrt(2*pi)) - z + 1/(12*z) - 1/(360*z^3) + ...
|
| 1575 |
+
|
| 1576 |
+
"""
|
| 1577 |
+
t = (MPZ_ONE<<(prec+prec)) // x # t = 1/x
|
| 1578 |
+
u = (t*t)>>prec # u = 1/x**2
|
| 1579 |
+
s = ln_sqrt2pi_fixed(prec) - x
|
| 1580 |
+
# Add initial terms of Stirling's series
|
| 1581 |
+
s += t//12; t = (t*u)>>prec
|
| 1582 |
+
s -= t//360; t = (t*u)>>prec
|
| 1583 |
+
s += t//1260; t = (t*u)>>prec
|
| 1584 |
+
s -= t//1680; t = (t*u)>>prec
|
| 1585 |
+
if not t: return s
|
| 1586 |
+
s += t//1188; t = (t*u)>>prec
|
| 1587 |
+
s -= 691*t//360360; t = (t*u)>>prec
|
| 1588 |
+
s += t//156; t = (t*u)>>prec
|
| 1589 |
+
if not t: return s
|
| 1590 |
+
s -= 3617*t//122400; t = (t*u)>>prec
|
| 1591 |
+
s += 43867*t//244188; t = (t*u)>>prec
|
| 1592 |
+
s -= 174611*t//125400; t = (t*u)>>prec
|
| 1593 |
+
if not t: return s
|
| 1594 |
+
k = 22
|
| 1595 |
+
# From here on, the coefficients are growing, so we
|
| 1596 |
+
# have to keep t at a roughly constant size
|
| 1597 |
+
usize = bitcount(abs(u))
|
| 1598 |
+
tsize = bitcount(abs(t))
|
| 1599 |
+
texp = 0
|
| 1600 |
+
while 1:
|
| 1601 |
+
p, q, pb, qb = stirling_coefficient(k)
|
| 1602 |
+
term_mag = tsize + pb + texp
|
| 1603 |
+
shift = -texp
|
| 1604 |
+
m = pb - term_mag
|
| 1605 |
+
if m > 0 and shift < m:
|
| 1606 |
+
p >>= m
|
| 1607 |
+
shift -= m
|
| 1608 |
+
m = tsize - term_mag
|
| 1609 |
+
if m > 0 and shift < m:
|
| 1610 |
+
w = t >> m
|
| 1611 |
+
shift -= m
|
| 1612 |
+
else:
|
| 1613 |
+
w = t
|
| 1614 |
+
term = (t*p//q) >> shift
|
| 1615 |
+
if not term:
|
| 1616 |
+
break
|
| 1617 |
+
s += term
|
| 1618 |
+
t = (t*u) >> usize
|
| 1619 |
+
texp -= (prec - usize)
|
| 1620 |
+
k += 2
|
| 1621 |
+
return s
|
| 1622 |
+
|
| 1623 |
+
def complex_stirling_series(x, y, prec):
|
| 1624 |
+
# t = 1/z
|
| 1625 |
+
_m = (x*x + y*y) >> prec
|
| 1626 |
+
tre = (x << prec) // _m
|
| 1627 |
+
tim = (-y << prec) // _m
|
| 1628 |
+
# u = 1/z**2
|
| 1629 |
+
ure = (tre*tre - tim*tim) >> prec
|
| 1630 |
+
uim = tim*tre >> (prec-1)
|
| 1631 |
+
# s = log(sqrt(2*pi)) - z
|
| 1632 |
+
sre = ln_sqrt2pi_fixed(prec) - x
|
| 1633 |
+
sim = -y
|
| 1634 |
+
|
| 1635 |
+
# Add initial terms of Stirling's series
|
| 1636 |
+
sre += tre//12; sim += tim//12;
|
| 1637 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1638 |
+
sre -= tre//360; sim -= tim//360;
|
| 1639 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1640 |
+
sre += tre//1260; sim += tim//1260;
|
| 1641 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1642 |
+
sre -= tre//1680; sim -= tim//1680;
|
| 1643 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1644 |
+
if abs(tre) + abs(tim) < 5: return sre, sim
|
| 1645 |
+
sre += tre//1188; sim += tim//1188;
|
| 1646 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1647 |
+
sre -= 691*tre//360360; sim -= 691*tim//360360;
|
| 1648 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1649 |
+
sre += tre//156; sim += tim//156;
|
| 1650 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1651 |
+
if abs(tre) + abs(tim) < 5: return sre, sim
|
| 1652 |
+
sre -= 3617*tre//122400; sim -= 3617*tim//122400;
|
| 1653 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1654 |
+
sre += 43867*tre//244188; sim += 43867*tim//244188;
|
| 1655 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1656 |
+
sre -= 174611*tre//125400; sim -= 174611*tim//125400;
|
| 1657 |
+
tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec)
|
| 1658 |
+
if abs(tre) + abs(tim) < 5: return sre, sim
|
| 1659 |
+
|
| 1660 |
+
k = 22
|
| 1661 |
+
# From here on, the coefficients are growing, so we
|
| 1662 |
+
# have to keep t at a roughly constant size
|
| 1663 |
+
usize = bitcount(max(abs(ure), abs(uim)))
|
| 1664 |
+
tsize = bitcount(max(abs(tre), abs(tim)))
|
| 1665 |
+
texp = 0
|
| 1666 |
+
while 1:
|
| 1667 |
+
p, q, pb, qb = stirling_coefficient(k)
|
| 1668 |
+
term_mag = tsize + pb + texp
|
| 1669 |
+
shift = -texp
|
| 1670 |
+
m = pb - term_mag
|
| 1671 |
+
if m > 0 and shift < m:
|
| 1672 |
+
p >>= m
|
| 1673 |
+
shift -= m
|
| 1674 |
+
m = tsize - term_mag
|
| 1675 |
+
if m > 0 and shift < m:
|
| 1676 |
+
wre = tre >> m
|
| 1677 |
+
wim = tim >> m
|
| 1678 |
+
shift -= m
|
| 1679 |
+
else:
|
| 1680 |
+
wre = tre
|
| 1681 |
+
wim = tim
|
| 1682 |
+
termre = (tre*p//q) >> shift
|
| 1683 |
+
termim = (tim*p//q) >> shift
|
| 1684 |
+
if abs(termre) + abs(termim) < 5:
|
| 1685 |
+
break
|
| 1686 |
+
sre += termre
|
| 1687 |
+
sim += termim
|
| 1688 |
+
tre, tim = ((tre*ure - tim*uim)>>usize), \
|
| 1689 |
+
((tre*uim + tim*ure)>>usize)
|
| 1690 |
+
texp -= (prec - usize)
|
| 1691 |
+
k += 2
|
| 1692 |
+
return sre, sim
|
| 1693 |
+
|
| 1694 |
+
|
| 1695 |
+
def mpf_gamma(x, prec, rnd='d', type=0):
|
| 1696 |
+
"""
|
| 1697 |
+
This function implements multipurpose evaluation of the gamma
|
| 1698 |
+
function, G(x), as well as the following versions of the same:
|
| 1699 |
+
|
| 1700 |
+
type = 0 -- G(x) [standard gamma function]
|
| 1701 |
+
type = 1 -- G(x+1) = x*G(x+1) = x! [factorial]
|
| 1702 |
+
type = 2 -- 1/G(x) [reciprocal gamma function]
|
| 1703 |
+
type = 3 -- log(|G(x)|) [log-gamma function, real part]
|
| 1704 |
+
"""
|
| 1705 |
+
|
| 1706 |
+
# Specal values
|
| 1707 |
+
sign, man, exp, bc = x
|
| 1708 |
+
if not man:
|
| 1709 |
+
if x == fzero:
|
| 1710 |
+
if type == 1: return fone
|
| 1711 |
+
if type == 2: return fzero
|
| 1712 |
+
raise ValueError("gamma function pole")
|
| 1713 |
+
if x == finf:
|
| 1714 |
+
if type == 2: return fzero
|
| 1715 |
+
return finf
|
| 1716 |
+
return fnan
|
| 1717 |
+
|
| 1718 |
+
# First of all, for log gamma, numbers can be well beyond the fixed-point
|
| 1719 |
+
# range, so we must take care of huge numbers before e.g. trying
|
| 1720 |
+
# to convert x to the nearest integer
|
| 1721 |
+
if type == 3:
|
| 1722 |
+
wp = prec+20
|
| 1723 |
+
if exp+bc > wp and not sign:
|
| 1724 |
+
return mpf_sub(mpf_mul(x, mpf_log(x, wp), wp), x, prec, rnd)
|
| 1725 |
+
|
| 1726 |
+
# We strongly want to special-case small integers
|
| 1727 |
+
is_integer = exp >= 0
|
| 1728 |
+
if is_integer:
|
| 1729 |
+
# Poles
|
| 1730 |
+
if sign:
|
| 1731 |
+
if type == 2:
|
| 1732 |
+
return fzero
|
| 1733 |
+
raise ValueError("gamma function pole")
|
| 1734 |
+
# n = x
|
| 1735 |
+
n = man << exp
|
| 1736 |
+
if n < SMALL_FACTORIAL_CACHE_SIZE:
|
| 1737 |
+
if type == 0:
|
| 1738 |
+
return mpf_pos(small_factorial_cache[n-1], prec, rnd)
|
| 1739 |
+
if type == 1:
|
| 1740 |
+
return mpf_pos(small_factorial_cache[n], prec, rnd)
|
| 1741 |
+
if type == 2:
|
| 1742 |
+
return mpf_div(fone, small_factorial_cache[n-1], prec, rnd)
|
| 1743 |
+
if type == 3:
|
| 1744 |
+
return mpf_log(small_factorial_cache[n-1], prec, rnd)
|
| 1745 |
+
else:
|
| 1746 |
+
# floor(abs(x))
|
| 1747 |
+
n = int(man >> (-exp))
|
| 1748 |
+
|
| 1749 |
+
# Estimate size and precision
|
| 1750 |
+
# Estimate log(gamma(|x|),2) as x*log(x,2)
|
| 1751 |
+
mag = exp + bc
|
| 1752 |
+
gamma_size = n*mag
|
| 1753 |
+
|
| 1754 |
+
if type == 3:
|
| 1755 |
+
wp = prec + 20
|
| 1756 |
+
else:
|
| 1757 |
+
wp = prec + bitcount(gamma_size) + 20
|
| 1758 |
+
|
| 1759 |
+
# Very close to 0, pole
|
| 1760 |
+
if mag < -wp:
|
| 1761 |
+
if type == 0:
|
| 1762 |
+
return mpf_sub(mpf_div(fone,x, wp),mpf_shift(fone,-wp),prec,rnd)
|
| 1763 |
+
if type == 1: return mpf_sub(fone, x, prec, rnd)
|
| 1764 |
+
if type == 2: return mpf_add(x, mpf_shift(fone,mag-wp), prec, rnd)
|
| 1765 |
+
if type == 3: return mpf_neg(mpf_log(mpf_abs(x), prec, rnd))
|
| 1766 |
+
|
| 1767 |
+
# From now on, we assume having a gamma function
|
| 1768 |
+
if type == 1:
|
| 1769 |
+
return mpf_gamma(mpf_add(x, fone), prec, rnd, 0)
|
| 1770 |
+
|
| 1771 |
+
# Special case integers (those not small enough to be caught above,
|
| 1772 |
+
# but still small enough for an exact factorial to be faster
|
| 1773 |
+
# than an approximate algorithm), and half-integers
|
| 1774 |
+
if exp >= -1:
|
| 1775 |
+
if is_integer:
|
| 1776 |
+
if gamma_size < 10*wp:
|
| 1777 |
+
if type == 0:
|
| 1778 |
+
return from_int(ifac(n-1), prec, rnd)
|
| 1779 |
+
if type == 2:
|
| 1780 |
+
return from_rational(MPZ_ONE, ifac(n-1), prec, rnd)
|
| 1781 |
+
if type == 3:
|
| 1782 |
+
return mpf_log(from_int(ifac(n-1)), prec, rnd)
|
| 1783 |
+
# half-integer
|
| 1784 |
+
if n < 100 or gamma_size < 10*wp:
|
| 1785 |
+
if sign:
|
| 1786 |
+
w = sqrtpi_fixed(wp)
|
| 1787 |
+
if n % 2: f = ifac2(2*n+1)
|
| 1788 |
+
else: f = -ifac2(2*n+1)
|
| 1789 |
+
if type == 0:
|
| 1790 |
+
return mpf_shift(from_rational(w, f, prec, rnd), -wp+n+1)
|
| 1791 |
+
if type == 2:
|
| 1792 |
+
return mpf_shift(from_rational(f, w, prec, rnd), wp-n-1)
|
| 1793 |
+
if type == 3:
|
| 1794 |
+
return mpf_log(mpf_shift(from_rational(w, abs(f),
|
| 1795 |
+
prec, rnd), -wp+n+1), prec, rnd)
|
| 1796 |
+
elif n == 0:
|
| 1797 |
+
if type == 0: return mpf_sqrtpi(prec, rnd)
|
| 1798 |
+
if type == 2: return mpf_div(fone, mpf_sqrtpi(wp), prec, rnd)
|
| 1799 |
+
if type == 3: return mpf_log(mpf_sqrtpi(wp), prec, rnd)
|
| 1800 |
+
else:
|
| 1801 |
+
w = sqrtpi_fixed(wp)
|
| 1802 |
+
w = from_man_exp(w * ifac2(2*n-1), -wp-n)
|
| 1803 |
+
if type == 0: return mpf_pos(w, prec, rnd)
|
| 1804 |
+
if type == 2: return mpf_div(fone, w, prec, rnd)
|
| 1805 |
+
if type == 3: return mpf_log(mpf_abs(w), prec, rnd)
|
| 1806 |
+
|
| 1807 |
+
# Convert to fixed point
|
| 1808 |
+
offset = exp + wp
|
| 1809 |
+
if offset >= 0: absxman = man << offset
|
| 1810 |
+
else: absxman = man >> (-offset)
|
| 1811 |
+
|
| 1812 |
+
# For log gamma, provide accurate evaluation for x = 1+eps and 2+eps
|
| 1813 |
+
if type == 3 and not sign:
|
| 1814 |
+
one = MPZ_ONE << wp
|
| 1815 |
+
one_dist = abs(absxman-one)
|
| 1816 |
+
two_dist = abs(absxman-2*one)
|
| 1817 |
+
cancellation = (wp - bitcount(min(one_dist, two_dist)))
|
| 1818 |
+
if cancellation > 10:
|
| 1819 |
+
xsub1 = mpf_sub(fone, x)
|
| 1820 |
+
xsub2 = mpf_sub(ftwo, x)
|
| 1821 |
+
xsub1mag = xsub1[2]+xsub1[3]
|
| 1822 |
+
xsub2mag = xsub2[2]+xsub2[3]
|
| 1823 |
+
if xsub1mag < -wp:
|
| 1824 |
+
return mpf_mul(mpf_euler(wp), mpf_sub(fone, x), prec, rnd)
|
| 1825 |
+
if xsub2mag < -wp:
|
| 1826 |
+
return mpf_mul(mpf_sub(fone, mpf_euler(wp)),
|
| 1827 |
+
mpf_sub(x, ftwo), prec, rnd)
|
| 1828 |
+
# Proceed but increase precision
|
| 1829 |
+
wp += max(-xsub1mag, -xsub2mag)
|
| 1830 |
+
offset = exp + wp
|
| 1831 |
+
if offset >= 0: absxman = man << offset
|
| 1832 |
+
else: absxman = man >> (-offset)
|
| 1833 |
+
|
| 1834 |
+
# Use Taylor series if appropriate
|
| 1835 |
+
n_for_stirling = int(GAMMA_STIRLING_BETA*wp)
|
| 1836 |
+
if n < max(100, n_for_stirling) and wp < MAX_GAMMA_TAYLOR_PREC:
|
| 1837 |
+
if sign:
|
| 1838 |
+
absxman = -absxman
|
| 1839 |
+
return gamma_fixed_taylor(x, absxman, wp, prec, rnd, type)
|
| 1840 |
+
|
| 1841 |
+
# Use Stirling's series
|
| 1842 |
+
# First ensure that |x| is large enough for rapid convergence
|
| 1843 |
+
xorig = x
|
| 1844 |
+
|
| 1845 |
+
# Argument reduction
|
| 1846 |
+
r = 0
|
| 1847 |
+
if n < n_for_stirling:
|
| 1848 |
+
r = one = MPZ_ONE << wp
|
| 1849 |
+
d = n_for_stirling - n
|
| 1850 |
+
for k in xrange(d):
|
| 1851 |
+
r = (r * absxman) >> wp
|
| 1852 |
+
absxman += one
|
| 1853 |
+
x = xabs = from_man_exp(absxman, -wp)
|
| 1854 |
+
if sign:
|
| 1855 |
+
x = mpf_neg(x)
|
| 1856 |
+
else:
|
| 1857 |
+
xabs = mpf_abs(x)
|
| 1858 |
+
|
| 1859 |
+
# Asymptotic series
|
| 1860 |
+
y = real_stirling_series(absxman, wp)
|
| 1861 |
+
u = to_fixed(mpf_log(xabs, wp), wp)
|
| 1862 |
+
u = ((absxman - (MPZ_ONE<<(wp-1))) * u) >> wp
|
| 1863 |
+
y += u
|
| 1864 |
+
w = from_man_exp(y, -wp)
|
| 1865 |
+
|
| 1866 |
+
# Compute final value
|
| 1867 |
+
if sign:
|
| 1868 |
+
# Reflection formula
|
| 1869 |
+
A = mpf_mul(mpf_sin_pi(xorig, wp), xorig, wp)
|
| 1870 |
+
B = mpf_neg(mpf_pi(wp))
|
| 1871 |
+
if type == 0 or type == 2:
|
| 1872 |
+
A = mpf_mul(A, mpf_exp(w, wp))
|
| 1873 |
+
if r:
|
| 1874 |
+
B = mpf_mul(B, from_man_exp(r, -wp), wp)
|
| 1875 |
+
if type == 0:
|
| 1876 |
+
return mpf_div(B, A, prec, rnd)
|
| 1877 |
+
if type == 2:
|
| 1878 |
+
return mpf_div(A, B, prec, rnd)
|
| 1879 |
+
if type == 3:
|
| 1880 |
+
if r:
|
| 1881 |
+
B = mpf_mul(B, from_man_exp(r, -wp), wp)
|
| 1882 |
+
A = mpf_add(mpf_log(mpf_abs(A), wp), w, wp)
|
| 1883 |
+
return mpf_sub(mpf_log(mpf_abs(B), wp), A, prec, rnd)
|
| 1884 |
+
else:
|
| 1885 |
+
if type == 0:
|
| 1886 |
+
if r:
|
| 1887 |
+
return mpf_div(mpf_exp(w, wp),
|
| 1888 |
+
from_man_exp(r, -wp), prec, rnd)
|
| 1889 |
+
return mpf_exp(w, prec, rnd)
|
| 1890 |
+
if type == 2:
|
| 1891 |
+
if r:
|
| 1892 |
+
return mpf_div(from_man_exp(r, -wp),
|
| 1893 |
+
mpf_exp(w, wp), prec, rnd)
|
| 1894 |
+
return mpf_exp(mpf_neg(w), prec, rnd)
|
| 1895 |
+
if type == 3:
|
| 1896 |
+
if r:
|
| 1897 |
+
return mpf_sub(w, mpf_log(from_man_exp(r,-wp), wp), prec, rnd)
|
| 1898 |
+
return mpf_pos(w, prec, rnd)
|
| 1899 |
+
|
| 1900 |
+
|
| 1901 |
+
def mpc_gamma(z, prec, rnd='d', type=0):
|
| 1902 |
+
a, b = z
|
| 1903 |
+
asign, aman, aexp, abc = a
|
| 1904 |
+
bsign, bman, bexp, bbc = b
|
| 1905 |
+
|
| 1906 |
+
if b == fzero:
|
| 1907 |
+
# Imaginary part on negative half-axis for log-gamma function
|
| 1908 |
+
if type == 3 and asign:
|
| 1909 |
+
re = mpf_gamma(a, prec, rnd, 3)
|
| 1910 |
+
n = (-aman) >> (-aexp)
|
| 1911 |
+
im = mpf_mul_int(mpf_pi(prec+10), n, prec, rnd)
|
| 1912 |
+
return re, im
|
| 1913 |
+
return mpf_gamma(a, prec, rnd, type), fzero
|
| 1914 |
+
|
| 1915 |
+
# Some kind of complex inf/nan
|
| 1916 |
+
if (not aman and aexp) or (not bman and bexp):
|
| 1917 |
+
return (fnan, fnan)
|
| 1918 |
+
|
| 1919 |
+
# Initial working precision
|
| 1920 |
+
wp = prec + 20
|
| 1921 |
+
|
| 1922 |
+
amag = aexp+abc
|
| 1923 |
+
bmag = bexp+bbc
|
| 1924 |
+
if aman:
|
| 1925 |
+
mag = max(amag, bmag)
|
| 1926 |
+
else:
|
| 1927 |
+
mag = bmag
|
| 1928 |
+
|
| 1929 |
+
# Close to 0
|
| 1930 |
+
if mag < -8:
|
| 1931 |
+
if mag < -wp:
|
| 1932 |
+
# 1/gamma(z) = z + euler*z^2 + O(z^3)
|
| 1933 |
+
v = mpc_add(z, mpc_mul_mpf(mpc_mul(z,z,wp),mpf_euler(wp),wp), wp)
|
| 1934 |
+
if type == 0: return mpc_reciprocal(v, prec, rnd)
|
| 1935 |
+
if type == 1: return mpc_div(z, v, prec, rnd)
|
| 1936 |
+
if type == 2: return mpc_pos(v, prec, rnd)
|
| 1937 |
+
if type == 3: return mpc_log(mpc_reciprocal(v, prec), prec, rnd)
|
| 1938 |
+
elif type != 1:
|
| 1939 |
+
wp += (-mag)
|
| 1940 |
+
|
| 1941 |
+
# Handle huge log-gamma values; must do this before converting to
|
| 1942 |
+
# a fixed-point value. TODO: determine a precise cutoff of validity
|
| 1943 |
+
# depending on amag and bmag
|
| 1944 |
+
if type == 3 and mag > wp and ((not asign) or (bmag >= amag)):
|
| 1945 |
+
return mpc_sub(mpc_mul(z, mpc_log(z, wp), wp), z, prec, rnd)
|
| 1946 |
+
|
| 1947 |
+
# From now on, we assume having a gamma function
|
| 1948 |
+
if type == 1:
|
| 1949 |
+
return mpc_gamma((mpf_add(a, fone), b), prec, rnd, 0)
|
| 1950 |
+
|
| 1951 |
+
an = abs(to_int(a))
|
| 1952 |
+
bn = abs(to_int(b))
|
| 1953 |
+
absn = max(an, bn)
|
| 1954 |
+
gamma_size = absn*mag
|
| 1955 |
+
if type == 3:
|
| 1956 |
+
pass
|
| 1957 |
+
else:
|
| 1958 |
+
wp += bitcount(gamma_size)
|
| 1959 |
+
|
| 1960 |
+
# Reflect to the right half-plane. Note that Stirling's expansion
|
| 1961 |
+
# is valid in the left half-plane too, as long as we're not too close
|
| 1962 |
+
# to the real axis, but in order to use this argument reduction
|
| 1963 |
+
# in the negative direction must be implemented.
|
| 1964 |
+
#need_reflection = asign and ((bmag < 0) or (amag-bmag > 4))
|
| 1965 |
+
need_reflection = asign
|
| 1966 |
+
zorig = z
|
| 1967 |
+
if need_reflection:
|
| 1968 |
+
z = mpc_neg(z)
|
| 1969 |
+
asign, aman, aexp, abc = a = z[0]
|
| 1970 |
+
bsign, bman, bexp, bbc = b = z[1]
|
| 1971 |
+
|
| 1972 |
+
# Imaginary part very small compared to real one?
|
| 1973 |
+
yfinal = 0
|
| 1974 |
+
balance_prec = 0
|
| 1975 |
+
if bmag < -10:
|
| 1976 |
+
# Check z ~= 1 and z ~= 2 for loggamma
|
| 1977 |
+
if type == 3:
|
| 1978 |
+
zsub1 = mpc_sub_mpf(z, fone)
|
| 1979 |
+
if zsub1[0] == fzero:
|
| 1980 |
+
cancel1 = -bmag
|
| 1981 |
+
else:
|
| 1982 |
+
cancel1 = -max(zsub1[0][2]+zsub1[0][3], bmag)
|
| 1983 |
+
if cancel1 > wp:
|
| 1984 |
+
pi = mpf_pi(wp)
|
| 1985 |
+
x = mpc_mul_mpf(zsub1, pi, wp)
|
| 1986 |
+
x = mpc_mul(x, x, wp)
|
| 1987 |
+
x = mpc_div_mpf(x, from_int(12), wp)
|
| 1988 |
+
y = mpc_mul_mpf(zsub1, mpf_neg(mpf_euler(wp)), wp)
|
| 1989 |
+
yfinal = mpc_add(x, y, wp)
|
| 1990 |
+
if not need_reflection:
|
| 1991 |
+
return mpc_pos(yfinal, prec, rnd)
|
| 1992 |
+
elif cancel1 > 0:
|
| 1993 |
+
wp += cancel1
|
| 1994 |
+
zsub2 = mpc_sub_mpf(z, ftwo)
|
| 1995 |
+
if zsub2[0] == fzero:
|
| 1996 |
+
cancel2 = -bmag
|
| 1997 |
+
else:
|
| 1998 |
+
cancel2 = -max(zsub2[0][2]+zsub2[0][3], bmag)
|
| 1999 |
+
if cancel2 > wp:
|
| 2000 |
+
pi = mpf_pi(wp)
|
| 2001 |
+
t = mpf_sub(mpf_mul(pi, pi), from_int(6))
|
| 2002 |
+
x = mpc_mul_mpf(mpc_mul(zsub2, zsub2, wp), t, wp)
|
| 2003 |
+
x = mpc_div_mpf(x, from_int(12), wp)
|
| 2004 |
+
y = mpc_mul_mpf(zsub2, mpf_sub(fone, mpf_euler(wp)), wp)
|
| 2005 |
+
yfinal = mpc_add(x, y, wp)
|
| 2006 |
+
if not need_reflection:
|
| 2007 |
+
return mpc_pos(yfinal, prec, rnd)
|
| 2008 |
+
elif cancel2 > 0:
|
| 2009 |
+
wp += cancel2
|
| 2010 |
+
if bmag < -wp:
|
| 2011 |
+
# Compute directly from the real gamma function.
|
| 2012 |
+
pp = 2*(wp+10)
|
| 2013 |
+
aabs = mpf_abs(a)
|
| 2014 |
+
eps = mpf_shift(fone, amag-wp)
|
| 2015 |
+
x1 = mpf_gamma(aabs, pp, type=type)
|
| 2016 |
+
x2 = mpf_gamma(mpf_add(aabs, eps), pp, type=type)
|
| 2017 |
+
xprime = mpf_div(mpf_sub(x2, x1, pp), eps, pp)
|
| 2018 |
+
y = mpf_mul(b, xprime, prec, rnd)
|
| 2019 |
+
yfinal = (x1, y)
|
| 2020 |
+
# Note: we still need to use the reflection formula for
|
| 2021 |
+
# near-poles, and the correct branch of the log-gamma function
|
| 2022 |
+
if not need_reflection:
|
| 2023 |
+
return mpc_pos(yfinal, prec, rnd)
|
| 2024 |
+
else:
|
| 2025 |
+
balance_prec += (-bmag)
|
| 2026 |
+
|
| 2027 |
+
wp += balance_prec
|
| 2028 |
+
n_for_stirling = int(GAMMA_STIRLING_BETA*wp)
|
| 2029 |
+
need_reduction = absn < n_for_stirling
|
| 2030 |
+
|
| 2031 |
+
afix = to_fixed(a, wp)
|
| 2032 |
+
bfix = to_fixed(b, wp)
|
| 2033 |
+
|
| 2034 |
+
r = 0
|
| 2035 |
+
if not yfinal:
|
| 2036 |
+
zprered = z
|
| 2037 |
+
# Argument reduction
|
| 2038 |
+
if absn < n_for_stirling:
|
| 2039 |
+
absn = complex(an, bn)
|
| 2040 |
+
d = int((1 + n_for_stirling**2 - bn**2)**0.5 - an)
|
| 2041 |
+
rre = one = MPZ_ONE << wp
|
| 2042 |
+
rim = MPZ_ZERO
|
| 2043 |
+
for k in xrange(d):
|
| 2044 |
+
rre, rim = ((afix*rre-bfix*rim)>>wp), ((afix*rim + bfix*rre)>>wp)
|
| 2045 |
+
afix += one
|
| 2046 |
+
r = from_man_exp(rre, -wp), from_man_exp(rim, -wp)
|
| 2047 |
+
a = from_man_exp(afix, -wp)
|
| 2048 |
+
z = a, b
|
| 2049 |
+
|
| 2050 |
+
yre, yim = complex_stirling_series(afix, bfix, wp)
|
| 2051 |
+
# (z-1/2)*log(z) + S
|
| 2052 |
+
lre, lim = mpc_log(z, wp)
|
| 2053 |
+
lre = to_fixed(lre, wp)
|
| 2054 |
+
lim = to_fixed(lim, wp)
|
| 2055 |
+
yre = ((lre*afix - lim*bfix)>>wp) - (lre>>1) + yre
|
| 2056 |
+
yim = ((lre*bfix + lim*afix)>>wp) - (lim>>1) + yim
|
| 2057 |
+
y = from_man_exp(yre, -wp), from_man_exp(yim, -wp)
|
| 2058 |
+
|
| 2059 |
+
if r and type == 3:
|
| 2060 |
+
# If re(z) > 0 and abs(z) <= 4, the branches of loggamma(z)
|
| 2061 |
+
# and log(gamma(z)) coincide. Otherwise, use the zeroth order
|
| 2062 |
+
# Stirling expansion to compute the correct imaginary part.
|
| 2063 |
+
y = mpc_sub(y, mpc_log(r, wp), wp)
|
| 2064 |
+
zfa = to_float(zprered[0])
|
| 2065 |
+
zfb = to_float(zprered[1])
|
| 2066 |
+
zfabs = math.hypot(zfa,zfb)
|
| 2067 |
+
#if not (zfa > 0.0 and zfabs <= 4):
|
| 2068 |
+
yfb = to_float(y[1])
|
| 2069 |
+
u = math.atan2(zfb, zfa)
|
| 2070 |
+
if zfabs <= 0.5:
|
| 2071 |
+
gi = 0.577216*zfb - u
|
| 2072 |
+
else:
|
| 2073 |
+
gi = -zfb - 0.5*u + zfa*u + zfb*math.log(zfabs)
|
| 2074 |
+
n = int(math.floor((gi-yfb)/(2*math.pi)+0.5))
|
| 2075 |
+
y = (y[0], mpf_add(y[1], mpf_mul_int(mpf_pi(wp), 2*n, wp), wp))
|
| 2076 |
+
|
| 2077 |
+
if need_reflection:
|
| 2078 |
+
if type == 0 or type == 2:
|
| 2079 |
+
A = mpc_mul(mpc_sin_pi(zorig, wp), zorig, wp)
|
| 2080 |
+
B = (mpf_neg(mpf_pi(wp)), fzero)
|
| 2081 |
+
if yfinal:
|
| 2082 |
+
if type == 2:
|
| 2083 |
+
A = mpc_div(A, yfinal, wp)
|
| 2084 |
+
else:
|
| 2085 |
+
A = mpc_mul(A, yfinal, wp)
|
| 2086 |
+
else:
|
| 2087 |
+
A = mpc_mul(A, mpc_exp(y, wp), wp)
|
| 2088 |
+
if r:
|
| 2089 |
+
B = mpc_mul(B, r, wp)
|
| 2090 |
+
if type == 0: return mpc_div(B, A, prec, rnd)
|
| 2091 |
+
if type == 2: return mpc_div(A, B, prec, rnd)
|
| 2092 |
+
|
| 2093 |
+
# Reflection formula for the log-gamma function with correct branch
|
| 2094 |
+
# http://functions.wolfram.com/GammaBetaErf/LogGamma/16/01/01/0006/
|
| 2095 |
+
# LogGamma[z] == -LogGamma[-z] - Log[-z] +
|
| 2096 |
+
# Sign[Im[z]] Floor[Re[z]] Pi I + Log[Pi] -
|
| 2097 |
+
# Log[Sin[Pi (z - Floor[Re[z]])]] -
|
| 2098 |
+
# Pi I (1 - Abs[Sign[Im[z]]]) Abs[Floor[Re[z]]]
|
| 2099 |
+
if type == 3:
|
| 2100 |
+
if yfinal:
|
| 2101 |
+
s1 = mpc_neg(yfinal)
|
| 2102 |
+
else:
|
| 2103 |
+
s1 = mpc_neg(y)
|
| 2104 |
+
# s -= log(-z)
|
| 2105 |
+
s1 = mpc_sub(s1, mpc_log(mpc_neg(zorig), wp), wp)
|
| 2106 |
+
# floor(re(z))
|
| 2107 |
+
rezfloor = mpf_floor(zorig[0])
|
| 2108 |
+
imzsign = mpf_sign(zorig[1])
|
| 2109 |
+
pi = mpf_pi(wp)
|
| 2110 |
+
t = mpf_mul(pi, rezfloor)
|
| 2111 |
+
t = mpf_mul_int(t, imzsign, wp)
|
| 2112 |
+
s1 = (s1[0], mpf_add(s1[1], t, wp))
|
| 2113 |
+
s1 = mpc_add_mpf(s1, mpf_log(pi, wp), wp)
|
| 2114 |
+
t = mpc_sin_pi(mpc_sub_mpf(zorig, rezfloor), wp)
|
| 2115 |
+
t = mpc_log(t, wp)
|
| 2116 |
+
s1 = mpc_sub(s1, t, wp)
|
| 2117 |
+
# Note: may actually be unused, because we fall back
|
| 2118 |
+
# to the mpf_ function for real arguments
|
| 2119 |
+
if not imzsign:
|
| 2120 |
+
t = mpf_mul(pi, mpf_floor(rezfloor), wp)
|
| 2121 |
+
s1 = (s1[0], mpf_sub(s1[1], t, wp))
|
| 2122 |
+
return mpc_pos(s1, prec, rnd)
|
| 2123 |
+
else:
|
| 2124 |
+
if type == 0:
|
| 2125 |
+
if r:
|
| 2126 |
+
return mpc_div(mpc_exp(y, wp), r, prec, rnd)
|
| 2127 |
+
return mpc_exp(y, prec, rnd)
|
| 2128 |
+
if type == 2:
|
| 2129 |
+
if r:
|
| 2130 |
+
return mpc_div(r, mpc_exp(y, wp), prec, rnd)
|
| 2131 |
+
return mpc_exp(mpc_neg(y), prec, rnd)
|
| 2132 |
+
if type == 3:
|
| 2133 |
+
return mpc_pos(y, prec, rnd)
|
| 2134 |
+
|
| 2135 |
+
def mpf_factorial(x, prec, rnd='d'):
|
| 2136 |
+
return mpf_gamma(x, prec, rnd, 1)
|
| 2137 |
+
|
| 2138 |
+
def mpc_factorial(x, prec, rnd='d'):
|
| 2139 |
+
return mpc_gamma(x, prec, rnd, 1)
|
| 2140 |
+
|
| 2141 |
+
def mpf_rgamma(x, prec, rnd='d'):
|
| 2142 |
+
return mpf_gamma(x, prec, rnd, 2)
|
| 2143 |
+
|
| 2144 |
+
def mpc_rgamma(x, prec, rnd='d'):
|
| 2145 |
+
return mpc_gamma(x, prec, rnd, 2)
|
| 2146 |
+
|
| 2147 |
+
def mpf_loggamma(x, prec, rnd='d'):
|
| 2148 |
+
sign, man, exp, bc = x
|
| 2149 |
+
if sign:
|
| 2150 |
+
raise ComplexResult
|
| 2151 |
+
return mpf_gamma(x, prec, rnd, 3)
|
| 2152 |
+
|
| 2153 |
+
def mpc_loggamma(z, prec, rnd='d'):
|
| 2154 |
+
a, b = z
|
| 2155 |
+
asign, aman, aexp, abc = a
|
| 2156 |
+
bsign, bman, bexp, bbc = b
|
| 2157 |
+
if b == fzero and asign:
|
| 2158 |
+
re = mpf_gamma(a, prec, rnd, 3)
|
| 2159 |
+
n = (-aman) >> (-aexp)
|
| 2160 |
+
im = mpf_mul_int(mpf_pi(prec+10), n, prec, rnd)
|
| 2161 |
+
return re, im
|
| 2162 |
+
return mpc_gamma(z, prec, rnd, 3)
|
| 2163 |
+
|
| 2164 |
+
def mpf_gamma_int(n, prec, rnd=round_fast):
|
| 2165 |
+
if n < SMALL_FACTORIAL_CACHE_SIZE:
|
| 2166 |
+
return mpf_pos(small_factorial_cache[n-1], prec, rnd)
|
| 2167 |
+
return mpf_gamma(from_int(n), prec, rnd)
|
.venv/lib/python3.11/site-packages/mpmath/libmp/libhyper.py
ADDED
|
@@ -0,0 +1,1150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This module implements computation of hypergeometric and related
|
| 3 |
+
functions. In particular, it provides code for generic summation
|
| 4 |
+
of hypergeometric series. Optimized versions for various special
|
| 5 |
+
cases are also provided.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import operator
|
| 9 |
+
import math
|
| 10 |
+
|
| 11 |
+
from .backend import MPZ_ZERO, MPZ_ONE, BACKEND, xrange, exec_
|
| 12 |
+
|
| 13 |
+
from .libintmath import gcd
|
| 14 |
+
|
| 15 |
+
from .libmpf import (\
|
| 16 |
+
ComplexResult, round_fast, round_nearest,
|
| 17 |
+
negative_rnd, bitcount, to_fixed, from_man_exp, from_int, to_int,
|
| 18 |
+
from_rational,
|
| 19 |
+
fzero, fone, fnone, ftwo, finf, fninf, fnan,
|
| 20 |
+
mpf_sign, mpf_add, mpf_abs, mpf_pos,
|
| 21 |
+
mpf_cmp, mpf_lt, mpf_le, mpf_gt, mpf_min_max,
|
| 22 |
+
mpf_perturb, mpf_neg, mpf_shift, mpf_sub, mpf_mul, mpf_div,
|
| 23 |
+
sqrt_fixed, mpf_sqrt, mpf_rdiv_int, mpf_pow_int,
|
| 24 |
+
to_rational,
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
from .libelefun import (\
|
| 28 |
+
mpf_pi, mpf_exp, mpf_log, pi_fixed, mpf_cos_sin, mpf_cos, mpf_sin,
|
| 29 |
+
mpf_sqrt, agm_fixed,
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
from .libmpc import (\
|
| 33 |
+
mpc_one, mpc_sub, mpc_mul_mpf, mpc_mul, mpc_neg, complex_int_pow,
|
| 34 |
+
mpc_div, mpc_add_mpf, mpc_sub_mpf,
|
| 35 |
+
mpc_log, mpc_add, mpc_pos, mpc_shift,
|
| 36 |
+
mpc_is_infnan, mpc_zero, mpc_sqrt, mpc_abs,
|
| 37 |
+
mpc_mpf_div, mpc_square, mpc_exp
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
from .libintmath import ifac
|
| 41 |
+
from .gammazeta import mpf_gamma_int, mpf_euler, euler_fixed
|
| 42 |
+
|
| 43 |
+
class NoConvergence(Exception):
|
| 44 |
+
pass
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
#-----------------------------------------------------------------------#
|
| 48 |
+
# #
|
| 49 |
+
# Generic hypergeometric series #
|
| 50 |
+
# #
|
| 51 |
+
#-----------------------------------------------------------------------#
|
| 52 |
+
|
| 53 |
+
"""
|
| 54 |
+
TODO:
|
| 55 |
+
|
| 56 |
+
1. proper mpq parsing
|
| 57 |
+
2. imaginary z special-cased (also: rational, integer?)
|
| 58 |
+
3. more clever handling of series that don't converge because of stupid
|
| 59 |
+
upwards rounding
|
| 60 |
+
4. checking for cancellation
|
| 61 |
+
|
| 62 |
+
"""
|
| 63 |
+
|
| 64 |
+
def make_hyp_summator(key):
|
| 65 |
+
"""
|
| 66 |
+
Returns a function that sums a generalized hypergeometric series,
|
| 67 |
+
for given parameter types (integer, rational, real, complex).
|
| 68 |
+
|
| 69 |
+
"""
|
| 70 |
+
p, q, param_types, ztype = key
|
| 71 |
+
|
| 72 |
+
pstring = "".join(param_types)
|
| 73 |
+
fname = "hypsum_%i_%i_%s_%s_%s" % (p, q, pstring[:p], pstring[p:], ztype)
|
| 74 |
+
#print "generating hypsum", fname
|
| 75 |
+
|
| 76 |
+
have_complex_param = 'C' in param_types
|
| 77 |
+
have_complex_arg = ztype == 'C'
|
| 78 |
+
have_complex = have_complex_param or have_complex_arg
|
| 79 |
+
|
| 80 |
+
source = []
|
| 81 |
+
add = source.append
|
| 82 |
+
|
| 83 |
+
aint = []
|
| 84 |
+
arat = []
|
| 85 |
+
bint = []
|
| 86 |
+
brat = []
|
| 87 |
+
areal = []
|
| 88 |
+
breal = []
|
| 89 |
+
acomplex = []
|
| 90 |
+
bcomplex = []
|
| 91 |
+
|
| 92 |
+
#add("wp = prec + 40")
|
| 93 |
+
add("MAX = kwargs.get('maxterms', wp*100)")
|
| 94 |
+
add("HIGH = MPZ_ONE<<epsshift")
|
| 95 |
+
add("LOW = -HIGH")
|
| 96 |
+
|
| 97 |
+
# Setup code
|
| 98 |
+
add("SRE = PRE = one = (MPZ_ONE << wp)")
|
| 99 |
+
if have_complex:
|
| 100 |
+
add("SIM = PIM = MPZ_ZERO")
|
| 101 |
+
|
| 102 |
+
if have_complex_arg:
|
| 103 |
+
add("xsign, xm, xe, xbc = z[0]")
|
| 104 |
+
add("if xsign: xm = -xm")
|
| 105 |
+
add("ysign, ym, ye, ybc = z[1]")
|
| 106 |
+
add("if ysign: ym = -ym")
|
| 107 |
+
else:
|
| 108 |
+
add("xsign, xm, xe, xbc = z")
|
| 109 |
+
add("if xsign: xm = -xm")
|
| 110 |
+
|
| 111 |
+
add("offset = xe + wp")
|
| 112 |
+
add("if offset >= 0:")
|
| 113 |
+
add(" ZRE = xm << offset")
|
| 114 |
+
add("else:")
|
| 115 |
+
add(" ZRE = xm >> (-offset)")
|
| 116 |
+
if have_complex_arg:
|
| 117 |
+
add("offset = ye + wp")
|
| 118 |
+
add("if offset >= 0:")
|
| 119 |
+
add(" ZIM = ym << offset")
|
| 120 |
+
add("else:")
|
| 121 |
+
add(" ZIM = ym >> (-offset)")
|
| 122 |
+
|
| 123 |
+
for i, flag in enumerate(param_types):
|
| 124 |
+
W = ["A", "B"][i >= p]
|
| 125 |
+
if flag == 'Z':
|
| 126 |
+
([aint,bint][i >= p]).append(i)
|
| 127 |
+
add("%sINT_%i = coeffs[%i]" % (W, i, i))
|
| 128 |
+
elif flag == 'Q':
|
| 129 |
+
([arat,brat][i >= p]).append(i)
|
| 130 |
+
add("%sP_%i, %sQ_%i = coeffs[%i]._mpq_" % (W, i, W, i, i))
|
| 131 |
+
elif flag == 'R':
|
| 132 |
+
([areal,breal][i >= p]).append(i)
|
| 133 |
+
add("xsign, xm, xe, xbc = coeffs[%i]._mpf_" % i)
|
| 134 |
+
add("if xsign: xm = -xm")
|
| 135 |
+
add("offset = xe + wp")
|
| 136 |
+
add("if offset >= 0:")
|
| 137 |
+
add(" %sREAL_%i = xm << offset" % (W, i))
|
| 138 |
+
add("else:")
|
| 139 |
+
add(" %sREAL_%i = xm >> (-offset)" % (W, i))
|
| 140 |
+
elif flag == 'C':
|
| 141 |
+
([acomplex,bcomplex][i >= p]).append(i)
|
| 142 |
+
add("__re, __im = coeffs[%i]._mpc_" % i)
|
| 143 |
+
add("xsign, xm, xe, xbc = __re")
|
| 144 |
+
add("if xsign: xm = -xm")
|
| 145 |
+
add("ysign, ym, ye, ybc = __im")
|
| 146 |
+
add("if ysign: ym = -ym")
|
| 147 |
+
|
| 148 |
+
add("offset = xe + wp")
|
| 149 |
+
add("if offset >= 0:")
|
| 150 |
+
add(" %sCRE_%i = xm << offset" % (W, i))
|
| 151 |
+
add("else:")
|
| 152 |
+
add(" %sCRE_%i = xm >> (-offset)" % (W, i))
|
| 153 |
+
add("offset = ye + wp")
|
| 154 |
+
add("if offset >= 0:")
|
| 155 |
+
add(" %sCIM_%i = ym << offset" % (W, i))
|
| 156 |
+
add("else:")
|
| 157 |
+
add(" %sCIM_%i = ym >> (-offset)" % (W, i))
|
| 158 |
+
else:
|
| 159 |
+
raise ValueError
|
| 160 |
+
|
| 161 |
+
l_areal = len(areal)
|
| 162 |
+
l_breal = len(breal)
|
| 163 |
+
cancellable_real = min(l_areal, l_breal)
|
| 164 |
+
noncancellable_real_num = areal[cancellable_real:]
|
| 165 |
+
noncancellable_real_den = breal[cancellable_real:]
|
| 166 |
+
|
| 167 |
+
# LOOP
|
| 168 |
+
add("for n in xrange(1,10**8):")
|
| 169 |
+
|
| 170 |
+
add(" if n in magnitude_check:")
|
| 171 |
+
add(" p_mag = bitcount(abs(PRE))")
|
| 172 |
+
if have_complex:
|
| 173 |
+
add(" p_mag = max(p_mag, bitcount(abs(PIM)))")
|
| 174 |
+
add(" magnitude_check[n] = wp-p_mag")
|
| 175 |
+
|
| 176 |
+
# Real factors
|
| 177 |
+
multiplier = " * ".join(["AINT_#".replace("#", str(i)) for i in aint] + \
|
| 178 |
+
["AP_#".replace("#", str(i)) for i in arat] + \
|
| 179 |
+
["BQ_#".replace("#", str(i)) for i in brat])
|
| 180 |
+
|
| 181 |
+
divisor = " * ".join(["BINT_#".replace("#", str(i)) for i in bint] + \
|
| 182 |
+
["BP_#".replace("#", str(i)) for i in brat] + \
|
| 183 |
+
["AQ_#".replace("#", str(i)) for i in arat] + ["n"])
|
| 184 |
+
|
| 185 |
+
if multiplier:
|
| 186 |
+
add(" mul = " + multiplier)
|
| 187 |
+
add(" div = " + divisor)
|
| 188 |
+
|
| 189 |
+
# Check for singular terms
|
| 190 |
+
add(" if not div:")
|
| 191 |
+
if multiplier:
|
| 192 |
+
add(" if not mul:")
|
| 193 |
+
add(" break")
|
| 194 |
+
add(" raise ZeroDivisionError")
|
| 195 |
+
|
| 196 |
+
# Update product
|
| 197 |
+
if have_complex:
|
| 198 |
+
|
| 199 |
+
# TODO: when there are several real parameters and just a few complex
|
| 200 |
+
# (maybe just the complex argument), we only need to do about
|
| 201 |
+
# half as many ops if we accumulate the real factor in a single real variable
|
| 202 |
+
for k in range(cancellable_real): add(" PRE = PRE * AREAL_%i // BREAL_%i" % (areal[k], breal[k]))
|
| 203 |
+
for i in noncancellable_real_num: add(" PRE = (PRE * AREAL_#) >> wp".replace("#", str(i)))
|
| 204 |
+
for i in noncancellable_real_den: add(" PRE = (PRE << wp) // BREAL_#".replace("#", str(i)))
|
| 205 |
+
for k in range(cancellable_real): add(" PIM = PIM * AREAL_%i // BREAL_%i" % (areal[k], breal[k]))
|
| 206 |
+
for i in noncancellable_real_num: add(" PIM = (PIM * AREAL_#) >> wp".replace("#", str(i)))
|
| 207 |
+
for i in noncancellable_real_den: add(" PIM = (PIM << wp) // BREAL_#".replace("#", str(i)))
|
| 208 |
+
|
| 209 |
+
if multiplier:
|
| 210 |
+
if have_complex_arg:
|
| 211 |
+
add(" PRE, PIM = (mul*(PRE*ZRE-PIM*ZIM))//div, (mul*(PIM*ZRE+PRE*ZIM))//div")
|
| 212 |
+
add(" PRE >>= wp")
|
| 213 |
+
add(" PIM >>= wp")
|
| 214 |
+
else:
|
| 215 |
+
add(" PRE = ((mul * PRE * ZRE) >> wp) // div")
|
| 216 |
+
add(" PIM = ((mul * PIM * ZRE) >> wp) // div")
|
| 217 |
+
else:
|
| 218 |
+
if have_complex_arg:
|
| 219 |
+
add(" PRE, PIM = (PRE*ZRE-PIM*ZIM)//div, (PIM*ZRE+PRE*ZIM)//div")
|
| 220 |
+
add(" PRE >>= wp")
|
| 221 |
+
add(" PIM >>= wp")
|
| 222 |
+
else:
|
| 223 |
+
add(" PRE = ((PRE * ZRE) >> wp) // div")
|
| 224 |
+
add(" PIM = ((PIM * ZRE) >> wp) // div")
|
| 225 |
+
|
| 226 |
+
for i in acomplex:
|
| 227 |
+
add(" PRE, PIM = PRE*ACRE_#-PIM*ACIM_#, PIM*ACRE_#+PRE*ACIM_#".replace("#", str(i)))
|
| 228 |
+
add(" PRE >>= wp")
|
| 229 |
+
add(" PIM >>= wp")
|
| 230 |
+
|
| 231 |
+
for i in bcomplex:
|
| 232 |
+
add(" mag = BCRE_#*BCRE_#+BCIM_#*BCIM_#".replace("#", str(i)))
|
| 233 |
+
add(" re = PRE*BCRE_# + PIM*BCIM_#".replace("#", str(i)))
|
| 234 |
+
add(" im = PIM*BCRE_# - PRE*BCIM_#".replace("#", str(i)))
|
| 235 |
+
add(" PRE = (re << wp) // mag".replace("#", str(i)))
|
| 236 |
+
add(" PIM = (im << wp) // mag".replace("#", str(i)))
|
| 237 |
+
|
| 238 |
+
else:
|
| 239 |
+
for k in range(cancellable_real): add(" PRE = PRE * AREAL_%i // BREAL_%i" % (areal[k], breal[k]))
|
| 240 |
+
for i in noncancellable_real_num: add(" PRE = (PRE * AREAL_#) >> wp".replace("#", str(i)))
|
| 241 |
+
for i in noncancellable_real_den: add(" PRE = (PRE << wp) // BREAL_#".replace("#", str(i)))
|
| 242 |
+
if multiplier:
|
| 243 |
+
add(" PRE = ((PRE * mul * ZRE) >> wp) // div")
|
| 244 |
+
else:
|
| 245 |
+
add(" PRE = ((PRE * ZRE) >> wp) // div")
|
| 246 |
+
|
| 247 |
+
# Add product to sum
|
| 248 |
+
if have_complex:
|
| 249 |
+
add(" SRE += PRE")
|
| 250 |
+
add(" SIM += PIM")
|
| 251 |
+
add(" if (HIGH > PRE > LOW) and (HIGH > PIM > LOW):")
|
| 252 |
+
add(" break")
|
| 253 |
+
else:
|
| 254 |
+
add(" SRE += PRE")
|
| 255 |
+
add(" if HIGH > PRE > LOW:")
|
| 256 |
+
add(" break")
|
| 257 |
+
|
| 258 |
+
#add(" from mpmath import nprint, log, ldexp")
|
| 259 |
+
#add(" nprint([n, log(abs(PRE),2), ldexp(PRE,-wp)])")
|
| 260 |
+
|
| 261 |
+
add(" if n > MAX:")
|
| 262 |
+
add(" raise NoConvergence('Hypergeometric series converges too slowly. Try increasing maxterms.')")
|
| 263 |
+
|
| 264 |
+
# +1 all parameters for next loop
|
| 265 |
+
for i in aint: add(" AINT_# += 1".replace("#", str(i)))
|
| 266 |
+
for i in bint: add(" BINT_# += 1".replace("#", str(i)))
|
| 267 |
+
for i in arat: add(" AP_# += AQ_#".replace("#", str(i)))
|
| 268 |
+
for i in brat: add(" BP_# += BQ_#".replace("#", str(i)))
|
| 269 |
+
for i in areal: add(" AREAL_# += one".replace("#", str(i)))
|
| 270 |
+
for i in breal: add(" BREAL_# += one".replace("#", str(i)))
|
| 271 |
+
for i in acomplex: add(" ACRE_# += one".replace("#", str(i)))
|
| 272 |
+
for i in bcomplex: add(" BCRE_# += one".replace("#", str(i)))
|
| 273 |
+
|
| 274 |
+
if have_complex:
|
| 275 |
+
add("a = from_man_exp(SRE, -wp, prec, 'n')")
|
| 276 |
+
add("b = from_man_exp(SIM, -wp, prec, 'n')")
|
| 277 |
+
|
| 278 |
+
add("if SRE:")
|
| 279 |
+
add(" if SIM:")
|
| 280 |
+
add(" magn = max(a[2]+a[3], b[2]+b[3])")
|
| 281 |
+
add(" else:")
|
| 282 |
+
add(" magn = a[2]+a[3]")
|
| 283 |
+
add("elif SIM:")
|
| 284 |
+
add(" magn = b[2]+b[3]")
|
| 285 |
+
add("else:")
|
| 286 |
+
add(" magn = -wp+1")
|
| 287 |
+
|
| 288 |
+
add("return (a, b), True, magn")
|
| 289 |
+
else:
|
| 290 |
+
add("a = from_man_exp(SRE, -wp, prec, 'n')")
|
| 291 |
+
|
| 292 |
+
add("if SRE:")
|
| 293 |
+
add(" magn = a[2]+a[3]")
|
| 294 |
+
add("else:")
|
| 295 |
+
add(" magn = -wp+1")
|
| 296 |
+
|
| 297 |
+
add("return a, False, magn")
|
| 298 |
+
|
| 299 |
+
source = "\n".join((" " + line) for line in source)
|
| 300 |
+
source = ("def %s(coeffs, z, prec, wp, epsshift, magnitude_check, **kwargs):\n" % fname) + source
|
| 301 |
+
|
| 302 |
+
namespace = {}
|
| 303 |
+
|
| 304 |
+
exec_(source, globals(), namespace)
|
| 305 |
+
|
| 306 |
+
#print source
|
| 307 |
+
return source, namespace[fname]
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
if BACKEND == 'sage':
|
| 311 |
+
|
| 312 |
+
def make_hyp_summator(key):
|
| 313 |
+
"""
|
| 314 |
+
Returns a function that sums a generalized hypergeometric series,
|
| 315 |
+
for given parameter types (integer, rational, real, complex).
|
| 316 |
+
"""
|
| 317 |
+
from sage.libs.mpmath.ext_main import hypsum_internal
|
| 318 |
+
p, q, param_types, ztype = key
|
| 319 |
+
def _hypsum(coeffs, z, prec, wp, epsshift, magnitude_check, **kwargs):
|
| 320 |
+
return hypsum_internal(p, q, param_types, ztype, coeffs, z,
|
| 321 |
+
prec, wp, epsshift, magnitude_check, kwargs)
|
| 322 |
+
|
| 323 |
+
return "(none)", _hypsum
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
#-----------------------------------------------------------------------#
|
| 327 |
+
# #
|
| 328 |
+
# Error functions #
|
| 329 |
+
# #
|
| 330 |
+
#-----------------------------------------------------------------------#
|
| 331 |
+
|
| 332 |
+
# TODO: mpf_erf should call mpf_erfc when appropriate (currently
|
| 333 |
+
# only the converse delegation is implemented)
|
| 334 |
+
|
| 335 |
+
def mpf_erf(x, prec, rnd=round_fast):
|
| 336 |
+
sign, man, exp, bc = x
|
| 337 |
+
if not man:
|
| 338 |
+
if x == fzero: return fzero
|
| 339 |
+
if x == finf: return fone
|
| 340 |
+
if x== fninf: return fnone
|
| 341 |
+
return fnan
|
| 342 |
+
size = exp + bc
|
| 343 |
+
lg = math.log
|
| 344 |
+
# The approximation erf(x) = 1 is accurate to > x^2 * log(e,2) bits
|
| 345 |
+
if size > 3 and 2*(size-1) + 0.528766 > lg(prec,2):
|
| 346 |
+
if sign:
|
| 347 |
+
return mpf_perturb(fnone, 0, prec, rnd)
|
| 348 |
+
else:
|
| 349 |
+
return mpf_perturb(fone, 1, prec, rnd)
|
| 350 |
+
# erf(x) ~ 2*x/sqrt(pi) close to 0
|
| 351 |
+
if size < -prec:
|
| 352 |
+
# 2*x
|
| 353 |
+
x = mpf_shift(x,1)
|
| 354 |
+
c = mpf_sqrt(mpf_pi(prec+20), prec+20)
|
| 355 |
+
# TODO: interval rounding
|
| 356 |
+
return mpf_div(x, c, prec, rnd)
|
| 357 |
+
wp = prec + abs(size) + 25
|
| 358 |
+
# Taylor series for erf, fixed-point summation
|
| 359 |
+
t = abs(to_fixed(x, wp))
|
| 360 |
+
t2 = (t*t) >> wp
|
| 361 |
+
s, term, k = t, 12345, 1
|
| 362 |
+
while term:
|
| 363 |
+
t = ((t * t2) >> wp) // k
|
| 364 |
+
term = t // (2*k+1)
|
| 365 |
+
if k & 1:
|
| 366 |
+
s -= term
|
| 367 |
+
else:
|
| 368 |
+
s += term
|
| 369 |
+
k += 1
|
| 370 |
+
s = (s << (wp+1)) // sqrt_fixed(pi_fixed(wp), wp)
|
| 371 |
+
if sign:
|
| 372 |
+
s = -s
|
| 373 |
+
return from_man_exp(s, -wp, prec, rnd)
|
| 374 |
+
|
| 375 |
+
# If possible, we use the asymptotic series for erfc.
|
| 376 |
+
# This is an alternating divergent asymptotic series, so
|
| 377 |
+
# the error is at most equal to the first omitted term.
|
| 378 |
+
# Here we check if the smallest term is small enough
|
| 379 |
+
# for a given x and precision
|
| 380 |
+
def erfc_check_series(x, prec):
|
| 381 |
+
n = to_int(x)
|
| 382 |
+
if n**2 * 1.44 > prec:
|
| 383 |
+
return True
|
| 384 |
+
return False
|
| 385 |
+
|
| 386 |
+
def mpf_erfc(x, prec, rnd=round_fast):
|
| 387 |
+
sign, man, exp, bc = x
|
| 388 |
+
if not man:
|
| 389 |
+
if x == fzero: return fone
|
| 390 |
+
if x == finf: return fzero
|
| 391 |
+
if x == fninf: return ftwo
|
| 392 |
+
return fnan
|
| 393 |
+
wp = prec + 20
|
| 394 |
+
mag = bc+exp
|
| 395 |
+
# Preserve full accuracy when exponent grows huge
|
| 396 |
+
wp += max(0, 2*mag)
|
| 397 |
+
regular_erf = sign or mag < 2
|
| 398 |
+
if regular_erf or not erfc_check_series(x, wp):
|
| 399 |
+
if regular_erf:
|
| 400 |
+
return mpf_sub(fone, mpf_erf(x, prec+10, negative_rnd[rnd]), prec, rnd)
|
| 401 |
+
# 1-erf(x) ~ exp(-x^2), increase prec to deal with cancellation
|
| 402 |
+
n = to_int(x)+1
|
| 403 |
+
return mpf_sub(fone, mpf_erf(x, prec + int(n**2*1.44) + 10), prec, rnd)
|
| 404 |
+
s = term = MPZ_ONE << wp
|
| 405 |
+
term_prev = 0
|
| 406 |
+
t = (2 * to_fixed(x, wp) ** 2) >> wp
|
| 407 |
+
k = 1
|
| 408 |
+
while 1:
|
| 409 |
+
term = ((term * (2*k - 1)) << wp) // t
|
| 410 |
+
if k > 4 and term > term_prev or not term:
|
| 411 |
+
break
|
| 412 |
+
if k & 1:
|
| 413 |
+
s -= term
|
| 414 |
+
else:
|
| 415 |
+
s += term
|
| 416 |
+
term_prev = term
|
| 417 |
+
#print k, to_str(from_man_exp(term, -wp, 50), 10)
|
| 418 |
+
k += 1
|
| 419 |
+
s = (s << wp) // sqrt_fixed(pi_fixed(wp), wp)
|
| 420 |
+
s = from_man_exp(s, -wp, wp)
|
| 421 |
+
z = mpf_exp(mpf_neg(mpf_mul(x,x,wp),wp),wp)
|
| 422 |
+
y = mpf_div(mpf_mul(z, s, wp), x, prec, rnd)
|
| 423 |
+
return y
|
| 424 |
+
|
| 425 |
+
|
| 426 |
+
#-----------------------------------------------------------------------#
|
| 427 |
+
# #
|
| 428 |
+
# Exponential integrals #
|
| 429 |
+
# #
|
| 430 |
+
#-----------------------------------------------------------------------#
|
| 431 |
+
|
| 432 |
+
def ei_taylor(x, prec):
|
| 433 |
+
s = t = x
|
| 434 |
+
k = 2
|
| 435 |
+
while t:
|
| 436 |
+
t = ((t*x) >> prec) // k
|
| 437 |
+
s += t // k
|
| 438 |
+
k += 1
|
| 439 |
+
return s
|
| 440 |
+
|
| 441 |
+
def complex_ei_taylor(zre, zim, prec):
|
| 442 |
+
_abs = abs
|
| 443 |
+
sre = tre = zre
|
| 444 |
+
sim = tim = zim
|
| 445 |
+
k = 2
|
| 446 |
+
while _abs(tre) + _abs(tim) > 5:
|
| 447 |
+
tre, tim = ((tre*zre-tim*zim)//k)>>prec, ((tre*zim+tim*zre)//k)>>prec
|
| 448 |
+
sre += tre // k
|
| 449 |
+
sim += tim // k
|
| 450 |
+
k += 1
|
| 451 |
+
return sre, sim
|
| 452 |
+
|
| 453 |
+
def ei_asymptotic(x, prec):
|
| 454 |
+
one = MPZ_ONE << prec
|
| 455 |
+
x = t = ((one << prec) // x)
|
| 456 |
+
s = one + x
|
| 457 |
+
k = 2
|
| 458 |
+
while t:
|
| 459 |
+
t = (k*t*x) >> prec
|
| 460 |
+
s += t
|
| 461 |
+
k += 1
|
| 462 |
+
return s
|
| 463 |
+
|
| 464 |
+
def complex_ei_asymptotic(zre, zim, prec):
|
| 465 |
+
_abs = abs
|
| 466 |
+
one = MPZ_ONE << prec
|
| 467 |
+
M = (zim*zim + zre*zre) >> prec
|
| 468 |
+
# 1 / z
|
| 469 |
+
xre = tre = (zre << prec) // M
|
| 470 |
+
xim = tim = ((-zim) << prec) // M
|
| 471 |
+
sre = one + xre
|
| 472 |
+
sim = xim
|
| 473 |
+
k = 2
|
| 474 |
+
while _abs(tre) + _abs(tim) > 1000:
|
| 475 |
+
#print tre, tim
|
| 476 |
+
tre, tim = ((tre*xre-tim*xim)*k)>>prec, ((tre*xim+tim*xre)*k)>>prec
|
| 477 |
+
sre += tre
|
| 478 |
+
sim += tim
|
| 479 |
+
k += 1
|
| 480 |
+
if k > prec:
|
| 481 |
+
raise NoConvergence
|
| 482 |
+
return sre, sim
|
| 483 |
+
|
| 484 |
+
def mpf_ei(x, prec, rnd=round_fast, e1=False):
|
| 485 |
+
if e1:
|
| 486 |
+
x = mpf_neg(x)
|
| 487 |
+
sign, man, exp, bc = x
|
| 488 |
+
if e1 and not sign:
|
| 489 |
+
if x == fzero:
|
| 490 |
+
return finf
|
| 491 |
+
raise ComplexResult("E1(x) for x < 0")
|
| 492 |
+
if man:
|
| 493 |
+
xabs = 0, man, exp, bc
|
| 494 |
+
xmag = exp+bc
|
| 495 |
+
wp = prec + 20
|
| 496 |
+
can_use_asymp = xmag > wp
|
| 497 |
+
if not can_use_asymp:
|
| 498 |
+
if exp >= 0:
|
| 499 |
+
xabsint = man << exp
|
| 500 |
+
else:
|
| 501 |
+
xabsint = man >> (-exp)
|
| 502 |
+
can_use_asymp = xabsint > int(wp*0.693) + 10
|
| 503 |
+
if can_use_asymp:
|
| 504 |
+
if xmag > wp:
|
| 505 |
+
v = fone
|
| 506 |
+
else:
|
| 507 |
+
v = from_man_exp(ei_asymptotic(to_fixed(x, wp), wp), -wp)
|
| 508 |
+
v = mpf_mul(v, mpf_exp(x, wp), wp)
|
| 509 |
+
v = mpf_div(v, x, prec, rnd)
|
| 510 |
+
else:
|
| 511 |
+
wp += 2*int(to_int(xabs))
|
| 512 |
+
u = to_fixed(x, wp)
|
| 513 |
+
v = ei_taylor(u, wp) + euler_fixed(wp)
|
| 514 |
+
t1 = from_man_exp(v,-wp)
|
| 515 |
+
t2 = mpf_log(xabs,wp)
|
| 516 |
+
v = mpf_add(t1, t2, prec, rnd)
|
| 517 |
+
else:
|
| 518 |
+
if x == fzero: v = fninf
|
| 519 |
+
elif x == finf: v = finf
|
| 520 |
+
elif x == fninf: v = fzero
|
| 521 |
+
else: v = fnan
|
| 522 |
+
if e1:
|
| 523 |
+
v = mpf_neg(v)
|
| 524 |
+
return v
|
| 525 |
+
|
| 526 |
+
def mpc_ei(z, prec, rnd=round_fast, e1=False):
|
| 527 |
+
if e1:
|
| 528 |
+
z = mpc_neg(z)
|
| 529 |
+
a, b = z
|
| 530 |
+
asign, aman, aexp, abc = a
|
| 531 |
+
bsign, bman, bexp, bbc = b
|
| 532 |
+
if b == fzero:
|
| 533 |
+
if e1:
|
| 534 |
+
x = mpf_neg(mpf_ei(a, prec, rnd))
|
| 535 |
+
if not asign:
|
| 536 |
+
y = mpf_neg(mpf_pi(prec, rnd))
|
| 537 |
+
else:
|
| 538 |
+
y = fzero
|
| 539 |
+
return x, y
|
| 540 |
+
else:
|
| 541 |
+
return mpf_ei(a, prec, rnd), fzero
|
| 542 |
+
if a != fzero:
|
| 543 |
+
if not aman or not bman:
|
| 544 |
+
return (fnan, fnan)
|
| 545 |
+
wp = prec + 40
|
| 546 |
+
amag = aexp+abc
|
| 547 |
+
bmag = bexp+bbc
|
| 548 |
+
zmag = max(amag, bmag)
|
| 549 |
+
can_use_asymp = zmag > wp
|
| 550 |
+
if not can_use_asymp:
|
| 551 |
+
zabsint = abs(to_int(a)) + abs(to_int(b))
|
| 552 |
+
can_use_asymp = zabsint > int(wp*0.693) + 20
|
| 553 |
+
try:
|
| 554 |
+
if can_use_asymp:
|
| 555 |
+
if zmag > wp:
|
| 556 |
+
v = fone, fzero
|
| 557 |
+
else:
|
| 558 |
+
zre = to_fixed(a, wp)
|
| 559 |
+
zim = to_fixed(b, wp)
|
| 560 |
+
vre, vim = complex_ei_asymptotic(zre, zim, wp)
|
| 561 |
+
v = from_man_exp(vre, -wp), from_man_exp(vim, -wp)
|
| 562 |
+
v = mpc_mul(v, mpc_exp(z, wp), wp)
|
| 563 |
+
v = mpc_div(v, z, wp)
|
| 564 |
+
if e1:
|
| 565 |
+
v = mpc_neg(v, prec, rnd)
|
| 566 |
+
else:
|
| 567 |
+
x, y = v
|
| 568 |
+
if bsign:
|
| 569 |
+
v = mpf_pos(x, prec, rnd), mpf_sub(y, mpf_pi(wp), prec, rnd)
|
| 570 |
+
else:
|
| 571 |
+
v = mpf_pos(x, prec, rnd), mpf_add(y, mpf_pi(wp), prec, rnd)
|
| 572 |
+
return v
|
| 573 |
+
except NoConvergence:
|
| 574 |
+
pass
|
| 575 |
+
#wp += 2*max(0,zmag)
|
| 576 |
+
wp += 2*int(to_int(mpc_abs(z, 5)))
|
| 577 |
+
zre = to_fixed(a, wp)
|
| 578 |
+
zim = to_fixed(b, wp)
|
| 579 |
+
vre, vim = complex_ei_taylor(zre, zim, wp)
|
| 580 |
+
vre += euler_fixed(wp)
|
| 581 |
+
v = from_man_exp(vre,-wp), from_man_exp(vim,-wp)
|
| 582 |
+
if e1:
|
| 583 |
+
u = mpc_log(mpc_neg(z),wp)
|
| 584 |
+
else:
|
| 585 |
+
u = mpc_log(z,wp)
|
| 586 |
+
v = mpc_add(v, u, prec, rnd)
|
| 587 |
+
if e1:
|
| 588 |
+
v = mpc_neg(v)
|
| 589 |
+
return v
|
| 590 |
+
|
| 591 |
+
def mpf_e1(x, prec, rnd=round_fast):
|
| 592 |
+
return mpf_ei(x, prec, rnd, True)
|
| 593 |
+
|
| 594 |
+
def mpc_e1(x, prec, rnd=round_fast):
|
| 595 |
+
return mpc_ei(x, prec, rnd, True)
|
| 596 |
+
|
| 597 |
+
def mpf_expint(n, x, prec, rnd=round_fast, gamma=False):
|
| 598 |
+
"""
|
| 599 |
+
E_n(x), n an integer, x real
|
| 600 |
+
|
| 601 |
+
With gamma=True, computes Gamma(n,x) (upper incomplete gamma function)
|
| 602 |
+
|
| 603 |
+
Returns (real, None) if real, otherwise (real, imag)
|
| 604 |
+
The imaginary part is an optional branch cut term
|
| 605 |
+
|
| 606 |
+
"""
|
| 607 |
+
sign, man, exp, bc = x
|
| 608 |
+
if not man:
|
| 609 |
+
if gamma:
|
| 610 |
+
if x == fzero:
|
| 611 |
+
# Actually gamma function pole
|
| 612 |
+
if n <= 0:
|
| 613 |
+
return finf, None
|
| 614 |
+
return mpf_gamma_int(n, prec, rnd), None
|
| 615 |
+
if x == finf:
|
| 616 |
+
return fzero, None
|
| 617 |
+
# TODO: could return finite imaginary value at -inf
|
| 618 |
+
return fnan, fnan
|
| 619 |
+
else:
|
| 620 |
+
if x == fzero:
|
| 621 |
+
if n > 1:
|
| 622 |
+
return from_rational(1, n-1, prec, rnd), None
|
| 623 |
+
else:
|
| 624 |
+
return finf, None
|
| 625 |
+
if x == finf:
|
| 626 |
+
return fzero, None
|
| 627 |
+
return fnan, fnan
|
| 628 |
+
n_orig = n
|
| 629 |
+
if gamma:
|
| 630 |
+
n = 1-n
|
| 631 |
+
wp = prec + 20
|
| 632 |
+
xmag = exp + bc
|
| 633 |
+
# Beware of near-poles
|
| 634 |
+
if xmag < -10:
|
| 635 |
+
raise NotImplementedError
|
| 636 |
+
nmag = bitcount(abs(n))
|
| 637 |
+
have_imag = n > 0 and sign
|
| 638 |
+
negx = mpf_neg(x)
|
| 639 |
+
# Skip series if direct convergence
|
| 640 |
+
if n == 0 or 2*nmag - xmag < -wp:
|
| 641 |
+
if gamma:
|
| 642 |
+
v = mpf_exp(negx, wp)
|
| 643 |
+
re = mpf_mul(v, mpf_pow_int(x, n_orig-1, wp), prec, rnd)
|
| 644 |
+
else:
|
| 645 |
+
v = mpf_exp(negx, wp)
|
| 646 |
+
re = mpf_div(v, x, prec, rnd)
|
| 647 |
+
else:
|
| 648 |
+
# Finite number of terms, or...
|
| 649 |
+
can_use_asymptotic_series = -3*wp < n <= 0
|
| 650 |
+
# ...large enough?
|
| 651 |
+
if not can_use_asymptotic_series:
|
| 652 |
+
xi = abs(to_int(x))
|
| 653 |
+
m = min(max(1, xi-n), 2*wp)
|
| 654 |
+
siz = -n*nmag + (m+n)*bitcount(abs(m+n)) - m*xmag - (144*m//100)
|
| 655 |
+
tol = -wp-10
|
| 656 |
+
can_use_asymptotic_series = siz < tol
|
| 657 |
+
if can_use_asymptotic_series:
|
| 658 |
+
r = ((-MPZ_ONE) << (wp+wp)) // to_fixed(x, wp)
|
| 659 |
+
m = n
|
| 660 |
+
t = r*m
|
| 661 |
+
s = MPZ_ONE << wp
|
| 662 |
+
while m and t:
|
| 663 |
+
s += t
|
| 664 |
+
m += 1
|
| 665 |
+
t = (m*r*t) >> wp
|
| 666 |
+
v = mpf_exp(negx, wp)
|
| 667 |
+
if gamma:
|
| 668 |
+
# ~ exp(-x) * x^(n-1) * (1 + ...)
|
| 669 |
+
v = mpf_mul(v, mpf_pow_int(x, n_orig-1, wp), wp)
|
| 670 |
+
else:
|
| 671 |
+
# ~ exp(-x)/x * (1 + ...)
|
| 672 |
+
v = mpf_div(v, x, wp)
|
| 673 |
+
re = mpf_mul(v, from_man_exp(s, -wp), prec, rnd)
|
| 674 |
+
elif n == 1:
|
| 675 |
+
re = mpf_neg(mpf_ei(negx, prec, rnd))
|
| 676 |
+
elif n > 0 and n < 3*wp:
|
| 677 |
+
T1 = mpf_neg(mpf_ei(negx, wp))
|
| 678 |
+
if gamma:
|
| 679 |
+
if n_orig & 1:
|
| 680 |
+
T1 = mpf_neg(T1)
|
| 681 |
+
else:
|
| 682 |
+
T1 = mpf_mul(T1, mpf_pow_int(negx, n-1, wp), wp)
|
| 683 |
+
r = t = to_fixed(x, wp)
|
| 684 |
+
facs = [1] * (n-1)
|
| 685 |
+
for k in range(1,n-1):
|
| 686 |
+
facs[k] = facs[k-1] * k
|
| 687 |
+
facs = facs[::-1]
|
| 688 |
+
s = facs[0] << wp
|
| 689 |
+
for k in range(1, n-1):
|
| 690 |
+
if k & 1:
|
| 691 |
+
s -= facs[k] * t
|
| 692 |
+
else:
|
| 693 |
+
s += facs[k] * t
|
| 694 |
+
t = (t*r) >> wp
|
| 695 |
+
T2 = from_man_exp(s, -wp, wp)
|
| 696 |
+
T2 = mpf_mul(T2, mpf_exp(negx, wp))
|
| 697 |
+
if gamma:
|
| 698 |
+
T2 = mpf_mul(T2, mpf_pow_int(x, n_orig, wp), wp)
|
| 699 |
+
R = mpf_add(T1, T2)
|
| 700 |
+
re = mpf_div(R, from_int(ifac(n-1)), prec, rnd)
|
| 701 |
+
else:
|
| 702 |
+
raise NotImplementedError
|
| 703 |
+
if have_imag:
|
| 704 |
+
M = from_int(-ifac(n-1))
|
| 705 |
+
if gamma:
|
| 706 |
+
im = mpf_div(mpf_pi(wp), M, prec, rnd)
|
| 707 |
+
if n_orig & 1:
|
| 708 |
+
im = mpf_neg(im)
|
| 709 |
+
else:
|
| 710 |
+
im = mpf_div(mpf_mul(mpf_pi(wp), mpf_pow_int(negx, n_orig-1, wp), wp), M, prec, rnd)
|
| 711 |
+
return re, im
|
| 712 |
+
else:
|
| 713 |
+
return re, None
|
| 714 |
+
|
| 715 |
+
def mpf_ci_si_taylor(x, wp, which=0):
|
| 716 |
+
"""
|
| 717 |
+
0 - Ci(x) - (euler+log(x))
|
| 718 |
+
1 - Si(x)
|
| 719 |
+
"""
|
| 720 |
+
x = to_fixed(x, wp)
|
| 721 |
+
x2 = -(x*x) >> wp
|
| 722 |
+
if which == 0:
|
| 723 |
+
s, t, k = 0, (MPZ_ONE<<wp), 2
|
| 724 |
+
else:
|
| 725 |
+
s, t, k = x, x, 3
|
| 726 |
+
while t:
|
| 727 |
+
t = (t*x2//(k*(k-1)))>>wp
|
| 728 |
+
s += t//k
|
| 729 |
+
k += 2
|
| 730 |
+
return from_man_exp(s, -wp)
|
| 731 |
+
|
| 732 |
+
def mpc_ci_si_taylor(re, im, wp, which=0):
|
| 733 |
+
# The following code is only designed for small arguments,
|
| 734 |
+
# and not too small arguments (for relative accuracy)
|
| 735 |
+
if re[1]:
|
| 736 |
+
mag = re[2]+re[3]
|
| 737 |
+
elif im[1]:
|
| 738 |
+
mag = im[2]+im[3]
|
| 739 |
+
if im[1]:
|
| 740 |
+
mag = max(mag, im[2]+im[3])
|
| 741 |
+
if mag > 2 or mag < -wp:
|
| 742 |
+
raise NotImplementedError
|
| 743 |
+
wp += (2-mag)
|
| 744 |
+
zre = to_fixed(re, wp)
|
| 745 |
+
zim = to_fixed(im, wp)
|
| 746 |
+
z2re = (zim*zim-zre*zre)>>wp
|
| 747 |
+
z2im = (-2*zre*zim)>>wp
|
| 748 |
+
tre = zre
|
| 749 |
+
tim = zim
|
| 750 |
+
one = MPZ_ONE<<wp
|
| 751 |
+
if which == 0:
|
| 752 |
+
sre, sim, tre, tim, k = 0, 0, (MPZ_ONE<<wp), 0, 2
|
| 753 |
+
else:
|
| 754 |
+
sre, sim, tre, tim, k = zre, zim, zre, zim, 3
|
| 755 |
+
while max(abs(tre), abs(tim)) > 2:
|
| 756 |
+
f = k*(k-1)
|
| 757 |
+
tre, tim = ((tre*z2re-tim*z2im)//f)>>wp, ((tre*z2im+tim*z2re)//f)>>wp
|
| 758 |
+
sre += tre//k
|
| 759 |
+
sim += tim//k
|
| 760 |
+
k += 2
|
| 761 |
+
return from_man_exp(sre, -wp), from_man_exp(sim, -wp)
|
| 762 |
+
|
| 763 |
+
def mpf_ci_si(x, prec, rnd=round_fast, which=2):
|
| 764 |
+
"""
|
| 765 |
+
Calculation of Ci(x), Si(x) for real x.
|
| 766 |
+
|
| 767 |
+
which = 0 -- returns (Ci(x), -)
|
| 768 |
+
which = 1 -- returns (Si(x), -)
|
| 769 |
+
which = 2 -- returns (Ci(x), Si(x))
|
| 770 |
+
|
| 771 |
+
Note: if x < 0, Ci(x) needs an additional imaginary term, pi*i.
|
| 772 |
+
"""
|
| 773 |
+
wp = prec + 20
|
| 774 |
+
sign, man, exp, bc = x
|
| 775 |
+
ci, si = None, None
|
| 776 |
+
if not man:
|
| 777 |
+
if x == fzero:
|
| 778 |
+
return (fninf, fzero)
|
| 779 |
+
if x == fnan:
|
| 780 |
+
return (x, x)
|
| 781 |
+
ci = fzero
|
| 782 |
+
if which != 0:
|
| 783 |
+
if x == finf:
|
| 784 |
+
si = mpf_shift(mpf_pi(prec, rnd), -1)
|
| 785 |
+
if x == fninf:
|
| 786 |
+
si = mpf_neg(mpf_shift(mpf_pi(prec, negative_rnd[rnd]), -1))
|
| 787 |
+
return (ci, si)
|
| 788 |
+
# For small x: Ci(x) ~ euler + log(x), Si(x) ~ x
|
| 789 |
+
mag = exp+bc
|
| 790 |
+
if mag < -wp:
|
| 791 |
+
if which != 0:
|
| 792 |
+
si = mpf_perturb(x, 1-sign, prec, rnd)
|
| 793 |
+
if which != 1:
|
| 794 |
+
y = mpf_euler(wp)
|
| 795 |
+
xabs = mpf_abs(x)
|
| 796 |
+
ci = mpf_add(y, mpf_log(xabs, wp), prec, rnd)
|
| 797 |
+
return ci, si
|
| 798 |
+
# For huge x: Ci(x) ~ sin(x)/x, Si(x) ~ pi/2
|
| 799 |
+
elif mag > wp:
|
| 800 |
+
if which != 0:
|
| 801 |
+
if sign:
|
| 802 |
+
si = mpf_neg(mpf_pi(prec, negative_rnd[rnd]))
|
| 803 |
+
else:
|
| 804 |
+
si = mpf_pi(prec, rnd)
|
| 805 |
+
si = mpf_shift(si, -1)
|
| 806 |
+
if which != 1:
|
| 807 |
+
ci = mpf_div(mpf_sin(x, wp), x, prec, rnd)
|
| 808 |
+
return ci, si
|
| 809 |
+
else:
|
| 810 |
+
wp += abs(mag)
|
| 811 |
+
# Use an asymptotic series? The smallest value of n!/x^n
|
| 812 |
+
# occurs for n ~ x, where the magnitude is ~ exp(-x).
|
| 813 |
+
asymptotic = mag-1 > math.log(wp, 2)
|
| 814 |
+
# Case 1: convergent series near 0
|
| 815 |
+
if not asymptotic:
|
| 816 |
+
if which != 0:
|
| 817 |
+
si = mpf_pos(mpf_ci_si_taylor(x, wp, 1), prec, rnd)
|
| 818 |
+
if which != 1:
|
| 819 |
+
ci = mpf_ci_si_taylor(x, wp, 0)
|
| 820 |
+
ci = mpf_add(ci, mpf_euler(wp), wp)
|
| 821 |
+
ci = mpf_add(ci, mpf_log(mpf_abs(x), wp), prec, rnd)
|
| 822 |
+
return ci, si
|
| 823 |
+
x = mpf_abs(x)
|
| 824 |
+
# Case 2: asymptotic series for x >> 1
|
| 825 |
+
xf = to_fixed(x, wp)
|
| 826 |
+
xr = (MPZ_ONE<<(2*wp)) // xf # 1/x
|
| 827 |
+
s1 = (MPZ_ONE << wp)
|
| 828 |
+
s2 = xr
|
| 829 |
+
t = xr
|
| 830 |
+
k = 2
|
| 831 |
+
while t:
|
| 832 |
+
t = -t
|
| 833 |
+
t = (t*xr*k)>>wp
|
| 834 |
+
k += 1
|
| 835 |
+
s1 += t
|
| 836 |
+
t = (t*xr*k)>>wp
|
| 837 |
+
k += 1
|
| 838 |
+
s2 += t
|
| 839 |
+
s1 = from_man_exp(s1, -wp)
|
| 840 |
+
s2 = from_man_exp(s2, -wp)
|
| 841 |
+
s1 = mpf_div(s1, x, wp)
|
| 842 |
+
s2 = mpf_div(s2, x, wp)
|
| 843 |
+
cos, sin = mpf_cos_sin(x, wp)
|
| 844 |
+
# Ci(x) = sin(x)*s1-cos(x)*s2
|
| 845 |
+
# Si(x) = pi/2-cos(x)*s1-sin(x)*s2
|
| 846 |
+
if which != 0:
|
| 847 |
+
si = mpf_add(mpf_mul(cos, s1), mpf_mul(sin, s2), wp)
|
| 848 |
+
si = mpf_sub(mpf_shift(mpf_pi(wp), -1), si, wp)
|
| 849 |
+
if sign:
|
| 850 |
+
si = mpf_neg(si)
|
| 851 |
+
si = mpf_pos(si, prec, rnd)
|
| 852 |
+
if which != 1:
|
| 853 |
+
ci = mpf_sub(mpf_mul(sin, s1), mpf_mul(cos, s2), prec, rnd)
|
| 854 |
+
return ci, si
|
| 855 |
+
|
| 856 |
+
def mpf_ci(x, prec, rnd=round_fast):
|
| 857 |
+
if mpf_sign(x) < 0:
|
| 858 |
+
raise ComplexResult
|
| 859 |
+
return mpf_ci_si(x, prec, rnd, 0)[0]
|
| 860 |
+
|
| 861 |
+
def mpf_si(x, prec, rnd=round_fast):
|
| 862 |
+
return mpf_ci_si(x, prec, rnd, 1)[1]
|
| 863 |
+
|
| 864 |
+
def mpc_ci(z, prec, rnd=round_fast):
|
| 865 |
+
re, im = z
|
| 866 |
+
if im == fzero:
|
| 867 |
+
ci = mpf_ci_si(re, prec, rnd, 0)[0]
|
| 868 |
+
if mpf_sign(re) < 0:
|
| 869 |
+
return (ci, mpf_pi(prec, rnd))
|
| 870 |
+
return (ci, fzero)
|
| 871 |
+
wp = prec + 20
|
| 872 |
+
cre, cim = mpc_ci_si_taylor(re, im, wp, 0)
|
| 873 |
+
cre = mpf_add(cre, mpf_euler(wp), wp)
|
| 874 |
+
ci = mpc_add((cre, cim), mpc_log(z, wp), prec, rnd)
|
| 875 |
+
return ci
|
| 876 |
+
|
| 877 |
+
def mpc_si(z, prec, rnd=round_fast):
|
| 878 |
+
re, im = z
|
| 879 |
+
if im == fzero:
|
| 880 |
+
return (mpf_ci_si(re, prec, rnd, 1)[1], fzero)
|
| 881 |
+
wp = prec + 20
|
| 882 |
+
z = mpc_ci_si_taylor(re, im, wp, 1)
|
| 883 |
+
return mpc_pos(z, prec, rnd)
|
| 884 |
+
|
| 885 |
+
|
| 886 |
+
#-----------------------------------------------------------------------#
|
| 887 |
+
# #
|
| 888 |
+
# Bessel functions #
|
| 889 |
+
# #
|
| 890 |
+
#-----------------------------------------------------------------------#
|
| 891 |
+
|
| 892 |
+
# A Bessel function of the first kind of integer order, J_n(x), is
|
| 893 |
+
# given by the power series
|
| 894 |
+
|
| 895 |
+
# oo
|
| 896 |
+
# ___ k 2 k + n
|
| 897 |
+
# \ (-1) / x \
|
| 898 |
+
# J_n(x) = ) ----------- | - |
|
| 899 |
+
# /___ k! (k + n)! \ 2 /
|
| 900 |
+
# k = 0
|
| 901 |
+
|
| 902 |
+
# Simplifying the quotient between two successive terms gives the
|
| 903 |
+
# ratio x^2 / (-4*k*(k+n)). Hence, we only need one full-precision
|
| 904 |
+
# multiplication and one division by a small integer per term.
|
| 905 |
+
# The complex version is very similar, the only difference being
|
| 906 |
+
# that the multiplication is actually 4 multiplies.
|
| 907 |
+
|
| 908 |
+
# In the general case, we have
|
| 909 |
+
# J_v(x) = (x/2)**v / v! * 0F1(v+1, (-1/4)*z**2)
|
| 910 |
+
|
| 911 |
+
# TODO: for extremely large x, we could use an asymptotic
|
| 912 |
+
# trigonometric approximation.
|
| 913 |
+
|
| 914 |
+
# TODO: recompute at higher precision if the fixed-point mantissa
|
| 915 |
+
# is very small
|
| 916 |
+
|
| 917 |
+
def mpf_besseljn(n, x, prec, rounding=round_fast):
|
| 918 |
+
prec += 50
|
| 919 |
+
negate = n < 0 and n & 1
|
| 920 |
+
mag = x[2]+x[3]
|
| 921 |
+
n = abs(n)
|
| 922 |
+
wp = prec + 20 + n*bitcount(n)
|
| 923 |
+
if mag < 0:
|
| 924 |
+
wp -= n * mag
|
| 925 |
+
x = to_fixed(x, wp)
|
| 926 |
+
x2 = (x**2) >> wp
|
| 927 |
+
if not n:
|
| 928 |
+
s = t = MPZ_ONE << wp
|
| 929 |
+
else:
|
| 930 |
+
s = t = (x**n // ifac(n)) >> ((n-1)*wp + n)
|
| 931 |
+
k = 1
|
| 932 |
+
while t:
|
| 933 |
+
t = ((t * x2) // (-4*k*(k+n))) >> wp
|
| 934 |
+
s += t
|
| 935 |
+
k += 1
|
| 936 |
+
if negate:
|
| 937 |
+
s = -s
|
| 938 |
+
return from_man_exp(s, -wp, prec, rounding)
|
| 939 |
+
|
| 940 |
+
def mpc_besseljn(n, z, prec, rounding=round_fast):
|
| 941 |
+
negate = n < 0 and n & 1
|
| 942 |
+
n = abs(n)
|
| 943 |
+
origprec = prec
|
| 944 |
+
zre, zim = z
|
| 945 |
+
mag = max(zre[2]+zre[3], zim[2]+zim[3])
|
| 946 |
+
prec += 20 + n*bitcount(n) + abs(mag)
|
| 947 |
+
if mag < 0:
|
| 948 |
+
prec -= n * mag
|
| 949 |
+
zre = to_fixed(zre, prec)
|
| 950 |
+
zim = to_fixed(zim, prec)
|
| 951 |
+
z2re = (zre**2 - zim**2) >> prec
|
| 952 |
+
z2im = (zre*zim) >> (prec-1)
|
| 953 |
+
if not n:
|
| 954 |
+
sre = tre = MPZ_ONE << prec
|
| 955 |
+
sim = tim = MPZ_ZERO
|
| 956 |
+
else:
|
| 957 |
+
re, im = complex_int_pow(zre, zim, n)
|
| 958 |
+
sre = tre = (re // ifac(n)) >> ((n-1)*prec + n)
|
| 959 |
+
sim = tim = (im // ifac(n)) >> ((n-1)*prec + n)
|
| 960 |
+
k = 1
|
| 961 |
+
while abs(tre) + abs(tim) > 3:
|
| 962 |
+
p = -4*k*(k+n)
|
| 963 |
+
tre, tim = tre*z2re - tim*z2im, tim*z2re + tre*z2im
|
| 964 |
+
tre = (tre // p) >> prec
|
| 965 |
+
tim = (tim // p) >> prec
|
| 966 |
+
sre += tre
|
| 967 |
+
sim += tim
|
| 968 |
+
k += 1
|
| 969 |
+
if negate:
|
| 970 |
+
sre = -sre
|
| 971 |
+
sim = -sim
|
| 972 |
+
re = from_man_exp(sre, -prec, origprec, rounding)
|
| 973 |
+
im = from_man_exp(sim, -prec, origprec, rounding)
|
| 974 |
+
return (re, im)
|
| 975 |
+
|
| 976 |
+
def mpf_agm(a, b, prec, rnd=round_fast):
|
| 977 |
+
"""
|
| 978 |
+
Computes the arithmetic-geometric mean agm(a,b) for
|
| 979 |
+
nonnegative mpf values a, b.
|
| 980 |
+
"""
|
| 981 |
+
asign, aman, aexp, abc = a
|
| 982 |
+
bsign, bman, bexp, bbc = b
|
| 983 |
+
if asign or bsign:
|
| 984 |
+
raise ComplexResult("agm of a negative number")
|
| 985 |
+
# Handle inf, nan or zero in either operand
|
| 986 |
+
if not (aman and bman):
|
| 987 |
+
if a == fnan or b == fnan:
|
| 988 |
+
return fnan
|
| 989 |
+
if a == finf:
|
| 990 |
+
if b == fzero:
|
| 991 |
+
return fnan
|
| 992 |
+
return finf
|
| 993 |
+
if b == finf:
|
| 994 |
+
if a == fzero:
|
| 995 |
+
return fnan
|
| 996 |
+
return finf
|
| 997 |
+
# agm(0,x) = agm(x,0) = 0
|
| 998 |
+
return fzero
|
| 999 |
+
wp = prec + 20
|
| 1000 |
+
amag = aexp+abc
|
| 1001 |
+
bmag = bexp+bbc
|
| 1002 |
+
mag_delta = amag - bmag
|
| 1003 |
+
# Reduce to roughly the same magnitude using floating-point AGM
|
| 1004 |
+
abs_mag_delta = abs(mag_delta)
|
| 1005 |
+
if abs_mag_delta > 10:
|
| 1006 |
+
while abs_mag_delta > 10:
|
| 1007 |
+
a, b = mpf_shift(mpf_add(a,b,wp),-1), \
|
| 1008 |
+
mpf_sqrt(mpf_mul(a,b,wp),wp)
|
| 1009 |
+
abs_mag_delta //= 2
|
| 1010 |
+
asign, aman, aexp, abc = a
|
| 1011 |
+
bsign, bman, bexp, bbc = b
|
| 1012 |
+
amag = aexp+abc
|
| 1013 |
+
bmag = bexp+bbc
|
| 1014 |
+
mag_delta = amag - bmag
|
| 1015 |
+
#print to_float(a), to_float(b)
|
| 1016 |
+
# Use agm(a,b) = agm(x*a,x*b)/x to obtain a, b ~= 1
|
| 1017 |
+
min_mag = min(amag,bmag)
|
| 1018 |
+
max_mag = max(amag,bmag)
|
| 1019 |
+
n = 0
|
| 1020 |
+
# If too small, we lose precision when going to fixed-point
|
| 1021 |
+
if min_mag < -8:
|
| 1022 |
+
n = -min_mag
|
| 1023 |
+
# If too large, we waste time using fixed-point with large numbers
|
| 1024 |
+
elif max_mag > 20:
|
| 1025 |
+
n = -max_mag
|
| 1026 |
+
if n:
|
| 1027 |
+
a = mpf_shift(a, n)
|
| 1028 |
+
b = mpf_shift(b, n)
|
| 1029 |
+
#print to_float(a), to_float(b)
|
| 1030 |
+
af = to_fixed(a, wp)
|
| 1031 |
+
bf = to_fixed(b, wp)
|
| 1032 |
+
g = agm_fixed(af, bf, wp)
|
| 1033 |
+
return from_man_exp(g, -wp-n, prec, rnd)
|
| 1034 |
+
|
| 1035 |
+
def mpf_agm1(a, prec, rnd=round_fast):
|
| 1036 |
+
"""
|
| 1037 |
+
Computes the arithmetic-geometric mean agm(1,a) for a nonnegative
|
| 1038 |
+
mpf value a.
|
| 1039 |
+
"""
|
| 1040 |
+
return mpf_agm(fone, a, prec, rnd)
|
| 1041 |
+
|
| 1042 |
+
def mpc_agm(a, b, prec, rnd=round_fast):
|
| 1043 |
+
"""
|
| 1044 |
+
Complex AGM.
|
| 1045 |
+
|
| 1046 |
+
TODO:
|
| 1047 |
+
* check that convergence works as intended
|
| 1048 |
+
* optimize
|
| 1049 |
+
* select a nonarbitrary branch
|
| 1050 |
+
"""
|
| 1051 |
+
if mpc_is_infnan(a) or mpc_is_infnan(b):
|
| 1052 |
+
return fnan, fnan
|
| 1053 |
+
if mpc_zero in (a, b):
|
| 1054 |
+
return fzero, fzero
|
| 1055 |
+
if mpc_neg(a) == b:
|
| 1056 |
+
return fzero, fzero
|
| 1057 |
+
wp = prec+20
|
| 1058 |
+
eps = mpf_shift(fone, -wp+10)
|
| 1059 |
+
while 1:
|
| 1060 |
+
a1 = mpc_shift(mpc_add(a, b, wp), -1)
|
| 1061 |
+
b1 = mpc_sqrt(mpc_mul(a, b, wp), wp)
|
| 1062 |
+
a, b = a1, b1
|
| 1063 |
+
size = mpf_min_max([mpc_abs(a,10), mpc_abs(b,10)])[1]
|
| 1064 |
+
err = mpc_abs(mpc_sub(a, b, 10), 10)
|
| 1065 |
+
if size == fzero or mpf_lt(err, mpf_mul(eps, size)):
|
| 1066 |
+
return a
|
| 1067 |
+
|
| 1068 |
+
def mpc_agm1(a, prec, rnd=round_fast):
|
| 1069 |
+
return mpc_agm(mpc_one, a, prec, rnd)
|
| 1070 |
+
|
| 1071 |
+
def mpf_ellipk(x, prec, rnd=round_fast):
|
| 1072 |
+
if not x[1]:
|
| 1073 |
+
if x == fzero:
|
| 1074 |
+
return mpf_shift(mpf_pi(prec, rnd), -1)
|
| 1075 |
+
if x == fninf:
|
| 1076 |
+
return fzero
|
| 1077 |
+
if x == fnan:
|
| 1078 |
+
return x
|
| 1079 |
+
if x == fone:
|
| 1080 |
+
return finf
|
| 1081 |
+
# TODO: for |x| << 1/2, one could use fall back to
|
| 1082 |
+
# pi/2 * hyp2f1_rat((1,2),(1,2),(1,1), x)
|
| 1083 |
+
wp = prec + 15
|
| 1084 |
+
# Use K(x) = pi/2/agm(1,a) where a = sqrt(1-x)
|
| 1085 |
+
# The sqrt raises ComplexResult if x > 0
|
| 1086 |
+
a = mpf_sqrt(mpf_sub(fone, x, wp), wp)
|
| 1087 |
+
v = mpf_agm1(a, wp)
|
| 1088 |
+
r = mpf_div(mpf_pi(wp), v, prec, rnd)
|
| 1089 |
+
return mpf_shift(r, -1)
|
| 1090 |
+
|
| 1091 |
+
def mpc_ellipk(z, prec, rnd=round_fast):
|
| 1092 |
+
re, im = z
|
| 1093 |
+
if im == fzero:
|
| 1094 |
+
if re == finf:
|
| 1095 |
+
return mpc_zero
|
| 1096 |
+
if mpf_le(re, fone):
|
| 1097 |
+
return mpf_ellipk(re, prec, rnd), fzero
|
| 1098 |
+
wp = prec + 15
|
| 1099 |
+
a = mpc_sqrt(mpc_sub(mpc_one, z, wp), wp)
|
| 1100 |
+
v = mpc_agm1(a, wp)
|
| 1101 |
+
r = mpc_mpf_div(mpf_pi(wp), v, prec, rnd)
|
| 1102 |
+
return mpc_shift(r, -1)
|
| 1103 |
+
|
| 1104 |
+
def mpf_ellipe(x, prec, rnd=round_fast):
|
| 1105 |
+
# http://functions.wolfram.com/EllipticIntegrals/
|
| 1106 |
+
# EllipticK/20/01/0001/
|
| 1107 |
+
# E = (1-m)*(K'(m)*2*m + K(m))
|
| 1108 |
+
sign, man, exp, bc = x
|
| 1109 |
+
if not man:
|
| 1110 |
+
if x == fzero:
|
| 1111 |
+
return mpf_shift(mpf_pi(prec, rnd), -1)
|
| 1112 |
+
if x == fninf:
|
| 1113 |
+
return finf
|
| 1114 |
+
if x == fnan:
|
| 1115 |
+
return x
|
| 1116 |
+
if x == finf:
|
| 1117 |
+
raise ComplexResult
|
| 1118 |
+
if x == fone:
|
| 1119 |
+
return fone
|
| 1120 |
+
wp = prec+20
|
| 1121 |
+
mag = exp+bc
|
| 1122 |
+
if mag < -wp:
|
| 1123 |
+
return mpf_shift(mpf_pi(prec, rnd), -1)
|
| 1124 |
+
# Compute a finite difference for K'
|
| 1125 |
+
p = max(mag, 0) - wp
|
| 1126 |
+
h = mpf_shift(fone, p)
|
| 1127 |
+
K = mpf_ellipk(x, 2*wp)
|
| 1128 |
+
Kh = mpf_ellipk(mpf_sub(x, h), 2*wp)
|
| 1129 |
+
Kdiff = mpf_shift(mpf_sub(K, Kh), -p)
|
| 1130 |
+
t = mpf_sub(fone, x)
|
| 1131 |
+
b = mpf_mul(Kdiff, mpf_shift(x,1), wp)
|
| 1132 |
+
return mpf_mul(t, mpf_add(K, b), prec, rnd)
|
| 1133 |
+
|
| 1134 |
+
def mpc_ellipe(z, prec, rnd=round_fast):
|
| 1135 |
+
re, im = z
|
| 1136 |
+
if im == fzero:
|
| 1137 |
+
if re == finf:
|
| 1138 |
+
return (fzero, finf)
|
| 1139 |
+
if mpf_le(re, fone):
|
| 1140 |
+
return mpf_ellipe(re, prec, rnd), fzero
|
| 1141 |
+
wp = prec + 15
|
| 1142 |
+
mag = mpc_abs(z, 1)
|
| 1143 |
+
p = max(mag[2]+mag[3], 0) - wp
|
| 1144 |
+
h = mpf_shift(fone, p)
|
| 1145 |
+
K = mpc_ellipk(z, 2*wp)
|
| 1146 |
+
Kh = mpc_ellipk(mpc_add_mpf(z, h, 2*wp), 2*wp)
|
| 1147 |
+
Kdiff = mpc_shift(mpc_sub(Kh, K, wp), -p)
|
| 1148 |
+
t = mpc_sub(mpc_one, z, wp)
|
| 1149 |
+
b = mpc_mul(Kdiff, mpc_shift(z,1), wp)
|
| 1150 |
+
return mpc_mul(t, mpc_add(K, b, wp), prec, rnd)
|
.venv/lib/python3.11/site-packages/mpmath/libmp/libintmath.py
ADDED
|
@@ -0,0 +1,584 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Utility functions for integer math.
|
| 3 |
+
|
| 4 |
+
TODO: rename, cleanup, perhaps move the gmpy wrapper code
|
| 5 |
+
here from settings.py
|
| 6 |
+
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import math
|
| 10 |
+
from bisect import bisect
|
| 11 |
+
|
| 12 |
+
from .backend import xrange
|
| 13 |
+
from .backend import BACKEND, gmpy, sage, sage_utils, MPZ, MPZ_ONE, MPZ_ZERO
|
| 14 |
+
|
| 15 |
+
small_trailing = [0] * 256
|
| 16 |
+
for j in range(1,8):
|
| 17 |
+
small_trailing[1<<j::1<<(j+1)] = [j] * (1<<(7-j))
|
| 18 |
+
|
| 19 |
+
def giant_steps(start, target, n=2):
|
| 20 |
+
"""
|
| 21 |
+
Return a list of integers ~=
|
| 22 |
+
|
| 23 |
+
[start, n*start, ..., target/n^2, target/n, target]
|
| 24 |
+
|
| 25 |
+
but conservatively rounded so that the quotient between two
|
| 26 |
+
successive elements is actually slightly less than n.
|
| 27 |
+
|
| 28 |
+
With n = 2, this describes suitable precision steps for a
|
| 29 |
+
quadratically convergent algorithm such as Newton's method;
|
| 30 |
+
with n = 3 steps for cubic convergence (Halley's method), etc.
|
| 31 |
+
|
| 32 |
+
>>> giant_steps(50,1000)
|
| 33 |
+
[66, 128, 253, 502, 1000]
|
| 34 |
+
>>> giant_steps(50,1000,4)
|
| 35 |
+
[65, 252, 1000]
|
| 36 |
+
|
| 37 |
+
"""
|
| 38 |
+
L = [target]
|
| 39 |
+
while L[-1] > start*n:
|
| 40 |
+
L = L + [L[-1]//n + 2]
|
| 41 |
+
return L[::-1]
|
| 42 |
+
|
| 43 |
+
def rshift(x, n):
|
| 44 |
+
"""For an integer x, calculate x >> n with the fastest (floor)
|
| 45 |
+
rounding. Unlike the plain Python expression (x >> n), n is
|
| 46 |
+
allowed to be negative, in which case a left shift is performed."""
|
| 47 |
+
if n >= 0: return x >> n
|
| 48 |
+
else: return x << (-n)
|
| 49 |
+
|
| 50 |
+
def lshift(x, n):
|
| 51 |
+
"""For an integer x, calculate x << n. Unlike the plain Python
|
| 52 |
+
expression (x << n), n is allowed to be negative, in which case a
|
| 53 |
+
right shift with default (floor) rounding is performed."""
|
| 54 |
+
if n >= 0: return x << n
|
| 55 |
+
else: return x >> (-n)
|
| 56 |
+
|
| 57 |
+
if BACKEND == 'sage':
|
| 58 |
+
import operator
|
| 59 |
+
rshift = operator.rshift
|
| 60 |
+
lshift = operator.lshift
|
| 61 |
+
|
| 62 |
+
def python_trailing(n):
|
| 63 |
+
"""Count the number of trailing zero bits in abs(n)."""
|
| 64 |
+
if not n:
|
| 65 |
+
return 0
|
| 66 |
+
low_byte = n & 0xff
|
| 67 |
+
if low_byte:
|
| 68 |
+
return small_trailing[low_byte]
|
| 69 |
+
t = 8
|
| 70 |
+
n >>= 8
|
| 71 |
+
while not n & 0xff:
|
| 72 |
+
n >>= 8
|
| 73 |
+
t += 8
|
| 74 |
+
return t + small_trailing[n & 0xff]
|
| 75 |
+
|
| 76 |
+
if BACKEND == 'gmpy':
|
| 77 |
+
if gmpy.version() >= '2':
|
| 78 |
+
def gmpy_trailing(n):
|
| 79 |
+
"""Count the number of trailing zero bits in abs(n) using gmpy."""
|
| 80 |
+
if n: return MPZ(n).bit_scan1()
|
| 81 |
+
else: return 0
|
| 82 |
+
else:
|
| 83 |
+
def gmpy_trailing(n):
|
| 84 |
+
"""Count the number of trailing zero bits in abs(n) using gmpy."""
|
| 85 |
+
if n: return MPZ(n).scan1()
|
| 86 |
+
else: return 0
|
| 87 |
+
|
| 88 |
+
# Small powers of 2
|
| 89 |
+
powers = [1<<_ for _ in range(300)]
|
| 90 |
+
|
| 91 |
+
def python_bitcount(n):
|
| 92 |
+
"""Calculate bit size of the nonnegative integer n."""
|
| 93 |
+
bc = bisect(powers, n)
|
| 94 |
+
if bc != 300:
|
| 95 |
+
return bc
|
| 96 |
+
bc = int(math.log(n, 2)) - 4
|
| 97 |
+
return bc + bctable[n>>bc]
|
| 98 |
+
|
| 99 |
+
def gmpy_bitcount(n):
|
| 100 |
+
"""Calculate bit size of the nonnegative integer n."""
|
| 101 |
+
if n: return MPZ(n).numdigits(2)
|
| 102 |
+
else: return 0
|
| 103 |
+
|
| 104 |
+
#def sage_bitcount(n):
|
| 105 |
+
# if n: return MPZ(n).nbits()
|
| 106 |
+
# else: return 0
|
| 107 |
+
|
| 108 |
+
def sage_trailing(n):
|
| 109 |
+
return MPZ(n).trailing_zero_bits()
|
| 110 |
+
|
| 111 |
+
if BACKEND == 'gmpy':
|
| 112 |
+
bitcount = gmpy_bitcount
|
| 113 |
+
trailing = gmpy_trailing
|
| 114 |
+
elif BACKEND == 'sage':
|
| 115 |
+
sage_bitcount = sage_utils.bitcount
|
| 116 |
+
bitcount = sage_bitcount
|
| 117 |
+
trailing = sage_trailing
|
| 118 |
+
else:
|
| 119 |
+
bitcount = python_bitcount
|
| 120 |
+
trailing = python_trailing
|
| 121 |
+
|
| 122 |
+
if BACKEND == 'gmpy' and 'bit_length' in dir(gmpy):
|
| 123 |
+
bitcount = gmpy.bit_length
|
| 124 |
+
|
| 125 |
+
# Used to avoid slow function calls as far as possible
|
| 126 |
+
trailtable = [trailing(n) for n in range(256)]
|
| 127 |
+
bctable = [bitcount(n) for n in range(1024)]
|
| 128 |
+
|
| 129 |
+
# TODO: speed up for bases 2, 4, 8, 16, ...
|
| 130 |
+
|
| 131 |
+
def bin_to_radix(x, xbits, base, bdigits):
|
| 132 |
+
"""Changes radix of a fixed-point number; i.e., converts
|
| 133 |
+
x * 2**xbits to floor(x * 10**bdigits)."""
|
| 134 |
+
return x * (MPZ(base)**bdigits) >> xbits
|
| 135 |
+
|
| 136 |
+
stddigits = '0123456789abcdefghijklmnopqrstuvwxyz'
|
| 137 |
+
|
| 138 |
+
def small_numeral(n, base=10, digits=stddigits):
|
| 139 |
+
"""Return the string numeral of a positive integer in an arbitrary
|
| 140 |
+
base. Most efficient for small input."""
|
| 141 |
+
if base == 10:
|
| 142 |
+
return str(n)
|
| 143 |
+
digs = []
|
| 144 |
+
while n:
|
| 145 |
+
n, digit = divmod(n, base)
|
| 146 |
+
digs.append(digits[digit])
|
| 147 |
+
return "".join(digs[::-1])
|
| 148 |
+
|
| 149 |
+
def numeral_python(n, base=10, size=0, digits=stddigits):
|
| 150 |
+
"""Represent the integer n as a string of digits in the given base.
|
| 151 |
+
Recursive division is used to make this function about 3x faster
|
| 152 |
+
than Python's str() for converting integers to decimal strings.
|
| 153 |
+
|
| 154 |
+
The 'size' parameters specifies the number of digits in n; this
|
| 155 |
+
number is only used to determine splitting points and need not be
|
| 156 |
+
exact."""
|
| 157 |
+
if n <= 0:
|
| 158 |
+
if not n:
|
| 159 |
+
return "0"
|
| 160 |
+
return "-" + numeral(-n, base, size, digits)
|
| 161 |
+
# Fast enough to do directly
|
| 162 |
+
if size < 250:
|
| 163 |
+
return small_numeral(n, base, digits)
|
| 164 |
+
# Divide in half
|
| 165 |
+
half = (size // 2) + (size & 1)
|
| 166 |
+
A, B = divmod(n, base**half)
|
| 167 |
+
ad = numeral(A, base, half, digits)
|
| 168 |
+
bd = numeral(B, base, half, digits).rjust(half, "0")
|
| 169 |
+
return ad + bd
|
| 170 |
+
|
| 171 |
+
def numeral_gmpy(n, base=10, size=0, digits=stddigits):
|
| 172 |
+
"""Represent the integer n as a string of digits in the given base.
|
| 173 |
+
Recursive division is used to make this function about 3x faster
|
| 174 |
+
than Python's str() for converting integers to decimal strings.
|
| 175 |
+
|
| 176 |
+
The 'size' parameters specifies the number of digits in n; this
|
| 177 |
+
number is only used to determine splitting points and need not be
|
| 178 |
+
exact."""
|
| 179 |
+
if n < 0:
|
| 180 |
+
return "-" + numeral(-n, base, size, digits)
|
| 181 |
+
# gmpy.digits() may cause a segmentation fault when trying to convert
|
| 182 |
+
# extremely large values to a string. The size limit may need to be
|
| 183 |
+
# adjusted on some platforms, but 1500000 works on Windows and Linux.
|
| 184 |
+
if size < 1500000:
|
| 185 |
+
return gmpy.digits(n, base)
|
| 186 |
+
# Divide in half
|
| 187 |
+
half = (size // 2) + (size & 1)
|
| 188 |
+
A, B = divmod(n, MPZ(base)**half)
|
| 189 |
+
ad = numeral(A, base, half, digits)
|
| 190 |
+
bd = numeral(B, base, half, digits).rjust(half, "0")
|
| 191 |
+
return ad + bd
|
| 192 |
+
|
| 193 |
+
if BACKEND == "gmpy":
|
| 194 |
+
numeral = numeral_gmpy
|
| 195 |
+
else:
|
| 196 |
+
numeral = numeral_python
|
| 197 |
+
|
| 198 |
+
_1_800 = 1<<800
|
| 199 |
+
_1_600 = 1<<600
|
| 200 |
+
_1_400 = 1<<400
|
| 201 |
+
_1_200 = 1<<200
|
| 202 |
+
_1_100 = 1<<100
|
| 203 |
+
_1_50 = 1<<50
|
| 204 |
+
|
| 205 |
+
def isqrt_small_python(x):
|
| 206 |
+
"""
|
| 207 |
+
Correctly (floor) rounded integer square root, using
|
| 208 |
+
division. Fast up to ~200 digits.
|
| 209 |
+
"""
|
| 210 |
+
if not x:
|
| 211 |
+
return x
|
| 212 |
+
if x < _1_800:
|
| 213 |
+
# Exact with IEEE double precision arithmetic
|
| 214 |
+
if x < _1_50:
|
| 215 |
+
return int(x**0.5)
|
| 216 |
+
# Initial estimate can be any integer >= the true root; round up
|
| 217 |
+
r = int(x**0.5 * 1.00000000000001) + 1
|
| 218 |
+
else:
|
| 219 |
+
bc = bitcount(x)
|
| 220 |
+
n = bc//2
|
| 221 |
+
r = int((x>>(2*n-100))**0.5+2)<<(n-50) # +2 is to round up
|
| 222 |
+
# The following iteration now precisely computes floor(sqrt(x))
|
| 223 |
+
# See e.g. Crandall & Pomerance, "Prime Numbers: A Computational
|
| 224 |
+
# Perspective"
|
| 225 |
+
while 1:
|
| 226 |
+
y = (r+x//r)>>1
|
| 227 |
+
if y >= r:
|
| 228 |
+
return r
|
| 229 |
+
r = y
|
| 230 |
+
|
| 231 |
+
def isqrt_fast_python(x):
|
| 232 |
+
"""
|
| 233 |
+
Fast approximate integer square root, computed using division-free
|
| 234 |
+
Newton iteration for large x. For random integers the result is almost
|
| 235 |
+
always correct (floor(sqrt(x))), but is 1 ulp too small with a roughly
|
| 236 |
+
0.1% probability. If x is very close to an exact square, the answer is
|
| 237 |
+
1 ulp wrong with high probability.
|
| 238 |
+
|
| 239 |
+
With 0 guard bits, the largest error over a set of 10^5 random
|
| 240 |
+
inputs of size 1-10^5 bits was 3 ulp. The use of 10 guard bits
|
| 241 |
+
almost certainly guarantees a max 1 ulp error.
|
| 242 |
+
"""
|
| 243 |
+
# Use direct division-based iteration if sqrt(x) < 2^400
|
| 244 |
+
# Assume floating-point square root accurate to within 1 ulp, then:
|
| 245 |
+
# 0 Newton iterations good to 52 bits
|
| 246 |
+
# 1 Newton iterations good to 104 bits
|
| 247 |
+
# 2 Newton iterations good to 208 bits
|
| 248 |
+
# 3 Newton iterations good to 416 bits
|
| 249 |
+
if x < _1_800:
|
| 250 |
+
y = int(x**0.5)
|
| 251 |
+
if x >= _1_100:
|
| 252 |
+
y = (y + x//y) >> 1
|
| 253 |
+
if x >= _1_200:
|
| 254 |
+
y = (y + x//y) >> 1
|
| 255 |
+
if x >= _1_400:
|
| 256 |
+
y = (y + x//y) >> 1
|
| 257 |
+
return y
|
| 258 |
+
bc = bitcount(x)
|
| 259 |
+
guard_bits = 10
|
| 260 |
+
x <<= 2*guard_bits
|
| 261 |
+
bc += 2*guard_bits
|
| 262 |
+
bc += (bc&1)
|
| 263 |
+
hbc = bc//2
|
| 264 |
+
startprec = min(50, hbc)
|
| 265 |
+
# Newton iteration for 1/sqrt(x), with floating-point starting value
|
| 266 |
+
r = int(2.0**(2*startprec) * (x >> (bc-2*startprec)) ** -0.5)
|
| 267 |
+
pp = startprec
|
| 268 |
+
for p in giant_steps(startprec, hbc):
|
| 269 |
+
# r**2, scaled from real size 2**(-bc) to 2**p
|
| 270 |
+
r2 = (r*r) >> (2*pp - p)
|
| 271 |
+
# x*r**2, scaled from real size ~1.0 to 2**p
|
| 272 |
+
xr2 = ((x >> (bc-p)) * r2) >> p
|
| 273 |
+
# New value of r, scaled from real size 2**(-bc/2) to 2**p
|
| 274 |
+
r = (r * ((3<<p) - xr2)) >> (pp+1)
|
| 275 |
+
pp = p
|
| 276 |
+
# (1/sqrt(x))*x = sqrt(x)
|
| 277 |
+
return (r*(x>>hbc)) >> (p+guard_bits)
|
| 278 |
+
|
| 279 |
+
def sqrtrem_python(x):
|
| 280 |
+
"""Correctly rounded integer (floor) square root with remainder."""
|
| 281 |
+
# to check cutoff:
|
| 282 |
+
# plot(lambda x: timing(isqrt, 2**int(x)), [0,2000])
|
| 283 |
+
if x < _1_600:
|
| 284 |
+
y = isqrt_small_python(x)
|
| 285 |
+
return y, x - y*y
|
| 286 |
+
y = isqrt_fast_python(x) + 1
|
| 287 |
+
rem = x - y*y
|
| 288 |
+
# Correct remainder
|
| 289 |
+
while rem < 0:
|
| 290 |
+
y -= 1
|
| 291 |
+
rem += (1+2*y)
|
| 292 |
+
else:
|
| 293 |
+
if rem:
|
| 294 |
+
while rem > 2*(1+y):
|
| 295 |
+
y += 1
|
| 296 |
+
rem -= (1+2*y)
|
| 297 |
+
return y, rem
|
| 298 |
+
|
| 299 |
+
def isqrt_python(x):
|
| 300 |
+
"""Integer square root with correct (floor) rounding."""
|
| 301 |
+
return sqrtrem_python(x)[0]
|
| 302 |
+
|
| 303 |
+
def sqrt_fixed(x, prec):
|
| 304 |
+
return isqrt_fast(x<<prec)
|
| 305 |
+
|
| 306 |
+
sqrt_fixed2 = sqrt_fixed
|
| 307 |
+
|
| 308 |
+
if BACKEND == 'gmpy':
|
| 309 |
+
if gmpy.version() >= '2':
|
| 310 |
+
isqrt_small = isqrt_fast = isqrt = gmpy.isqrt
|
| 311 |
+
sqrtrem = gmpy.isqrt_rem
|
| 312 |
+
else:
|
| 313 |
+
isqrt_small = isqrt_fast = isqrt = gmpy.sqrt
|
| 314 |
+
sqrtrem = gmpy.sqrtrem
|
| 315 |
+
elif BACKEND == 'sage':
|
| 316 |
+
isqrt_small = isqrt_fast = isqrt = \
|
| 317 |
+
getattr(sage_utils, "isqrt", lambda n: MPZ(n).isqrt())
|
| 318 |
+
sqrtrem = lambda n: MPZ(n).sqrtrem()
|
| 319 |
+
else:
|
| 320 |
+
isqrt_small = isqrt_small_python
|
| 321 |
+
isqrt_fast = isqrt_fast_python
|
| 322 |
+
isqrt = isqrt_python
|
| 323 |
+
sqrtrem = sqrtrem_python
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
def ifib(n, _cache={}):
|
| 327 |
+
"""Computes the nth Fibonacci number as an integer, for
|
| 328 |
+
integer n."""
|
| 329 |
+
if n < 0:
|
| 330 |
+
return (-1)**(-n+1) * ifib(-n)
|
| 331 |
+
if n in _cache:
|
| 332 |
+
return _cache[n]
|
| 333 |
+
m = n
|
| 334 |
+
# Use Dijkstra's logarithmic algorithm
|
| 335 |
+
# The following implementation is basically equivalent to
|
| 336 |
+
# http://en.literateprograms.org/Fibonacci_numbers_(Scheme)
|
| 337 |
+
a, b, p, q = MPZ_ONE, MPZ_ZERO, MPZ_ZERO, MPZ_ONE
|
| 338 |
+
while n:
|
| 339 |
+
if n & 1:
|
| 340 |
+
aq = a*q
|
| 341 |
+
a, b = b*q+aq+a*p, b*p+aq
|
| 342 |
+
n -= 1
|
| 343 |
+
else:
|
| 344 |
+
qq = q*q
|
| 345 |
+
p, q = p*p+qq, qq+2*p*q
|
| 346 |
+
n >>= 1
|
| 347 |
+
if m < 250:
|
| 348 |
+
_cache[m] = b
|
| 349 |
+
return b
|
| 350 |
+
|
| 351 |
+
MAX_FACTORIAL_CACHE = 1000
|
| 352 |
+
|
| 353 |
+
def ifac(n, memo={0:1, 1:1}):
|
| 354 |
+
"""Return n factorial (for integers n >= 0 only)."""
|
| 355 |
+
f = memo.get(n)
|
| 356 |
+
if f:
|
| 357 |
+
return f
|
| 358 |
+
k = len(memo)
|
| 359 |
+
p = memo[k-1]
|
| 360 |
+
MAX = MAX_FACTORIAL_CACHE
|
| 361 |
+
while k <= n:
|
| 362 |
+
p *= k
|
| 363 |
+
if k <= MAX:
|
| 364 |
+
memo[k] = p
|
| 365 |
+
k += 1
|
| 366 |
+
return p
|
| 367 |
+
|
| 368 |
+
def ifac2(n, memo_pair=[{0:1}, {1:1}]):
|
| 369 |
+
"""Return n!! (double factorial), integers n >= 0 only."""
|
| 370 |
+
memo = memo_pair[n&1]
|
| 371 |
+
f = memo.get(n)
|
| 372 |
+
if f:
|
| 373 |
+
return f
|
| 374 |
+
k = max(memo)
|
| 375 |
+
p = memo[k]
|
| 376 |
+
MAX = MAX_FACTORIAL_CACHE
|
| 377 |
+
while k < n:
|
| 378 |
+
k += 2
|
| 379 |
+
p *= k
|
| 380 |
+
if k <= MAX:
|
| 381 |
+
memo[k] = p
|
| 382 |
+
return p
|
| 383 |
+
|
| 384 |
+
if BACKEND == 'gmpy':
|
| 385 |
+
ifac = gmpy.fac
|
| 386 |
+
elif BACKEND == 'sage':
|
| 387 |
+
ifac = lambda n: int(sage.factorial(n))
|
| 388 |
+
ifib = sage.fibonacci
|
| 389 |
+
|
| 390 |
+
def list_primes(n):
|
| 391 |
+
n = n + 1
|
| 392 |
+
sieve = list(xrange(n))
|
| 393 |
+
sieve[:2] = [0, 0]
|
| 394 |
+
for i in xrange(2, int(n**0.5)+1):
|
| 395 |
+
if sieve[i]:
|
| 396 |
+
for j in xrange(i**2, n, i):
|
| 397 |
+
sieve[j] = 0
|
| 398 |
+
return [p for p in sieve if p]
|
| 399 |
+
|
| 400 |
+
if BACKEND == 'sage':
|
| 401 |
+
# Note: it is *VERY* important for performance that we convert
|
| 402 |
+
# the list to Python ints.
|
| 403 |
+
def list_primes(n):
|
| 404 |
+
return [int(_) for _ in sage.primes(n+1)]
|
| 405 |
+
|
| 406 |
+
small_odd_primes = (3,5,7,11,13,17,19,23,29,31,37,41,43,47)
|
| 407 |
+
small_odd_primes_set = set(small_odd_primes)
|
| 408 |
+
|
| 409 |
+
def isprime(n):
|
| 410 |
+
"""
|
| 411 |
+
Determines whether n is a prime number. A probabilistic test is
|
| 412 |
+
performed if n is very large. No special trick is used for detecting
|
| 413 |
+
perfect powers.
|
| 414 |
+
|
| 415 |
+
>>> sum(list_primes(100000))
|
| 416 |
+
454396537
|
| 417 |
+
>>> sum(n*isprime(n) for n in range(100000))
|
| 418 |
+
454396537
|
| 419 |
+
|
| 420 |
+
"""
|
| 421 |
+
n = int(n)
|
| 422 |
+
if not n & 1:
|
| 423 |
+
return n == 2
|
| 424 |
+
if n < 50:
|
| 425 |
+
return n in small_odd_primes_set
|
| 426 |
+
for p in small_odd_primes:
|
| 427 |
+
if not n % p:
|
| 428 |
+
return False
|
| 429 |
+
m = n-1
|
| 430 |
+
s = trailing(m)
|
| 431 |
+
d = m >> s
|
| 432 |
+
def test(a):
|
| 433 |
+
x = pow(a,d,n)
|
| 434 |
+
if x == 1 or x == m:
|
| 435 |
+
return True
|
| 436 |
+
for r in xrange(1,s):
|
| 437 |
+
x = x**2 % n
|
| 438 |
+
if x == m:
|
| 439 |
+
return True
|
| 440 |
+
return False
|
| 441 |
+
# See http://primes.utm.edu/prove/prove2_3.html
|
| 442 |
+
if n < 1373653:
|
| 443 |
+
witnesses = [2,3]
|
| 444 |
+
elif n < 341550071728321:
|
| 445 |
+
witnesses = [2,3,5,7,11,13,17]
|
| 446 |
+
else:
|
| 447 |
+
witnesses = small_odd_primes
|
| 448 |
+
for a in witnesses:
|
| 449 |
+
if not test(a):
|
| 450 |
+
return False
|
| 451 |
+
return True
|
| 452 |
+
|
| 453 |
+
def moebius(n):
|
| 454 |
+
"""
|
| 455 |
+
Evaluates the Moebius function which is `mu(n) = (-1)^k` if `n`
|
| 456 |
+
is a product of `k` distinct primes and `mu(n) = 0` otherwise.
|
| 457 |
+
|
| 458 |
+
TODO: speed up using factorization
|
| 459 |
+
"""
|
| 460 |
+
n = abs(int(n))
|
| 461 |
+
if n < 2:
|
| 462 |
+
return n
|
| 463 |
+
factors = []
|
| 464 |
+
for p in xrange(2, n+1):
|
| 465 |
+
if not (n % p):
|
| 466 |
+
if not (n % p**2):
|
| 467 |
+
return 0
|
| 468 |
+
if not sum(p % f for f in factors):
|
| 469 |
+
factors.append(p)
|
| 470 |
+
return (-1)**len(factors)
|
| 471 |
+
|
| 472 |
+
def gcd(*args):
|
| 473 |
+
a = 0
|
| 474 |
+
for b in args:
|
| 475 |
+
if a:
|
| 476 |
+
while b:
|
| 477 |
+
a, b = b, a % b
|
| 478 |
+
else:
|
| 479 |
+
a = b
|
| 480 |
+
return a
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
# Comment by Juan Arias de Reyna:
|
| 484 |
+
#
|
| 485 |
+
# I learn this method to compute EulerE[2n] from van de Lune.
|
| 486 |
+
#
|
| 487 |
+
# We apply the formula EulerE[2n] = (-1)^n 2**(-2n) sum_{j=0}^n a(2n,2j+1)
|
| 488 |
+
#
|
| 489 |
+
# where the numbers a(n,j) vanish for j > n+1 or j <= -1 and satisfies
|
| 490 |
+
#
|
| 491 |
+
# a(0,-1) = a(0,0) = 0; a(0,1)= 1; a(0,2) = a(0,3) = 0
|
| 492 |
+
#
|
| 493 |
+
# a(n,j) = a(n-1,j) when n+j is even
|
| 494 |
+
# a(n,j) = (j-1) a(n-1,j-1) + (j+1) a(n-1,j+1) when n+j is odd
|
| 495 |
+
#
|
| 496 |
+
#
|
| 497 |
+
# But we can use only one array unidimensional a(j) since to compute
|
| 498 |
+
# a(n,j) we only need to know a(n-1,k) where k and j are of different parity
|
| 499 |
+
# and we have not to conserve the used values.
|
| 500 |
+
#
|
| 501 |
+
# We cached up the values of Euler numbers to sufficiently high order.
|
| 502 |
+
#
|
| 503 |
+
# Important Observation: If we pretend to use the numbers
|
| 504 |
+
# EulerE[1], EulerE[2], ... , EulerE[n]
|
| 505 |
+
# it is convenient to compute first EulerE[n], since the algorithm
|
| 506 |
+
# computes first all
|
| 507 |
+
# the previous ones, and keeps them in the CACHE
|
| 508 |
+
|
| 509 |
+
MAX_EULER_CACHE = 500
|
| 510 |
+
|
| 511 |
+
def eulernum(m, _cache={0:MPZ_ONE}):
|
| 512 |
+
r"""
|
| 513 |
+
Computes the Euler numbers `E(n)`, which can be defined as
|
| 514 |
+
coefficients of the Taylor expansion of `1/cosh x`:
|
| 515 |
+
|
| 516 |
+
.. math ::
|
| 517 |
+
|
| 518 |
+
\frac{1}{\cosh x} = \sum_{n=0}^\infty \frac{E_n}{n!} x^n
|
| 519 |
+
|
| 520 |
+
Example::
|
| 521 |
+
|
| 522 |
+
>>> [int(eulernum(n)) for n in range(11)]
|
| 523 |
+
[1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521]
|
| 524 |
+
>>> [int(eulernum(n)) for n in range(11)] # test cache
|
| 525 |
+
[1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521]
|
| 526 |
+
|
| 527 |
+
"""
|
| 528 |
+
# for odd m > 1, the Euler numbers are zero
|
| 529 |
+
if m & 1:
|
| 530 |
+
return MPZ_ZERO
|
| 531 |
+
f = _cache.get(m)
|
| 532 |
+
if f:
|
| 533 |
+
return f
|
| 534 |
+
MAX = MAX_EULER_CACHE
|
| 535 |
+
n = m
|
| 536 |
+
a = [MPZ(_) for _ in [0,0,1,0,0,0]]
|
| 537 |
+
for n in range(1, m+1):
|
| 538 |
+
for j in range(n+1, -1, -2):
|
| 539 |
+
a[j+1] = (j-1)*a[j] + (j+1)*a[j+2]
|
| 540 |
+
a.append(0)
|
| 541 |
+
suma = 0
|
| 542 |
+
for k in range(n+1, -1, -2):
|
| 543 |
+
suma += a[k+1]
|
| 544 |
+
if n <= MAX:
|
| 545 |
+
_cache[n] = ((-1)**(n//2))*(suma // 2**n)
|
| 546 |
+
if n == m:
|
| 547 |
+
return ((-1)**(n//2))*suma // 2**n
|
| 548 |
+
|
| 549 |
+
def stirling1(n, k):
|
| 550 |
+
"""
|
| 551 |
+
Stirling number of the first kind.
|
| 552 |
+
"""
|
| 553 |
+
if n < 0 or k < 0:
|
| 554 |
+
raise ValueError
|
| 555 |
+
if k >= n:
|
| 556 |
+
return MPZ(n == k)
|
| 557 |
+
if k < 1:
|
| 558 |
+
return MPZ_ZERO
|
| 559 |
+
L = [MPZ_ZERO] * (k+1)
|
| 560 |
+
L[1] = MPZ_ONE
|
| 561 |
+
for m in xrange(2, n+1):
|
| 562 |
+
for j in xrange(min(k, m), 0, -1):
|
| 563 |
+
L[j] = (m-1) * L[j] + L[j-1]
|
| 564 |
+
return (-1)**(n+k) * L[k]
|
| 565 |
+
|
| 566 |
+
def stirling2(n, k):
|
| 567 |
+
"""
|
| 568 |
+
Stirling number of the second kind.
|
| 569 |
+
"""
|
| 570 |
+
if n < 0 or k < 0:
|
| 571 |
+
raise ValueError
|
| 572 |
+
if k >= n:
|
| 573 |
+
return MPZ(n == k)
|
| 574 |
+
if k <= 1:
|
| 575 |
+
return MPZ(k == 1)
|
| 576 |
+
s = MPZ_ZERO
|
| 577 |
+
t = MPZ_ONE
|
| 578 |
+
for j in xrange(k+1):
|
| 579 |
+
if (k + j) & 1:
|
| 580 |
+
s -= t * MPZ(j)**n
|
| 581 |
+
else:
|
| 582 |
+
s += t * MPZ(j)**n
|
| 583 |
+
t = t * (k - j) // (j + 1)
|
| 584 |
+
return s // ifac(k)
|
.venv/lib/python3.11/site-packages/mpmath/libmp/libmpc.py
ADDED
|
@@ -0,0 +1,835 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Low-level functions for complex arithmetic.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import sys
|
| 6 |
+
|
| 7 |
+
from .backend import MPZ, MPZ_ZERO, MPZ_ONE, MPZ_TWO, BACKEND
|
| 8 |
+
|
| 9 |
+
from .libmpf import (\
|
| 10 |
+
round_floor, round_ceiling, round_down, round_up,
|
| 11 |
+
round_nearest, round_fast, bitcount,
|
| 12 |
+
bctable, normalize, normalize1, reciprocal_rnd, rshift, lshift, giant_steps,
|
| 13 |
+
negative_rnd,
|
| 14 |
+
to_str, to_fixed, from_man_exp, from_float, to_float, from_int, to_int,
|
| 15 |
+
fzero, fone, ftwo, fhalf, finf, fninf, fnan, fnone,
|
| 16 |
+
mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul,
|
| 17 |
+
mpf_div, mpf_mul_int, mpf_shift, mpf_sqrt, mpf_hypot,
|
| 18 |
+
mpf_rdiv_int, mpf_floor, mpf_ceil, mpf_nint, mpf_frac,
|
| 19 |
+
mpf_sign, mpf_hash,
|
| 20 |
+
ComplexResult
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
from .libelefun import (\
|
| 24 |
+
mpf_pi, mpf_exp, mpf_log, mpf_cos_sin, mpf_cosh_sinh, mpf_tan, mpf_pow_int,
|
| 25 |
+
mpf_log_hypot,
|
| 26 |
+
mpf_cos_sin_pi, mpf_phi,
|
| 27 |
+
mpf_cos, mpf_sin, mpf_cos_pi, mpf_sin_pi,
|
| 28 |
+
mpf_atan, mpf_atan2, mpf_cosh, mpf_sinh, mpf_tanh,
|
| 29 |
+
mpf_asin, mpf_acos, mpf_acosh, mpf_nthroot, mpf_fibonacci
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
# An mpc value is a (real, imag) tuple
|
| 33 |
+
mpc_one = fone, fzero
|
| 34 |
+
mpc_zero = fzero, fzero
|
| 35 |
+
mpc_two = ftwo, fzero
|
| 36 |
+
mpc_half = (fhalf, fzero)
|
| 37 |
+
|
| 38 |
+
_infs = (finf, fninf)
|
| 39 |
+
_infs_nan = (finf, fninf, fnan)
|
| 40 |
+
|
| 41 |
+
def mpc_is_inf(z):
|
| 42 |
+
"""Check if either real or imaginary part is infinite"""
|
| 43 |
+
re, im = z
|
| 44 |
+
if re in _infs: return True
|
| 45 |
+
if im in _infs: return True
|
| 46 |
+
return False
|
| 47 |
+
|
| 48 |
+
def mpc_is_infnan(z):
|
| 49 |
+
"""Check if either real or imaginary part is infinite or nan"""
|
| 50 |
+
re, im = z
|
| 51 |
+
if re in _infs_nan: return True
|
| 52 |
+
if im in _infs_nan: return True
|
| 53 |
+
return False
|
| 54 |
+
|
| 55 |
+
def mpc_to_str(z, dps, **kwargs):
|
| 56 |
+
re, im = z
|
| 57 |
+
rs = to_str(re, dps)
|
| 58 |
+
if im[0]:
|
| 59 |
+
return rs + " - " + to_str(mpf_neg(im), dps, **kwargs) + "j"
|
| 60 |
+
else:
|
| 61 |
+
return rs + " + " + to_str(im, dps, **kwargs) + "j"
|
| 62 |
+
|
| 63 |
+
def mpc_to_complex(z, strict=False, rnd=round_fast):
|
| 64 |
+
re, im = z
|
| 65 |
+
return complex(to_float(re, strict, rnd), to_float(im, strict, rnd))
|
| 66 |
+
|
| 67 |
+
def mpc_hash(z):
|
| 68 |
+
if sys.version_info >= (3, 2):
|
| 69 |
+
re, im = z
|
| 70 |
+
h = mpf_hash(re) + sys.hash_info.imag * mpf_hash(im)
|
| 71 |
+
# Need to reduce either module 2^32 or 2^64
|
| 72 |
+
h = h % (2**sys.hash_info.width)
|
| 73 |
+
return int(h)
|
| 74 |
+
else:
|
| 75 |
+
try:
|
| 76 |
+
return hash(mpc_to_complex(z, strict=True))
|
| 77 |
+
except OverflowError:
|
| 78 |
+
return hash(z)
|
| 79 |
+
|
| 80 |
+
def mpc_conjugate(z, prec, rnd=round_fast):
|
| 81 |
+
re, im = z
|
| 82 |
+
return re, mpf_neg(im, prec, rnd)
|
| 83 |
+
|
| 84 |
+
def mpc_is_nonzero(z):
|
| 85 |
+
return z != mpc_zero
|
| 86 |
+
|
| 87 |
+
def mpc_add(z, w, prec, rnd=round_fast):
|
| 88 |
+
a, b = z
|
| 89 |
+
c, d = w
|
| 90 |
+
return mpf_add(a, c, prec, rnd), mpf_add(b, d, prec, rnd)
|
| 91 |
+
|
| 92 |
+
def mpc_add_mpf(z, x, prec, rnd=round_fast):
|
| 93 |
+
a, b = z
|
| 94 |
+
return mpf_add(a, x, prec, rnd), b
|
| 95 |
+
|
| 96 |
+
def mpc_sub(z, w, prec=0, rnd=round_fast):
|
| 97 |
+
a, b = z
|
| 98 |
+
c, d = w
|
| 99 |
+
return mpf_sub(a, c, prec, rnd), mpf_sub(b, d, prec, rnd)
|
| 100 |
+
|
| 101 |
+
def mpc_sub_mpf(z, p, prec=0, rnd=round_fast):
|
| 102 |
+
a, b = z
|
| 103 |
+
return mpf_sub(a, p, prec, rnd), b
|
| 104 |
+
|
| 105 |
+
def mpc_pos(z, prec, rnd=round_fast):
|
| 106 |
+
a, b = z
|
| 107 |
+
return mpf_pos(a, prec, rnd), mpf_pos(b, prec, rnd)
|
| 108 |
+
|
| 109 |
+
def mpc_neg(z, prec=None, rnd=round_fast):
|
| 110 |
+
a, b = z
|
| 111 |
+
return mpf_neg(a, prec, rnd), mpf_neg(b, prec, rnd)
|
| 112 |
+
|
| 113 |
+
def mpc_shift(z, n):
|
| 114 |
+
a, b = z
|
| 115 |
+
return mpf_shift(a, n), mpf_shift(b, n)
|
| 116 |
+
|
| 117 |
+
def mpc_abs(z, prec, rnd=round_fast):
|
| 118 |
+
"""Absolute value of a complex number, |a+bi|.
|
| 119 |
+
Returns an mpf value."""
|
| 120 |
+
a, b = z
|
| 121 |
+
return mpf_hypot(a, b, prec, rnd)
|
| 122 |
+
|
| 123 |
+
def mpc_arg(z, prec, rnd=round_fast):
|
| 124 |
+
"""Argument of a complex number. Returns an mpf value."""
|
| 125 |
+
a, b = z
|
| 126 |
+
return mpf_atan2(b, a, prec, rnd)
|
| 127 |
+
|
| 128 |
+
def mpc_floor(z, prec, rnd=round_fast):
|
| 129 |
+
a, b = z
|
| 130 |
+
return mpf_floor(a, prec, rnd), mpf_floor(b, prec, rnd)
|
| 131 |
+
|
| 132 |
+
def mpc_ceil(z, prec, rnd=round_fast):
|
| 133 |
+
a, b = z
|
| 134 |
+
return mpf_ceil(a, prec, rnd), mpf_ceil(b, prec, rnd)
|
| 135 |
+
|
| 136 |
+
def mpc_nint(z, prec, rnd=round_fast):
|
| 137 |
+
a, b = z
|
| 138 |
+
return mpf_nint(a, prec, rnd), mpf_nint(b, prec, rnd)
|
| 139 |
+
|
| 140 |
+
def mpc_frac(z, prec, rnd=round_fast):
|
| 141 |
+
a, b = z
|
| 142 |
+
return mpf_frac(a, prec, rnd), mpf_frac(b, prec, rnd)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def mpc_mul(z, w, prec, rnd=round_fast):
|
| 146 |
+
"""
|
| 147 |
+
Complex multiplication.
|
| 148 |
+
|
| 149 |
+
Returns the real and imaginary part of (a+bi)*(c+di), rounded to
|
| 150 |
+
the specified precision. The rounding mode applies to the real and
|
| 151 |
+
imaginary parts separately.
|
| 152 |
+
"""
|
| 153 |
+
a, b = z
|
| 154 |
+
c, d = w
|
| 155 |
+
p = mpf_mul(a, c)
|
| 156 |
+
q = mpf_mul(b, d)
|
| 157 |
+
r = mpf_mul(a, d)
|
| 158 |
+
s = mpf_mul(b, c)
|
| 159 |
+
re = mpf_sub(p, q, prec, rnd)
|
| 160 |
+
im = mpf_add(r, s, prec, rnd)
|
| 161 |
+
return re, im
|
| 162 |
+
|
| 163 |
+
def mpc_square(z, prec, rnd=round_fast):
|
| 164 |
+
# (a+b*I)**2 == a**2 - b**2 + 2*I*a*b
|
| 165 |
+
a, b = z
|
| 166 |
+
p = mpf_mul(a,a)
|
| 167 |
+
q = mpf_mul(b,b)
|
| 168 |
+
r = mpf_mul(a,b, prec, rnd)
|
| 169 |
+
re = mpf_sub(p, q, prec, rnd)
|
| 170 |
+
im = mpf_shift(r, 1)
|
| 171 |
+
return re, im
|
| 172 |
+
|
| 173 |
+
def mpc_mul_mpf(z, p, prec, rnd=round_fast):
|
| 174 |
+
a, b = z
|
| 175 |
+
re = mpf_mul(a, p, prec, rnd)
|
| 176 |
+
im = mpf_mul(b, p, prec, rnd)
|
| 177 |
+
return re, im
|
| 178 |
+
|
| 179 |
+
def mpc_mul_imag_mpf(z, x, prec, rnd=round_fast):
|
| 180 |
+
"""
|
| 181 |
+
Multiply the mpc value z by I*x where x is an mpf value.
|
| 182 |
+
"""
|
| 183 |
+
a, b = z
|
| 184 |
+
re = mpf_neg(mpf_mul(b, x, prec, rnd))
|
| 185 |
+
im = mpf_mul(a, x, prec, rnd)
|
| 186 |
+
return re, im
|
| 187 |
+
|
| 188 |
+
def mpc_mul_int(z, n, prec, rnd=round_fast):
|
| 189 |
+
a, b = z
|
| 190 |
+
re = mpf_mul_int(a, n, prec, rnd)
|
| 191 |
+
im = mpf_mul_int(b, n, prec, rnd)
|
| 192 |
+
return re, im
|
| 193 |
+
|
| 194 |
+
def mpc_div(z, w, prec, rnd=round_fast):
|
| 195 |
+
a, b = z
|
| 196 |
+
c, d = w
|
| 197 |
+
wp = prec + 10
|
| 198 |
+
# mag = c*c + d*d
|
| 199 |
+
mag = mpf_add(mpf_mul(c, c), mpf_mul(d, d), wp)
|
| 200 |
+
# (a*c+b*d)/mag, (b*c-a*d)/mag
|
| 201 |
+
t = mpf_add(mpf_mul(a,c), mpf_mul(b,d), wp)
|
| 202 |
+
u = mpf_sub(mpf_mul(b,c), mpf_mul(a,d), wp)
|
| 203 |
+
return mpf_div(t,mag,prec,rnd), mpf_div(u,mag,prec,rnd)
|
| 204 |
+
|
| 205 |
+
def mpc_div_mpf(z, p, prec, rnd=round_fast):
|
| 206 |
+
"""Calculate z/p where p is real"""
|
| 207 |
+
a, b = z
|
| 208 |
+
re = mpf_div(a, p, prec, rnd)
|
| 209 |
+
im = mpf_div(b, p, prec, rnd)
|
| 210 |
+
return re, im
|
| 211 |
+
|
| 212 |
+
def mpc_reciprocal(z, prec, rnd=round_fast):
|
| 213 |
+
"""Calculate 1/z efficiently"""
|
| 214 |
+
a, b = z
|
| 215 |
+
m = mpf_add(mpf_mul(a,a),mpf_mul(b,b),prec+10)
|
| 216 |
+
re = mpf_div(a, m, prec, rnd)
|
| 217 |
+
im = mpf_neg(mpf_div(b, m, prec, rnd))
|
| 218 |
+
return re, im
|
| 219 |
+
|
| 220 |
+
def mpc_mpf_div(p, z, prec, rnd=round_fast):
|
| 221 |
+
"""Calculate p/z where p is real efficiently"""
|
| 222 |
+
a, b = z
|
| 223 |
+
m = mpf_add(mpf_mul(a,a),mpf_mul(b,b), prec+10)
|
| 224 |
+
re = mpf_div(mpf_mul(a,p), m, prec, rnd)
|
| 225 |
+
im = mpf_div(mpf_neg(mpf_mul(b,p)), m, prec, rnd)
|
| 226 |
+
return re, im
|
| 227 |
+
|
| 228 |
+
def complex_int_pow(a, b, n):
|
| 229 |
+
"""Complex integer power: computes (a+b*I)**n exactly for
|
| 230 |
+
nonnegative n (a and b must be Python ints)."""
|
| 231 |
+
wre = 1
|
| 232 |
+
wim = 0
|
| 233 |
+
while n:
|
| 234 |
+
if n & 1:
|
| 235 |
+
wre, wim = wre*a - wim*b, wim*a + wre*b
|
| 236 |
+
n -= 1
|
| 237 |
+
a, b = a*a - b*b, 2*a*b
|
| 238 |
+
n //= 2
|
| 239 |
+
return wre, wim
|
| 240 |
+
|
| 241 |
+
def mpc_pow(z, w, prec, rnd=round_fast):
|
| 242 |
+
if w[1] == fzero:
|
| 243 |
+
return mpc_pow_mpf(z, w[0], prec, rnd)
|
| 244 |
+
return mpc_exp(mpc_mul(mpc_log(z, prec+10), w, prec+10), prec, rnd)
|
| 245 |
+
|
| 246 |
+
def mpc_pow_mpf(z, p, prec, rnd=round_fast):
|
| 247 |
+
psign, pman, pexp, pbc = p
|
| 248 |
+
if pexp >= 0:
|
| 249 |
+
return mpc_pow_int(z, (-1)**psign * (pman<<pexp), prec, rnd)
|
| 250 |
+
if pexp == -1:
|
| 251 |
+
sqrtz = mpc_sqrt(z, prec+10)
|
| 252 |
+
return mpc_pow_int(sqrtz, (-1)**psign * pman, prec, rnd)
|
| 253 |
+
return mpc_exp(mpc_mul_mpf(mpc_log(z, prec+10), p, prec+10), prec, rnd)
|
| 254 |
+
|
| 255 |
+
def mpc_pow_int(z, n, prec, rnd=round_fast):
|
| 256 |
+
a, b = z
|
| 257 |
+
if b == fzero:
|
| 258 |
+
return mpf_pow_int(a, n, prec, rnd), fzero
|
| 259 |
+
if a == fzero:
|
| 260 |
+
v = mpf_pow_int(b, n, prec, rnd)
|
| 261 |
+
n %= 4
|
| 262 |
+
if n == 0:
|
| 263 |
+
return v, fzero
|
| 264 |
+
elif n == 1:
|
| 265 |
+
return fzero, v
|
| 266 |
+
elif n == 2:
|
| 267 |
+
return mpf_neg(v), fzero
|
| 268 |
+
elif n == 3:
|
| 269 |
+
return fzero, mpf_neg(v)
|
| 270 |
+
if n == 0: return mpc_one
|
| 271 |
+
if n == 1: return mpc_pos(z, prec, rnd)
|
| 272 |
+
if n == 2: return mpc_square(z, prec, rnd)
|
| 273 |
+
if n == -1: return mpc_reciprocal(z, prec, rnd)
|
| 274 |
+
if n < 0: return mpc_reciprocal(mpc_pow_int(z, -n, prec+4), prec, rnd)
|
| 275 |
+
asign, aman, aexp, abc = a
|
| 276 |
+
bsign, bman, bexp, bbc = b
|
| 277 |
+
if asign: aman = -aman
|
| 278 |
+
if bsign: bman = -bman
|
| 279 |
+
de = aexp - bexp
|
| 280 |
+
abs_de = abs(de)
|
| 281 |
+
exact_size = n*(abs_de + max(abc, bbc))
|
| 282 |
+
if exact_size < 10000:
|
| 283 |
+
if de > 0:
|
| 284 |
+
aman <<= de
|
| 285 |
+
aexp = bexp
|
| 286 |
+
else:
|
| 287 |
+
bman <<= (-de)
|
| 288 |
+
bexp = aexp
|
| 289 |
+
re, im = complex_int_pow(aman, bman, n)
|
| 290 |
+
re = from_man_exp(re, int(n*aexp), prec, rnd)
|
| 291 |
+
im = from_man_exp(im, int(n*bexp), prec, rnd)
|
| 292 |
+
return re, im
|
| 293 |
+
return mpc_exp(mpc_mul_int(mpc_log(z, prec+10), n, prec+10), prec, rnd)
|
| 294 |
+
|
| 295 |
+
def mpc_sqrt(z, prec, rnd=round_fast):
|
| 296 |
+
"""Complex square root (principal branch).
|
| 297 |
+
|
| 298 |
+
We have sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i where
|
| 299 |
+
r = abs(a+bi), when a+bi is not a negative real number."""
|
| 300 |
+
a, b = z
|
| 301 |
+
if b == fzero:
|
| 302 |
+
if a == fzero:
|
| 303 |
+
return (a, b)
|
| 304 |
+
# When a+bi is a negative real number, we get a real sqrt times i
|
| 305 |
+
if a[0]:
|
| 306 |
+
im = mpf_sqrt(mpf_neg(a), prec, rnd)
|
| 307 |
+
return (fzero, im)
|
| 308 |
+
else:
|
| 309 |
+
re = mpf_sqrt(a, prec, rnd)
|
| 310 |
+
return (re, fzero)
|
| 311 |
+
wp = prec+20
|
| 312 |
+
if not a[0]: # case a positive
|
| 313 |
+
t = mpf_add(mpc_abs((a, b), wp), a, wp) # t = abs(a+bi) + a
|
| 314 |
+
u = mpf_shift(t, -1) # u = t/2
|
| 315 |
+
re = mpf_sqrt(u, prec, rnd) # re = sqrt(u)
|
| 316 |
+
v = mpf_shift(t, 1) # v = 2*t
|
| 317 |
+
w = mpf_sqrt(v, wp) # w = sqrt(v)
|
| 318 |
+
im = mpf_div(b, w, prec, rnd) # im = b / w
|
| 319 |
+
else: # case a negative
|
| 320 |
+
t = mpf_sub(mpc_abs((a, b), wp), a, wp) # t = abs(a+bi) - a
|
| 321 |
+
u = mpf_shift(t, -1) # u = t/2
|
| 322 |
+
im = mpf_sqrt(u, prec, rnd) # im = sqrt(u)
|
| 323 |
+
v = mpf_shift(t, 1) # v = 2*t
|
| 324 |
+
w = mpf_sqrt(v, wp) # w = sqrt(v)
|
| 325 |
+
re = mpf_div(b, w, prec, rnd) # re = b/w
|
| 326 |
+
if b[0]:
|
| 327 |
+
re = mpf_neg(re)
|
| 328 |
+
im = mpf_neg(im)
|
| 329 |
+
return re, im
|
| 330 |
+
|
| 331 |
+
def mpc_nthroot_fixed(a, b, n, prec):
|
| 332 |
+
# a, b signed integers at fixed precision prec
|
| 333 |
+
start = 50
|
| 334 |
+
a1 = int(rshift(a, prec - n*start))
|
| 335 |
+
b1 = int(rshift(b, prec - n*start))
|
| 336 |
+
try:
|
| 337 |
+
r = (a1 + 1j * b1)**(1.0/n)
|
| 338 |
+
re = r.real
|
| 339 |
+
im = r.imag
|
| 340 |
+
re = MPZ(int(re))
|
| 341 |
+
im = MPZ(int(im))
|
| 342 |
+
except OverflowError:
|
| 343 |
+
a1 = from_int(a1, start)
|
| 344 |
+
b1 = from_int(b1, start)
|
| 345 |
+
fn = from_int(n)
|
| 346 |
+
nth = mpf_rdiv_int(1, fn, start)
|
| 347 |
+
re, im = mpc_pow((a1, b1), (nth, fzero), start)
|
| 348 |
+
re = to_int(re)
|
| 349 |
+
im = to_int(im)
|
| 350 |
+
extra = 10
|
| 351 |
+
prevp = start
|
| 352 |
+
extra1 = n
|
| 353 |
+
for p in giant_steps(start, prec+extra):
|
| 354 |
+
# this is slow for large n, unlike int_pow_fixed
|
| 355 |
+
re2, im2 = complex_int_pow(re, im, n-1)
|
| 356 |
+
re2 = rshift(re2, (n-1)*prevp - p - extra1)
|
| 357 |
+
im2 = rshift(im2, (n-1)*prevp - p - extra1)
|
| 358 |
+
r4 = (re2*re2 + im2*im2) >> (p + extra1)
|
| 359 |
+
ap = rshift(a, prec - p)
|
| 360 |
+
bp = rshift(b, prec - p)
|
| 361 |
+
rec = (ap * re2 + bp * im2) >> p
|
| 362 |
+
imc = (-ap * im2 + bp * re2) >> p
|
| 363 |
+
reb = (rec << p) // r4
|
| 364 |
+
imb = (imc << p) // r4
|
| 365 |
+
re = (reb + (n-1)*lshift(re, p-prevp))//n
|
| 366 |
+
im = (imb + (n-1)*lshift(im, p-prevp))//n
|
| 367 |
+
prevp = p
|
| 368 |
+
return re, im
|
| 369 |
+
|
| 370 |
+
def mpc_nthroot(z, n, prec, rnd=round_fast):
|
| 371 |
+
"""
|
| 372 |
+
Complex n-th root.
|
| 373 |
+
|
| 374 |
+
Use Newton method as in the real case when it is faster,
|
| 375 |
+
otherwise use z**(1/n)
|
| 376 |
+
"""
|
| 377 |
+
a, b = z
|
| 378 |
+
if a[0] == 0 and b == fzero:
|
| 379 |
+
re = mpf_nthroot(a, n, prec, rnd)
|
| 380 |
+
return (re, fzero)
|
| 381 |
+
if n < 2:
|
| 382 |
+
if n == 0:
|
| 383 |
+
return mpc_one
|
| 384 |
+
if n == 1:
|
| 385 |
+
return mpc_pos((a, b), prec, rnd)
|
| 386 |
+
if n == -1:
|
| 387 |
+
return mpc_div(mpc_one, (a, b), prec, rnd)
|
| 388 |
+
inverse = mpc_nthroot((a, b), -n, prec+5, reciprocal_rnd[rnd])
|
| 389 |
+
return mpc_div(mpc_one, inverse, prec, rnd)
|
| 390 |
+
if n <= 20:
|
| 391 |
+
prec2 = int(1.2 * (prec + 10))
|
| 392 |
+
asign, aman, aexp, abc = a
|
| 393 |
+
bsign, bman, bexp, bbc = b
|
| 394 |
+
pf = mpc_abs((a,b), prec)
|
| 395 |
+
if pf[-2] + pf[-1] > -10 and pf[-2] + pf[-1] < prec:
|
| 396 |
+
af = to_fixed(a, prec2)
|
| 397 |
+
bf = to_fixed(b, prec2)
|
| 398 |
+
re, im = mpc_nthroot_fixed(af, bf, n, prec2)
|
| 399 |
+
extra = 10
|
| 400 |
+
re = from_man_exp(re, -prec2-extra, prec2, rnd)
|
| 401 |
+
im = from_man_exp(im, -prec2-extra, prec2, rnd)
|
| 402 |
+
return re, im
|
| 403 |
+
fn = from_int(n)
|
| 404 |
+
prec2 = prec+10 + 10
|
| 405 |
+
nth = mpf_rdiv_int(1, fn, prec2)
|
| 406 |
+
re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd)
|
| 407 |
+
re = normalize(re[0], re[1], re[2], re[3], prec, rnd)
|
| 408 |
+
im = normalize(im[0], im[1], im[2], im[3], prec, rnd)
|
| 409 |
+
return re, im
|
| 410 |
+
|
| 411 |
+
def mpc_cbrt(z, prec, rnd=round_fast):
|
| 412 |
+
"""
|
| 413 |
+
Complex cubic root.
|
| 414 |
+
"""
|
| 415 |
+
return mpc_nthroot(z, 3, prec, rnd)
|
| 416 |
+
|
| 417 |
+
def mpc_exp(z, prec, rnd=round_fast):
|
| 418 |
+
"""
|
| 419 |
+
Complex exponential function.
|
| 420 |
+
|
| 421 |
+
We use the direct formula exp(a+bi) = exp(a) * (cos(b) + sin(b)*i)
|
| 422 |
+
for the computation. This formula is very nice because it is
|
| 423 |
+
pefectly stable; since we just do real multiplications, the only
|
| 424 |
+
numerical errors that can creep in are single-ulp rounding errors.
|
| 425 |
+
|
| 426 |
+
The formula is efficient since mpmath's real exp is quite fast and
|
| 427 |
+
since we can compute cos and sin simultaneously.
|
| 428 |
+
|
| 429 |
+
It is no problem if a and b are large; if the implementations of
|
| 430 |
+
exp/cos/sin are accurate and efficient for all real numbers, then
|
| 431 |
+
so is this function for all complex numbers.
|
| 432 |
+
"""
|
| 433 |
+
a, b = z
|
| 434 |
+
if a == fzero:
|
| 435 |
+
return mpf_cos_sin(b, prec, rnd)
|
| 436 |
+
if b == fzero:
|
| 437 |
+
return mpf_exp(a, prec, rnd), fzero
|
| 438 |
+
mag = mpf_exp(a, prec+4, rnd)
|
| 439 |
+
c, s = mpf_cos_sin(b, prec+4, rnd)
|
| 440 |
+
re = mpf_mul(mag, c, prec, rnd)
|
| 441 |
+
im = mpf_mul(mag, s, prec, rnd)
|
| 442 |
+
return re, im
|
| 443 |
+
|
| 444 |
+
def mpc_log(z, prec, rnd=round_fast):
|
| 445 |
+
re = mpf_log_hypot(z[0], z[1], prec, rnd)
|
| 446 |
+
im = mpc_arg(z, prec, rnd)
|
| 447 |
+
return re, im
|
| 448 |
+
|
| 449 |
+
def mpc_cos(z, prec, rnd=round_fast):
|
| 450 |
+
"""Complex cosine. The formula used is cos(a+bi) = cos(a)*cosh(b) -
|
| 451 |
+
sin(a)*sinh(b)*i.
|
| 452 |
+
|
| 453 |
+
The same comments apply as for the complex exp: only real
|
| 454 |
+
multiplications are pewrormed, so no cancellation errors are
|
| 455 |
+
possible. The formula is also efficient since we can compute both
|
| 456 |
+
pairs (cos, sin) and (cosh, sinh) in single stwps."""
|
| 457 |
+
a, b = z
|
| 458 |
+
if b == fzero:
|
| 459 |
+
return mpf_cos(a, prec, rnd), fzero
|
| 460 |
+
if a == fzero:
|
| 461 |
+
return mpf_cosh(b, prec, rnd), fzero
|
| 462 |
+
wp = prec + 6
|
| 463 |
+
c, s = mpf_cos_sin(a, wp)
|
| 464 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 465 |
+
re = mpf_mul(c, ch, prec, rnd)
|
| 466 |
+
im = mpf_mul(s, sh, prec, rnd)
|
| 467 |
+
return re, mpf_neg(im)
|
| 468 |
+
|
| 469 |
+
def mpc_sin(z, prec, rnd=round_fast):
|
| 470 |
+
"""Complex sine. We have sin(a+bi) = sin(a)*cosh(b) +
|
| 471 |
+
cos(a)*sinh(b)*i. See the docstring for mpc_cos for additional
|
| 472 |
+
comments."""
|
| 473 |
+
a, b = z
|
| 474 |
+
if b == fzero:
|
| 475 |
+
return mpf_sin(a, prec, rnd), fzero
|
| 476 |
+
if a == fzero:
|
| 477 |
+
return fzero, mpf_sinh(b, prec, rnd)
|
| 478 |
+
wp = prec + 6
|
| 479 |
+
c, s = mpf_cos_sin(a, wp)
|
| 480 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 481 |
+
re = mpf_mul(s, ch, prec, rnd)
|
| 482 |
+
im = mpf_mul(c, sh, prec, rnd)
|
| 483 |
+
return re, im
|
| 484 |
+
|
| 485 |
+
def mpc_tan(z, prec, rnd=round_fast):
|
| 486 |
+
"""Complex tangent. Computed as tan(a+bi) = sin(2a)/M + sinh(2b)/M*i
|
| 487 |
+
where M = cos(2a) + cosh(2b)."""
|
| 488 |
+
a, b = z
|
| 489 |
+
asign, aman, aexp, abc = a
|
| 490 |
+
bsign, bman, bexp, bbc = b
|
| 491 |
+
if b == fzero: return mpf_tan(a, prec, rnd), fzero
|
| 492 |
+
if a == fzero: return fzero, mpf_tanh(b, prec, rnd)
|
| 493 |
+
wp = prec + 15
|
| 494 |
+
a = mpf_shift(a, 1)
|
| 495 |
+
b = mpf_shift(b, 1)
|
| 496 |
+
c, s = mpf_cos_sin(a, wp)
|
| 497 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 498 |
+
# TODO: handle cancellation when c ~= -1 and ch ~= 1
|
| 499 |
+
mag = mpf_add(c, ch, wp)
|
| 500 |
+
re = mpf_div(s, mag, prec, rnd)
|
| 501 |
+
im = mpf_div(sh, mag, prec, rnd)
|
| 502 |
+
return re, im
|
| 503 |
+
|
| 504 |
+
def mpc_cos_pi(z, prec, rnd=round_fast):
|
| 505 |
+
a, b = z
|
| 506 |
+
if b == fzero:
|
| 507 |
+
return mpf_cos_pi(a, prec, rnd), fzero
|
| 508 |
+
b = mpf_mul(b, mpf_pi(prec+5), prec+5)
|
| 509 |
+
if a == fzero:
|
| 510 |
+
return mpf_cosh(b, prec, rnd), fzero
|
| 511 |
+
wp = prec + 6
|
| 512 |
+
c, s = mpf_cos_sin_pi(a, wp)
|
| 513 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 514 |
+
re = mpf_mul(c, ch, prec, rnd)
|
| 515 |
+
im = mpf_mul(s, sh, prec, rnd)
|
| 516 |
+
return re, mpf_neg(im)
|
| 517 |
+
|
| 518 |
+
def mpc_sin_pi(z, prec, rnd=round_fast):
|
| 519 |
+
a, b = z
|
| 520 |
+
if b == fzero:
|
| 521 |
+
return mpf_sin_pi(a, prec, rnd), fzero
|
| 522 |
+
b = mpf_mul(b, mpf_pi(prec+5), prec+5)
|
| 523 |
+
if a == fzero:
|
| 524 |
+
return fzero, mpf_sinh(b, prec, rnd)
|
| 525 |
+
wp = prec + 6
|
| 526 |
+
c, s = mpf_cos_sin_pi(a, wp)
|
| 527 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 528 |
+
re = mpf_mul(s, ch, prec, rnd)
|
| 529 |
+
im = mpf_mul(c, sh, prec, rnd)
|
| 530 |
+
return re, im
|
| 531 |
+
|
| 532 |
+
def mpc_cos_sin(z, prec, rnd=round_fast):
|
| 533 |
+
a, b = z
|
| 534 |
+
if a == fzero:
|
| 535 |
+
ch, sh = mpf_cosh_sinh(b, prec, rnd)
|
| 536 |
+
return (ch, fzero), (fzero, sh)
|
| 537 |
+
if b == fzero:
|
| 538 |
+
c, s = mpf_cos_sin(a, prec, rnd)
|
| 539 |
+
return (c, fzero), (s, fzero)
|
| 540 |
+
wp = prec + 6
|
| 541 |
+
c, s = mpf_cos_sin(a, wp)
|
| 542 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 543 |
+
cre = mpf_mul(c, ch, prec, rnd)
|
| 544 |
+
cim = mpf_mul(s, sh, prec, rnd)
|
| 545 |
+
sre = mpf_mul(s, ch, prec, rnd)
|
| 546 |
+
sim = mpf_mul(c, sh, prec, rnd)
|
| 547 |
+
return (cre, mpf_neg(cim)), (sre, sim)
|
| 548 |
+
|
| 549 |
+
def mpc_cos_sin_pi(z, prec, rnd=round_fast):
|
| 550 |
+
a, b = z
|
| 551 |
+
if b == fzero:
|
| 552 |
+
c, s = mpf_cos_sin_pi(a, prec, rnd)
|
| 553 |
+
return (c, fzero), (s, fzero)
|
| 554 |
+
b = mpf_mul(b, mpf_pi(prec+5), prec+5)
|
| 555 |
+
if a == fzero:
|
| 556 |
+
ch, sh = mpf_cosh_sinh(b, prec, rnd)
|
| 557 |
+
return (ch, fzero), (fzero, sh)
|
| 558 |
+
wp = prec + 6
|
| 559 |
+
c, s = mpf_cos_sin_pi(a, wp)
|
| 560 |
+
ch, sh = mpf_cosh_sinh(b, wp)
|
| 561 |
+
cre = mpf_mul(c, ch, prec, rnd)
|
| 562 |
+
cim = mpf_mul(s, sh, prec, rnd)
|
| 563 |
+
sre = mpf_mul(s, ch, prec, rnd)
|
| 564 |
+
sim = mpf_mul(c, sh, prec, rnd)
|
| 565 |
+
return (cre, mpf_neg(cim)), (sre, sim)
|
| 566 |
+
|
| 567 |
+
def mpc_cosh(z, prec, rnd=round_fast):
|
| 568 |
+
"""Complex hyperbolic cosine. Computed as cosh(z) = cos(z*i)."""
|
| 569 |
+
a, b = z
|
| 570 |
+
return mpc_cos((b, mpf_neg(a)), prec, rnd)
|
| 571 |
+
|
| 572 |
+
def mpc_sinh(z, prec, rnd=round_fast):
|
| 573 |
+
"""Complex hyperbolic sine. Computed as sinh(z) = -i*sin(z*i)."""
|
| 574 |
+
a, b = z
|
| 575 |
+
b, a = mpc_sin((b, a), prec, rnd)
|
| 576 |
+
return a, b
|
| 577 |
+
|
| 578 |
+
def mpc_tanh(z, prec, rnd=round_fast):
|
| 579 |
+
"""Complex hyperbolic tangent. Computed as tanh(z) = -i*tan(z*i)."""
|
| 580 |
+
a, b = z
|
| 581 |
+
b, a = mpc_tan((b, a), prec, rnd)
|
| 582 |
+
return a, b
|
| 583 |
+
|
| 584 |
+
# TODO: avoid loss of accuracy
|
| 585 |
+
def mpc_atan(z, prec, rnd=round_fast):
|
| 586 |
+
a, b = z
|
| 587 |
+
# atan(z) = (I/2)*(log(1-I*z) - log(1+I*z))
|
| 588 |
+
# x = 1-I*z = 1 + b - I*a
|
| 589 |
+
# y = 1+I*z = 1 - b + I*a
|
| 590 |
+
wp = prec + 15
|
| 591 |
+
x = mpf_add(fone, b, wp), mpf_neg(a)
|
| 592 |
+
y = mpf_sub(fone, b, wp), a
|
| 593 |
+
l1 = mpc_log(x, wp)
|
| 594 |
+
l2 = mpc_log(y, wp)
|
| 595 |
+
a, b = mpc_sub(l1, l2, prec, rnd)
|
| 596 |
+
# (I/2) * (a+b*I) = (-b/2 + a/2*I)
|
| 597 |
+
v = mpf_neg(mpf_shift(b,-1)), mpf_shift(a,-1)
|
| 598 |
+
# Subtraction at infinity gives correct real part but
|
| 599 |
+
# wrong imaginary part (should be zero)
|
| 600 |
+
if v[1] == fnan and mpc_is_inf(z):
|
| 601 |
+
v = (v[0], fzero)
|
| 602 |
+
return v
|
| 603 |
+
|
| 604 |
+
beta_crossover = from_float(0.6417)
|
| 605 |
+
alpha_crossover = from_float(1.5)
|
| 606 |
+
|
| 607 |
+
def acos_asin(z, prec, rnd, n):
|
| 608 |
+
""" complex acos for n = 0, asin for n = 1
|
| 609 |
+
The algorithm is described in
|
| 610 |
+
T.E. Hull, T.F. Fairgrieve and P.T.P. Tang
|
| 611 |
+
'Implementing the Complex Arcsine and Arcosine Functions
|
| 612 |
+
using Exception Handling',
|
| 613 |
+
ACM Trans. on Math. Software Vol. 23 (1997), p299
|
| 614 |
+
The complex acos and asin can be defined as
|
| 615 |
+
acos(z) = acos(beta) - I*sign(a)* log(alpha + sqrt(alpha**2 -1))
|
| 616 |
+
asin(z) = asin(beta) + I*sign(a)* log(alpha + sqrt(alpha**2 -1))
|
| 617 |
+
where z = a + I*b
|
| 618 |
+
alpha = (1/2)*(r + s); beta = (1/2)*(r - s) = a/alpha
|
| 619 |
+
r = sqrt((a+1)**2 + y**2); s = sqrt((a-1)**2 + y**2)
|
| 620 |
+
These expressions are rewritten in different ways in different
|
| 621 |
+
regions, delimited by two crossovers alpha_crossover and beta_crossover,
|
| 622 |
+
and by abs(a) <= 1, in order to improve the numerical accuracy.
|
| 623 |
+
"""
|
| 624 |
+
a, b = z
|
| 625 |
+
wp = prec + 10
|
| 626 |
+
# special cases with real argument
|
| 627 |
+
if b == fzero:
|
| 628 |
+
am = mpf_sub(fone, mpf_abs(a), wp)
|
| 629 |
+
# case abs(a) <= 1
|
| 630 |
+
if not am[0]:
|
| 631 |
+
if n == 0:
|
| 632 |
+
return mpf_acos(a, prec, rnd), fzero
|
| 633 |
+
else:
|
| 634 |
+
return mpf_asin(a, prec, rnd), fzero
|
| 635 |
+
# cases abs(a) > 1
|
| 636 |
+
else:
|
| 637 |
+
# case a < -1
|
| 638 |
+
if a[0]:
|
| 639 |
+
pi = mpf_pi(prec, rnd)
|
| 640 |
+
c = mpf_acosh(mpf_neg(a), prec, rnd)
|
| 641 |
+
if n == 0:
|
| 642 |
+
return pi, mpf_neg(c)
|
| 643 |
+
else:
|
| 644 |
+
return mpf_neg(mpf_shift(pi, -1)), c
|
| 645 |
+
# case a > 1
|
| 646 |
+
else:
|
| 647 |
+
c = mpf_acosh(a, prec, rnd)
|
| 648 |
+
if n == 0:
|
| 649 |
+
return fzero, c
|
| 650 |
+
else:
|
| 651 |
+
pi = mpf_pi(prec, rnd)
|
| 652 |
+
return mpf_shift(pi, -1), mpf_neg(c)
|
| 653 |
+
asign = bsign = 0
|
| 654 |
+
if a[0]:
|
| 655 |
+
a = mpf_neg(a)
|
| 656 |
+
asign = 1
|
| 657 |
+
if b[0]:
|
| 658 |
+
b = mpf_neg(b)
|
| 659 |
+
bsign = 1
|
| 660 |
+
am = mpf_sub(fone, a, wp)
|
| 661 |
+
ap = mpf_add(fone, a, wp)
|
| 662 |
+
r = mpf_hypot(ap, b, wp)
|
| 663 |
+
s = mpf_hypot(am, b, wp)
|
| 664 |
+
alpha = mpf_shift(mpf_add(r, s, wp), -1)
|
| 665 |
+
beta = mpf_div(a, alpha, wp)
|
| 666 |
+
b2 = mpf_mul(b,b, wp)
|
| 667 |
+
# case beta <= beta_crossover
|
| 668 |
+
if not mpf_sub(beta_crossover, beta, wp)[0]:
|
| 669 |
+
if n == 0:
|
| 670 |
+
re = mpf_acos(beta, wp)
|
| 671 |
+
else:
|
| 672 |
+
re = mpf_asin(beta, wp)
|
| 673 |
+
else:
|
| 674 |
+
# to compute the real part in this region use the identity
|
| 675 |
+
# asin(beta) = atan(beta/sqrt(1-beta**2))
|
| 676 |
+
# beta/sqrt(1-beta**2) = (alpha + a) * (alpha - a)
|
| 677 |
+
# alpha + a is numerically accurate; alpha - a can have
|
| 678 |
+
# cancellations leading to numerical inaccuracies, so rewrite
|
| 679 |
+
# it in differente ways according to the region
|
| 680 |
+
Ax = mpf_add(alpha, a, wp)
|
| 681 |
+
# case a <= 1
|
| 682 |
+
if not am[0]:
|
| 683 |
+
# c = b*b/(r + (a+1)); d = (s + (1-a))
|
| 684 |
+
# alpha - a = (1/2)*(c + d)
|
| 685 |
+
# case n=0: re = atan(sqrt((1/2) * Ax * (c + d))/a)
|
| 686 |
+
# case n=1: re = atan(a/sqrt((1/2) * Ax * (c + d)))
|
| 687 |
+
c = mpf_div(b2, mpf_add(r, ap, wp), wp)
|
| 688 |
+
d = mpf_add(s, am, wp)
|
| 689 |
+
re = mpf_shift(mpf_mul(Ax, mpf_add(c, d, wp), wp), -1)
|
| 690 |
+
if n == 0:
|
| 691 |
+
re = mpf_atan(mpf_div(mpf_sqrt(re, wp), a, wp), wp)
|
| 692 |
+
else:
|
| 693 |
+
re = mpf_atan(mpf_div(a, mpf_sqrt(re, wp), wp), wp)
|
| 694 |
+
else:
|
| 695 |
+
# c = Ax/(r + (a+1)); d = Ax/(s - (1-a))
|
| 696 |
+
# alpha - a = (1/2)*(c + d)
|
| 697 |
+
# case n = 0: re = atan(b*sqrt(c + d)/2/a)
|
| 698 |
+
# case n = 1: re = atan(a/(b*sqrt(c + d)/2)
|
| 699 |
+
c = mpf_div(Ax, mpf_add(r, ap, wp), wp)
|
| 700 |
+
d = mpf_div(Ax, mpf_sub(s, am, wp), wp)
|
| 701 |
+
re = mpf_shift(mpf_add(c, d, wp), -1)
|
| 702 |
+
re = mpf_mul(b, mpf_sqrt(re, wp), wp)
|
| 703 |
+
if n == 0:
|
| 704 |
+
re = mpf_atan(mpf_div(re, a, wp), wp)
|
| 705 |
+
else:
|
| 706 |
+
re = mpf_atan(mpf_div(a, re, wp), wp)
|
| 707 |
+
# to compute alpha + sqrt(alpha**2 - 1), if alpha <= alpha_crossover
|
| 708 |
+
# replace it with 1 + Am1 + sqrt(Am1*(alpha+1)))
|
| 709 |
+
# where Am1 = alpha -1
|
| 710 |
+
# if alpha <= alpha_crossover:
|
| 711 |
+
if not mpf_sub(alpha_crossover, alpha, wp)[0]:
|
| 712 |
+
c1 = mpf_div(b2, mpf_add(r, ap, wp), wp)
|
| 713 |
+
# case a < 1
|
| 714 |
+
if mpf_neg(am)[0]:
|
| 715 |
+
# Am1 = (1/2) * (b*b/(r + (a+1)) + b*b/(s + (1-a))
|
| 716 |
+
c2 = mpf_add(s, am, wp)
|
| 717 |
+
c2 = mpf_div(b2, c2, wp)
|
| 718 |
+
Am1 = mpf_shift(mpf_add(c1, c2, wp), -1)
|
| 719 |
+
else:
|
| 720 |
+
# Am1 = (1/2) * (b*b/(r + (a+1)) + (s - (1-a)))
|
| 721 |
+
c2 = mpf_sub(s, am, wp)
|
| 722 |
+
Am1 = mpf_shift(mpf_add(c1, c2, wp), -1)
|
| 723 |
+
# im = log(1 + Am1 + sqrt(Am1*(alpha+1)))
|
| 724 |
+
im = mpf_mul(Am1, mpf_add(alpha, fone, wp), wp)
|
| 725 |
+
im = mpf_log(mpf_add(fone, mpf_add(Am1, mpf_sqrt(im, wp), wp), wp), wp)
|
| 726 |
+
else:
|
| 727 |
+
# im = log(alpha + sqrt(alpha*alpha - 1))
|
| 728 |
+
im = mpf_sqrt(mpf_sub(mpf_mul(alpha, alpha, wp), fone, wp), wp)
|
| 729 |
+
im = mpf_log(mpf_add(alpha, im, wp), wp)
|
| 730 |
+
if asign:
|
| 731 |
+
if n == 0:
|
| 732 |
+
re = mpf_sub(mpf_pi(wp), re, wp)
|
| 733 |
+
else:
|
| 734 |
+
re = mpf_neg(re)
|
| 735 |
+
if not bsign and n == 0:
|
| 736 |
+
im = mpf_neg(im)
|
| 737 |
+
if bsign and n == 1:
|
| 738 |
+
im = mpf_neg(im)
|
| 739 |
+
re = normalize(re[0], re[1], re[2], re[3], prec, rnd)
|
| 740 |
+
im = normalize(im[0], im[1], im[2], im[3], prec, rnd)
|
| 741 |
+
return re, im
|
| 742 |
+
|
| 743 |
+
def mpc_acos(z, prec, rnd=round_fast):
|
| 744 |
+
return acos_asin(z, prec, rnd, 0)
|
| 745 |
+
|
| 746 |
+
def mpc_asin(z, prec, rnd=round_fast):
|
| 747 |
+
return acos_asin(z, prec, rnd, 1)
|
| 748 |
+
|
| 749 |
+
def mpc_asinh(z, prec, rnd=round_fast):
|
| 750 |
+
# asinh(z) = I * asin(-I z)
|
| 751 |
+
a, b = z
|
| 752 |
+
a, b = mpc_asin((b, mpf_neg(a)), prec, rnd)
|
| 753 |
+
return mpf_neg(b), a
|
| 754 |
+
|
| 755 |
+
def mpc_acosh(z, prec, rnd=round_fast):
|
| 756 |
+
# acosh(z) = -I * acos(z) for Im(acos(z)) <= 0
|
| 757 |
+
# +I * acos(z) otherwise
|
| 758 |
+
a, b = mpc_acos(z, prec, rnd)
|
| 759 |
+
if b[0] or b == fzero:
|
| 760 |
+
return mpf_neg(b), a
|
| 761 |
+
else:
|
| 762 |
+
return b, mpf_neg(a)
|
| 763 |
+
|
| 764 |
+
def mpc_atanh(z, prec, rnd=round_fast):
|
| 765 |
+
# atanh(z) = (log(1+z)-log(1-z))/2
|
| 766 |
+
wp = prec + 15
|
| 767 |
+
a = mpc_add(z, mpc_one, wp)
|
| 768 |
+
b = mpc_sub(mpc_one, z, wp)
|
| 769 |
+
a = mpc_log(a, wp)
|
| 770 |
+
b = mpc_log(b, wp)
|
| 771 |
+
v = mpc_shift(mpc_sub(a, b, wp), -1)
|
| 772 |
+
# Subtraction at infinity gives correct imaginary part but
|
| 773 |
+
# wrong real part (should be zero)
|
| 774 |
+
if v[0] == fnan and mpc_is_inf(z):
|
| 775 |
+
v = (fzero, v[1])
|
| 776 |
+
return v
|
| 777 |
+
|
| 778 |
+
def mpc_fibonacci(z, prec, rnd=round_fast):
|
| 779 |
+
re, im = z
|
| 780 |
+
if im == fzero:
|
| 781 |
+
return (mpf_fibonacci(re, prec, rnd), fzero)
|
| 782 |
+
size = max(abs(re[2]+re[3]), abs(re[2]+re[3]))
|
| 783 |
+
wp = prec + size + 20
|
| 784 |
+
a = mpf_phi(wp)
|
| 785 |
+
b = mpf_add(mpf_shift(a, 1), fnone, wp)
|
| 786 |
+
u = mpc_pow((a, fzero), z, wp)
|
| 787 |
+
v = mpc_cos_pi(z, wp)
|
| 788 |
+
v = mpc_div(v, u, wp)
|
| 789 |
+
u = mpc_sub(u, v, wp)
|
| 790 |
+
u = mpc_div_mpf(u, b, prec, rnd)
|
| 791 |
+
return u
|
| 792 |
+
|
| 793 |
+
def mpf_expj(x, prec, rnd='f'):
|
| 794 |
+
raise ComplexResult
|
| 795 |
+
|
| 796 |
+
def mpc_expj(z, prec, rnd='f'):
|
| 797 |
+
re, im = z
|
| 798 |
+
if im == fzero:
|
| 799 |
+
return mpf_cos_sin(re, prec, rnd)
|
| 800 |
+
if re == fzero:
|
| 801 |
+
return mpf_exp(mpf_neg(im), prec, rnd), fzero
|
| 802 |
+
ey = mpf_exp(mpf_neg(im), prec+10)
|
| 803 |
+
c, s = mpf_cos_sin(re, prec+10)
|
| 804 |
+
re = mpf_mul(ey, c, prec, rnd)
|
| 805 |
+
im = mpf_mul(ey, s, prec, rnd)
|
| 806 |
+
return re, im
|
| 807 |
+
|
| 808 |
+
def mpf_expjpi(x, prec, rnd='f'):
|
| 809 |
+
raise ComplexResult
|
| 810 |
+
|
| 811 |
+
def mpc_expjpi(z, prec, rnd='f'):
|
| 812 |
+
re, im = z
|
| 813 |
+
if im == fzero:
|
| 814 |
+
return mpf_cos_sin_pi(re, prec, rnd)
|
| 815 |
+
sign, man, exp, bc = im
|
| 816 |
+
wp = prec+10
|
| 817 |
+
if man:
|
| 818 |
+
wp += max(0, exp+bc)
|
| 819 |
+
im = mpf_neg(mpf_mul(mpf_pi(wp), im, wp))
|
| 820 |
+
if re == fzero:
|
| 821 |
+
return mpf_exp(im, prec, rnd), fzero
|
| 822 |
+
ey = mpf_exp(im, prec+10)
|
| 823 |
+
c, s = mpf_cos_sin_pi(re, prec+10)
|
| 824 |
+
re = mpf_mul(ey, c, prec, rnd)
|
| 825 |
+
im = mpf_mul(ey, s, prec, rnd)
|
| 826 |
+
return re, im
|
| 827 |
+
|
| 828 |
+
|
| 829 |
+
if BACKEND == 'sage':
|
| 830 |
+
try:
|
| 831 |
+
import sage.libs.mpmath.ext_libmp as _lbmp
|
| 832 |
+
mpc_exp = _lbmp.mpc_exp
|
| 833 |
+
mpc_sqrt = _lbmp.mpc_sqrt
|
| 834 |
+
except (ImportError, AttributeError):
|
| 835 |
+
print("Warning: Sage imports in libmpc failed")
|
.venv/lib/python3.11/site-packages/mpmath/libmp/libmpf.py
ADDED
|
@@ -0,0 +1,1414 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Low-level functions for arbitrary-precision floating-point arithmetic.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
__docformat__ = 'plaintext'
|
| 6 |
+
|
| 7 |
+
import math
|
| 8 |
+
|
| 9 |
+
from bisect import bisect
|
| 10 |
+
|
| 11 |
+
import sys
|
| 12 |
+
|
| 13 |
+
# Importing random is slow
|
| 14 |
+
#from random import getrandbits
|
| 15 |
+
getrandbits = None
|
| 16 |
+
|
| 17 |
+
from .backend import (MPZ, MPZ_TYPE, MPZ_ZERO, MPZ_ONE, MPZ_TWO, MPZ_FIVE,
|
| 18 |
+
BACKEND, STRICT, HASH_MODULUS, HASH_BITS, gmpy, sage, sage_utils)
|
| 19 |
+
|
| 20 |
+
from .libintmath import (giant_steps,
|
| 21 |
+
trailtable, bctable, lshift, rshift, bitcount, trailing,
|
| 22 |
+
sqrt_fixed, numeral, isqrt, isqrt_fast, sqrtrem,
|
| 23 |
+
bin_to_radix)
|
| 24 |
+
|
| 25 |
+
# We don't pickle tuples directly for the following reasons:
|
| 26 |
+
# 1: pickle uses str() for ints, which is inefficient when they are large
|
| 27 |
+
# 2: pickle doesn't work for gmpy mpzs
|
| 28 |
+
# Both problems are solved by using hex()
|
| 29 |
+
|
| 30 |
+
if BACKEND == 'sage':
|
| 31 |
+
def to_pickable(x):
|
| 32 |
+
sign, man, exp, bc = x
|
| 33 |
+
return sign, hex(man), exp, bc
|
| 34 |
+
else:
|
| 35 |
+
def to_pickable(x):
|
| 36 |
+
sign, man, exp, bc = x
|
| 37 |
+
return sign, hex(man)[2:], exp, bc
|
| 38 |
+
|
| 39 |
+
def from_pickable(x):
|
| 40 |
+
sign, man, exp, bc = x
|
| 41 |
+
return (sign, MPZ(man, 16), exp, bc)
|
| 42 |
+
|
| 43 |
+
class ComplexResult(ValueError):
|
| 44 |
+
pass
|
| 45 |
+
|
| 46 |
+
try:
|
| 47 |
+
intern
|
| 48 |
+
except NameError:
|
| 49 |
+
intern = lambda x: x
|
| 50 |
+
|
| 51 |
+
# All supported rounding modes
|
| 52 |
+
round_nearest = intern('n')
|
| 53 |
+
round_floor = intern('f')
|
| 54 |
+
round_ceiling = intern('c')
|
| 55 |
+
round_up = intern('u')
|
| 56 |
+
round_down = intern('d')
|
| 57 |
+
round_fast = round_down
|
| 58 |
+
|
| 59 |
+
def prec_to_dps(n):
|
| 60 |
+
"""Return number of accurate decimals that can be represented
|
| 61 |
+
with a precision of n bits."""
|
| 62 |
+
return max(1, int(round(int(n)/3.3219280948873626)-1))
|
| 63 |
+
|
| 64 |
+
def dps_to_prec(n):
|
| 65 |
+
"""Return the number of bits required to represent n decimals
|
| 66 |
+
accurately."""
|
| 67 |
+
return max(1, int(round((int(n)+1)*3.3219280948873626)))
|
| 68 |
+
|
| 69 |
+
def repr_dps(n):
|
| 70 |
+
"""Return the number of decimal digits required to represent
|
| 71 |
+
a number with n-bit precision so that it can be uniquely
|
| 72 |
+
reconstructed from the representation."""
|
| 73 |
+
dps = prec_to_dps(n)
|
| 74 |
+
if dps == 15:
|
| 75 |
+
return 17
|
| 76 |
+
return dps + 3
|
| 77 |
+
|
| 78 |
+
#----------------------------------------------------------------------------#
|
| 79 |
+
# Some commonly needed float values #
|
| 80 |
+
#----------------------------------------------------------------------------#
|
| 81 |
+
|
| 82 |
+
# Regular number format:
|
| 83 |
+
# (-1)**sign * mantissa * 2**exponent, plus bitcount of mantissa
|
| 84 |
+
fzero = (0, MPZ_ZERO, 0, 0)
|
| 85 |
+
fnzero = (1, MPZ_ZERO, 0, 0)
|
| 86 |
+
fone = (0, MPZ_ONE, 0, 1)
|
| 87 |
+
fnone = (1, MPZ_ONE, 0, 1)
|
| 88 |
+
ftwo = (0, MPZ_ONE, 1, 1)
|
| 89 |
+
ften = (0, MPZ_FIVE, 1, 3)
|
| 90 |
+
fhalf = (0, MPZ_ONE, -1, 1)
|
| 91 |
+
|
| 92 |
+
# Arbitrary encoding for special numbers: zero mantissa, nonzero exponent
|
| 93 |
+
fnan = (0, MPZ_ZERO, -123, -1)
|
| 94 |
+
finf = (0, MPZ_ZERO, -456, -2)
|
| 95 |
+
fninf = (1, MPZ_ZERO, -789, -3)
|
| 96 |
+
|
| 97 |
+
# Was 1e1000; this is broken in Python 2.4
|
| 98 |
+
math_float_inf = 1e300 * 1e300
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
#----------------------------------------------------------------------------#
|
| 102 |
+
# Rounding #
|
| 103 |
+
#----------------------------------------------------------------------------#
|
| 104 |
+
|
| 105 |
+
# This function can be used to round a mantissa generally. However,
|
| 106 |
+
# we will try to do most rounding inline for efficiency.
|
| 107 |
+
def round_int(x, n, rnd):
|
| 108 |
+
if rnd == round_nearest:
|
| 109 |
+
if x >= 0:
|
| 110 |
+
t = x >> (n-1)
|
| 111 |
+
if t & 1 and ((t & 2) or (x & h_mask[n<300][n])):
|
| 112 |
+
return (t>>1)+1
|
| 113 |
+
else:
|
| 114 |
+
return t>>1
|
| 115 |
+
else:
|
| 116 |
+
return -round_int(-x, n, rnd)
|
| 117 |
+
if rnd == round_floor:
|
| 118 |
+
return x >> n
|
| 119 |
+
if rnd == round_ceiling:
|
| 120 |
+
return -((-x) >> n)
|
| 121 |
+
if rnd == round_down:
|
| 122 |
+
if x >= 0:
|
| 123 |
+
return x >> n
|
| 124 |
+
return -((-x) >> n)
|
| 125 |
+
if rnd == round_up:
|
| 126 |
+
if x >= 0:
|
| 127 |
+
return -((-x) >> n)
|
| 128 |
+
return x >> n
|
| 129 |
+
|
| 130 |
+
# These masks are used to pick out segments of numbers to determine
|
| 131 |
+
# which direction to round when rounding to nearest.
|
| 132 |
+
class h_mask_big:
|
| 133 |
+
def __getitem__(self, n):
|
| 134 |
+
return (MPZ_ONE<<(n-1))-1
|
| 135 |
+
|
| 136 |
+
h_mask_small = [0]+[((MPZ_ONE<<(_-1))-1) for _ in range(1, 300)]
|
| 137 |
+
h_mask = [h_mask_big(), h_mask_small]
|
| 138 |
+
|
| 139 |
+
# The >> operator rounds to floor. shifts_down[rnd][sign]
|
| 140 |
+
# tells whether this is the right direction to use, or if the
|
| 141 |
+
# number should be negated before shifting
|
| 142 |
+
shifts_down = {round_floor:(1,0), round_ceiling:(0,1),
|
| 143 |
+
round_down:(1,1), round_up:(0,0)}
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
#----------------------------------------------------------------------------#
|
| 147 |
+
# Normalization of raw mpfs #
|
| 148 |
+
#----------------------------------------------------------------------------#
|
| 149 |
+
|
| 150 |
+
# This function is called almost every time an mpf is created.
|
| 151 |
+
# It has been optimized accordingly.
|
| 152 |
+
|
| 153 |
+
def _normalize(sign, man, exp, bc, prec, rnd):
|
| 154 |
+
"""
|
| 155 |
+
Create a raw mpf tuple with value (-1)**sign * man * 2**exp and
|
| 156 |
+
normalized mantissa. The mantissa is rounded in the specified
|
| 157 |
+
direction if its size exceeds the precision. Trailing zero bits
|
| 158 |
+
are also stripped from the mantissa to ensure that the
|
| 159 |
+
representation is canonical.
|
| 160 |
+
|
| 161 |
+
Conditions on the input:
|
| 162 |
+
* The input must represent a regular (finite) number
|
| 163 |
+
* The sign bit must be 0 or 1
|
| 164 |
+
* The mantissa must be positive
|
| 165 |
+
* The exponent must be an integer
|
| 166 |
+
* The bitcount must be exact
|
| 167 |
+
|
| 168 |
+
If these conditions are not met, use from_man_exp, mpf_pos, or any
|
| 169 |
+
of the conversion functions to create normalized raw mpf tuples.
|
| 170 |
+
"""
|
| 171 |
+
if not man:
|
| 172 |
+
return fzero
|
| 173 |
+
# Cut mantissa down to size if larger than target precision
|
| 174 |
+
n = bc - prec
|
| 175 |
+
if n > 0:
|
| 176 |
+
if rnd == round_nearest:
|
| 177 |
+
t = man >> (n-1)
|
| 178 |
+
if t & 1 and ((t & 2) or (man & h_mask[n<300][n])):
|
| 179 |
+
man = (t>>1)+1
|
| 180 |
+
else:
|
| 181 |
+
man = t>>1
|
| 182 |
+
elif shifts_down[rnd][sign]:
|
| 183 |
+
man >>= n
|
| 184 |
+
else:
|
| 185 |
+
man = -((-man)>>n)
|
| 186 |
+
exp += n
|
| 187 |
+
bc = prec
|
| 188 |
+
# Strip trailing bits
|
| 189 |
+
if not man & 1:
|
| 190 |
+
t = trailtable[int(man & 255)]
|
| 191 |
+
if not t:
|
| 192 |
+
while not man & 255:
|
| 193 |
+
man >>= 8
|
| 194 |
+
exp += 8
|
| 195 |
+
bc -= 8
|
| 196 |
+
t = trailtable[int(man & 255)]
|
| 197 |
+
man >>= t
|
| 198 |
+
exp += t
|
| 199 |
+
bc -= t
|
| 200 |
+
# Bit count can be wrong if the input mantissa was 1 less than
|
| 201 |
+
# a power of 2 and got rounded up, thereby adding an extra bit.
|
| 202 |
+
# With trailing bits removed, all powers of two have mantissa 1,
|
| 203 |
+
# so this is easy to check for.
|
| 204 |
+
if man == 1:
|
| 205 |
+
bc = 1
|
| 206 |
+
return sign, man, exp, bc
|
| 207 |
+
|
| 208 |
+
def _normalize1(sign, man, exp, bc, prec, rnd):
|
| 209 |
+
"""same as normalize, but with the added condition that
|
| 210 |
+
man is odd or zero
|
| 211 |
+
"""
|
| 212 |
+
if not man:
|
| 213 |
+
return fzero
|
| 214 |
+
if bc <= prec:
|
| 215 |
+
return sign, man, exp, bc
|
| 216 |
+
n = bc - prec
|
| 217 |
+
if rnd == round_nearest:
|
| 218 |
+
t = man >> (n-1)
|
| 219 |
+
if t & 1 and ((t & 2) or (man & h_mask[n<300][n])):
|
| 220 |
+
man = (t>>1)+1
|
| 221 |
+
else:
|
| 222 |
+
man = t>>1
|
| 223 |
+
elif shifts_down[rnd][sign]:
|
| 224 |
+
man >>= n
|
| 225 |
+
else:
|
| 226 |
+
man = -((-man)>>n)
|
| 227 |
+
exp += n
|
| 228 |
+
bc = prec
|
| 229 |
+
# Strip trailing bits
|
| 230 |
+
if not man & 1:
|
| 231 |
+
t = trailtable[int(man & 255)]
|
| 232 |
+
if not t:
|
| 233 |
+
while not man & 255:
|
| 234 |
+
man >>= 8
|
| 235 |
+
exp += 8
|
| 236 |
+
bc -= 8
|
| 237 |
+
t = trailtable[int(man & 255)]
|
| 238 |
+
man >>= t
|
| 239 |
+
exp += t
|
| 240 |
+
bc -= t
|
| 241 |
+
# Bit count can be wrong if the input mantissa was 1 less than
|
| 242 |
+
# a power of 2 and got rounded up, thereby adding an extra bit.
|
| 243 |
+
# With trailing bits removed, all powers of two have mantissa 1,
|
| 244 |
+
# so this is easy to check for.
|
| 245 |
+
if man == 1:
|
| 246 |
+
bc = 1
|
| 247 |
+
return sign, man, exp, bc
|
| 248 |
+
|
| 249 |
+
try:
|
| 250 |
+
_exp_types = (int, long)
|
| 251 |
+
except NameError:
|
| 252 |
+
_exp_types = (int,)
|
| 253 |
+
|
| 254 |
+
def strict_normalize(sign, man, exp, bc, prec, rnd):
|
| 255 |
+
"""Additional checks on the components of an mpf. Enable tests by setting
|
| 256 |
+
the environment variable MPMATH_STRICT to Y."""
|
| 257 |
+
assert type(man) == MPZ_TYPE
|
| 258 |
+
assert type(bc) in _exp_types
|
| 259 |
+
assert type(exp) in _exp_types
|
| 260 |
+
assert bc == bitcount(man)
|
| 261 |
+
return _normalize(sign, man, exp, bc, prec, rnd)
|
| 262 |
+
|
| 263 |
+
def strict_normalize1(sign, man, exp, bc, prec, rnd):
|
| 264 |
+
"""Additional checks on the components of an mpf. Enable tests by setting
|
| 265 |
+
the environment variable MPMATH_STRICT to Y."""
|
| 266 |
+
assert type(man) == MPZ_TYPE
|
| 267 |
+
assert type(bc) in _exp_types
|
| 268 |
+
assert type(exp) in _exp_types
|
| 269 |
+
assert bc == bitcount(man)
|
| 270 |
+
assert (not man) or (man & 1)
|
| 271 |
+
return _normalize1(sign, man, exp, bc, prec, rnd)
|
| 272 |
+
|
| 273 |
+
if BACKEND == 'gmpy' and '_mpmath_normalize' in dir(gmpy):
|
| 274 |
+
_normalize = gmpy._mpmath_normalize
|
| 275 |
+
_normalize1 = gmpy._mpmath_normalize
|
| 276 |
+
|
| 277 |
+
if BACKEND == 'sage':
|
| 278 |
+
_normalize = _normalize1 = sage_utils.normalize
|
| 279 |
+
|
| 280 |
+
if STRICT:
|
| 281 |
+
normalize = strict_normalize
|
| 282 |
+
normalize1 = strict_normalize1
|
| 283 |
+
else:
|
| 284 |
+
normalize = _normalize
|
| 285 |
+
normalize1 = _normalize1
|
| 286 |
+
|
| 287 |
+
#----------------------------------------------------------------------------#
|
| 288 |
+
# Conversion functions #
|
| 289 |
+
#----------------------------------------------------------------------------#
|
| 290 |
+
|
| 291 |
+
def from_man_exp(man, exp, prec=None, rnd=round_fast):
|
| 292 |
+
"""Create raw mpf from (man, exp) pair. The mantissa may be signed.
|
| 293 |
+
If no precision is specified, the mantissa is stored exactly."""
|
| 294 |
+
man = MPZ(man)
|
| 295 |
+
sign = 0
|
| 296 |
+
if man < 0:
|
| 297 |
+
sign = 1
|
| 298 |
+
man = -man
|
| 299 |
+
if man < 1024:
|
| 300 |
+
bc = bctable[int(man)]
|
| 301 |
+
else:
|
| 302 |
+
bc = bitcount(man)
|
| 303 |
+
if not prec:
|
| 304 |
+
if not man:
|
| 305 |
+
return fzero
|
| 306 |
+
if not man & 1:
|
| 307 |
+
if man & 2:
|
| 308 |
+
return (sign, man >> 1, exp + 1, bc - 1)
|
| 309 |
+
t = trailtable[int(man & 255)]
|
| 310 |
+
if not t:
|
| 311 |
+
while not man & 255:
|
| 312 |
+
man >>= 8
|
| 313 |
+
exp += 8
|
| 314 |
+
bc -= 8
|
| 315 |
+
t = trailtable[int(man & 255)]
|
| 316 |
+
man >>= t
|
| 317 |
+
exp += t
|
| 318 |
+
bc -= t
|
| 319 |
+
return (sign, man, exp, bc)
|
| 320 |
+
return normalize(sign, man, exp, bc, prec, rnd)
|
| 321 |
+
|
| 322 |
+
int_cache = dict((n, from_man_exp(n, 0)) for n in range(-10, 257))
|
| 323 |
+
|
| 324 |
+
if BACKEND == 'gmpy' and '_mpmath_create' in dir(gmpy):
|
| 325 |
+
from_man_exp = gmpy._mpmath_create
|
| 326 |
+
|
| 327 |
+
if BACKEND == 'sage':
|
| 328 |
+
from_man_exp = sage_utils.from_man_exp
|
| 329 |
+
|
| 330 |
+
def from_int(n, prec=0, rnd=round_fast):
|
| 331 |
+
"""Create a raw mpf from an integer. If no precision is specified,
|
| 332 |
+
the mantissa is stored exactly."""
|
| 333 |
+
if not prec:
|
| 334 |
+
if n in int_cache:
|
| 335 |
+
return int_cache[n]
|
| 336 |
+
return from_man_exp(n, 0, prec, rnd)
|
| 337 |
+
|
| 338 |
+
def to_man_exp(s):
|
| 339 |
+
"""Return (man, exp) of a raw mpf. Raise an error if inf/nan."""
|
| 340 |
+
sign, man, exp, bc = s
|
| 341 |
+
if (not man) and exp:
|
| 342 |
+
raise ValueError("mantissa and exponent are undefined for %s" % man)
|
| 343 |
+
return man, exp
|
| 344 |
+
|
| 345 |
+
def to_int(s, rnd=None):
|
| 346 |
+
"""Convert a raw mpf to the nearest int. Rounding is done down by
|
| 347 |
+
default (same as int(float) in Python), but can be changed. If the
|
| 348 |
+
input is inf/nan, an exception is raised."""
|
| 349 |
+
sign, man, exp, bc = s
|
| 350 |
+
if (not man) and exp:
|
| 351 |
+
raise ValueError("cannot convert inf or nan to int")
|
| 352 |
+
if exp >= 0:
|
| 353 |
+
if sign:
|
| 354 |
+
return (-man) << exp
|
| 355 |
+
return man << exp
|
| 356 |
+
# Make default rounding fast
|
| 357 |
+
if not rnd:
|
| 358 |
+
if sign:
|
| 359 |
+
return -(man >> (-exp))
|
| 360 |
+
else:
|
| 361 |
+
return man >> (-exp)
|
| 362 |
+
if sign:
|
| 363 |
+
return round_int(-man, -exp, rnd)
|
| 364 |
+
else:
|
| 365 |
+
return round_int(man, -exp, rnd)
|
| 366 |
+
|
| 367 |
+
def mpf_round_int(s, rnd):
|
| 368 |
+
sign, man, exp, bc = s
|
| 369 |
+
if (not man) and exp:
|
| 370 |
+
return s
|
| 371 |
+
if exp >= 0:
|
| 372 |
+
return s
|
| 373 |
+
mag = exp+bc
|
| 374 |
+
if mag < 1:
|
| 375 |
+
if rnd == round_ceiling:
|
| 376 |
+
if sign: return fzero
|
| 377 |
+
else: return fone
|
| 378 |
+
elif rnd == round_floor:
|
| 379 |
+
if sign: return fnone
|
| 380 |
+
else: return fzero
|
| 381 |
+
elif rnd == round_nearest:
|
| 382 |
+
if mag < 0 or man == MPZ_ONE: return fzero
|
| 383 |
+
elif sign: return fnone
|
| 384 |
+
else: return fone
|
| 385 |
+
else:
|
| 386 |
+
raise NotImplementedError
|
| 387 |
+
return mpf_pos(s, min(bc, mag), rnd)
|
| 388 |
+
|
| 389 |
+
def mpf_floor(s, prec=0, rnd=round_fast):
|
| 390 |
+
v = mpf_round_int(s, round_floor)
|
| 391 |
+
if prec:
|
| 392 |
+
v = mpf_pos(v, prec, rnd)
|
| 393 |
+
return v
|
| 394 |
+
|
| 395 |
+
def mpf_ceil(s, prec=0, rnd=round_fast):
|
| 396 |
+
v = mpf_round_int(s, round_ceiling)
|
| 397 |
+
if prec:
|
| 398 |
+
v = mpf_pos(v, prec, rnd)
|
| 399 |
+
return v
|
| 400 |
+
|
| 401 |
+
def mpf_nint(s, prec=0, rnd=round_fast):
|
| 402 |
+
v = mpf_round_int(s, round_nearest)
|
| 403 |
+
if prec:
|
| 404 |
+
v = mpf_pos(v, prec, rnd)
|
| 405 |
+
return v
|
| 406 |
+
|
| 407 |
+
def mpf_frac(s, prec=0, rnd=round_fast):
|
| 408 |
+
return mpf_sub(s, mpf_floor(s), prec, rnd)
|
| 409 |
+
|
| 410 |
+
def from_float(x, prec=53, rnd=round_fast):
|
| 411 |
+
"""Create a raw mpf from a Python float, rounding if necessary.
|
| 412 |
+
If prec >= 53, the result is guaranteed to represent exactly the
|
| 413 |
+
same number as the input. If prec is not specified, use prec=53."""
|
| 414 |
+
# frexp only raises an exception for nan on some platforms
|
| 415 |
+
if x != x:
|
| 416 |
+
return fnan
|
| 417 |
+
# in Python2.5 math.frexp gives an exception for float infinity
|
| 418 |
+
# in Python2.6 it returns (float infinity, 0)
|
| 419 |
+
try:
|
| 420 |
+
m, e = math.frexp(x)
|
| 421 |
+
except:
|
| 422 |
+
if x == math_float_inf: return finf
|
| 423 |
+
if x == -math_float_inf: return fninf
|
| 424 |
+
return fnan
|
| 425 |
+
if x == math_float_inf: return finf
|
| 426 |
+
if x == -math_float_inf: return fninf
|
| 427 |
+
return from_man_exp(int(m*(1<<53)), e-53, prec, rnd)
|
| 428 |
+
|
| 429 |
+
def from_npfloat(x, prec=113, rnd=round_fast):
|
| 430 |
+
"""Create a raw mpf from a numpy float, rounding if necessary.
|
| 431 |
+
If prec >= 113, the result is guaranteed to represent exactly the
|
| 432 |
+
same number as the input. If prec is not specified, use prec=113."""
|
| 433 |
+
y = float(x)
|
| 434 |
+
if x == y: # ldexp overflows for float16
|
| 435 |
+
return from_float(y, prec, rnd)
|
| 436 |
+
import numpy as np
|
| 437 |
+
if np.isfinite(x):
|
| 438 |
+
m, e = np.frexp(x)
|
| 439 |
+
return from_man_exp(int(np.ldexp(m, 113)), int(e-113), prec, rnd)
|
| 440 |
+
if np.isposinf(x): return finf
|
| 441 |
+
if np.isneginf(x): return fninf
|
| 442 |
+
return fnan
|
| 443 |
+
|
| 444 |
+
def from_Decimal(x, prec=None, rnd=round_fast):
|
| 445 |
+
"""Create a raw mpf from a Decimal, rounding if necessary.
|
| 446 |
+
If prec is not specified, use the equivalent bit precision
|
| 447 |
+
of the number of significant digits in x."""
|
| 448 |
+
if x.is_nan(): return fnan
|
| 449 |
+
if x.is_infinite(): return fninf if x.is_signed() else finf
|
| 450 |
+
if prec is None:
|
| 451 |
+
prec = int(len(x.as_tuple()[1])*3.3219280948873626)
|
| 452 |
+
return from_str(str(x), prec, rnd)
|
| 453 |
+
|
| 454 |
+
def to_float(s, strict=False, rnd=round_fast):
|
| 455 |
+
"""
|
| 456 |
+
Convert a raw mpf to a Python float. The result is exact if the
|
| 457 |
+
bitcount of s is <= 53 and no underflow/overflow occurs.
|
| 458 |
+
|
| 459 |
+
If the number is too large or too small to represent as a regular
|
| 460 |
+
float, it will be converted to inf or 0.0. Setting strict=True
|
| 461 |
+
forces an OverflowError to be raised instead.
|
| 462 |
+
|
| 463 |
+
Warning: with a directed rounding mode, the correct nearest representable
|
| 464 |
+
floating-point number in the specified direction might not be computed
|
| 465 |
+
in case of overflow or (gradual) underflow.
|
| 466 |
+
"""
|
| 467 |
+
sign, man, exp, bc = s
|
| 468 |
+
if not man:
|
| 469 |
+
if s == fzero: return 0.0
|
| 470 |
+
if s == finf: return math_float_inf
|
| 471 |
+
if s == fninf: return -math_float_inf
|
| 472 |
+
return math_float_inf/math_float_inf
|
| 473 |
+
if bc > 53:
|
| 474 |
+
sign, man, exp, bc = normalize1(sign, man, exp, bc, 53, rnd)
|
| 475 |
+
if sign:
|
| 476 |
+
man = -man
|
| 477 |
+
try:
|
| 478 |
+
return math.ldexp(man, exp)
|
| 479 |
+
except OverflowError:
|
| 480 |
+
if strict:
|
| 481 |
+
raise
|
| 482 |
+
# Overflow to infinity
|
| 483 |
+
if exp + bc > 0:
|
| 484 |
+
if sign:
|
| 485 |
+
return -math_float_inf
|
| 486 |
+
else:
|
| 487 |
+
return math_float_inf
|
| 488 |
+
# Underflow to zero
|
| 489 |
+
return 0.0
|
| 490 |
+
|
| 491 |
+
def from_rational(p, q, prec, rnd=round_fast):
|
| 492 |
+
"""Create a raw mpf from a rational number p/q, round if
|
| 493 |
+
necessary."""
|
| 494 |
+
return mpf_div(from_int(p), from_int(q), prec, rnd)
|
| 495 |
+
|
| 496 |
+
def to_rational(s):
|
| 497 |
+
"""Convert a raw mpf to a rational number. Return integers (p, q)
|
| 498 |
+
such that s = p/q exactly."""
|
| 499 |
+
sign, man, exp, bc = s
|
| 500 |
+
if sign:
|
| 501 |
+
man = -man
|
| 502 |
+
if bc == -1:
|
| 503 |
+
raise ValueError("cannot convert %s to a rational number" % man)
|
| 504 |
+
if exp >= 0:
|
| 505 |
+
return man * (1<<exp), 1
|
| 506 |
+
else:
|
| 507 |
+
return man, 1<<(-exp)
|
| 508 |
+
|
| 509 |
+
def to_fixed(s, prec):
|
| 510 |
+
"""Convert a raw mpf to a fixed-point big integer"""
|
| 511 |
+
sign, man, exp, bc = s
|
| 512 |
+
offset = exp + prec
|
| 513 |
+
if sign:
|
| 514 |
+
if offset >= 0: return (-man) << offset
|
| 515 |
+
else: return (-man) >> (-offset)
|
| 516 |
+
else:
|
| 517 |
+
if offset >= 0: return man << offset
|
| 518 |
+
else: return man >> (-offset)
|
| 519 |
+
|
| 520 |
+
|
| 521 |
+
##############################################################################
|
| 522 |
+
##############################################################################
|
| 523 |
+
|
| 524 |
+
#----------------------------------------------------------------------------#
|
| 525 |
+
# Arithmetic operations, etc. #
|
| 526 |
+
#----------------------------------------------------------------------------#
|
| 527 |
+
|
| 528 |
+
def mpf_rand(prec):
|
| 529 |
+
"""Return a raw mpf chosen randomly from [0, 1), with prec bits
|
| 530 |
+
in the mantissa."""
|
| 531 |
+
global getrandbits
|
| 532 |
+
if not getrandbits:
|
| 533 |
+
import random
|
| 534 |
+
getrandbits = random.getrandbits
|
| 535 |
+
return from_man_exp(getrandbits(prec), -prec, prec, round_floor)
|
| 536 |
+
|
| 537 |
+
def mpf_eq(s, t):
|
| 538 |
+
"""Test equality of two raw mpfs. This is simply tuple comparison
|
| 539 |
+
unless either number is nan, in which case the result is False."""
|
| 540 |
+
if not s[1] or not t[1]:
|
| 541 |
+
if s == fnan or t == fnan:
|
| 542 |
+
return False
|
| 543 |
+
return s == t
|
| 544 |
+
|
| 545 |
+
def mpf_hash(s):
|
| 546 |
+
# Duplicate the new hash algorithm introduces in Python 3.2.
|
| 547 |
+
if sys.version_info >= (3, 2):
|
| 548 |
+
ssign, sman, sexp, sbc = s
|
| 549 |
+
|
| 550 |
+
# Handle special numbers
|
| 551 |
+
if not sman:
|
| 552 |
+
if s == fnan: return sys.hash_info.nan
|
| 553 |
+
if s == finf: return sys.hash_info.inf
|
| 554 |
+
if s == fninf: return -sys.hash_info.inf
|
| 555 |
+
h = sman % HASH_MODULUS
|
| 556 |
+
if sexp >= 0:
|
| 557 |
+
sexp = sexp % HASH_BITS
|
| 558 |
+
else:
|
| 559 |
+
sexp = HASH_BITS - 1 - ((-1 - sexp) % HASH_BITS)
|
| 560 |
+
h = (h << sexp) % HASH_MODULUS
|
| 561 |
+
if ssign: h = -h
|
| 562 |
+
if h == -1: h = -2
|
| 563 |
+
return int(h)
|
| 564 |
+
else:
|
| 565 |
+
try:
|
| 566 |
+
# Try to be compatible with hash values for floats and ints
|
| 567 |
+
return hash(to_float(s, strict=1))
|
| 568 |
+
except OverflowError:
|
| 569 |
+
# We must unfortunately sacrifice compatibility with ints here.
|
| 570 |
+
# We could do hash(man << exp) when the exponent is positive, but
|
| 571 |
+
# this would cause unreasonable inefficiency for large numbers.
|
| 572 |
+
return hash(s)
|
| 573 |
+
|
| 574 |
+
def mpf_cmp(s, t):
|
| 575 |
+
"""Compare the raw mpfs s and t. Return -1 if s < t, 0 if s == t,
|
| 576 |
+
and 1 if s > t. (Same convention as Python's cmp() function.)"""
|
| 577 |
+
|
| 578 |
+
# In principle, a comparison amounts to determining the sign of s-t.
|
| 579 |
+
# A full subtraction is relatively slow, however, so we first try to
|
| 580 |
+
# look at the components.
|
| 581 |
+
ssign, sman, sexp, sbc = s
|
| 582 |
+
tsign, tman, texp, tbc = t
|
| 583 |
+
|
| 584 |
+
# Handle zeros and special numbers
|
| 585 |
+
if not sman or not tman:
|
| 586 |
+
if s == fzero: return -mpf_sign(t)
|
| 587 |
+
if t == fzero: return mpf_sign(s)
|
| 588 |
+
if s == t: return 0
|
| 589 |
+
# Follow same convention as Python's cmp for float nan
|
| 590 |
+
if t == fnan: return 1
|
| 591 |
+
if s == finf: return 1
|
| 592 |
+
if t == fninf: return 1
|
| 593 |
+
return -1
|
| 594 |
+
# Different sides of zero
|
| 595 |
+
if ssign != tsign:
|
| 596 |
+
if not ssign: return 1
|
| 597 |
+
return -1
|
| 598 |
+
# This reduces to direct integer comparison
|
| 599 |
+
if sexp == texp:
|
| 600 |
+
if sman == tman:
|
| 601 |
+
return 0
|
| 602 |
+
if sman > tman:
|
| 603 |
+
if ssign: return -1
|
| 604 |
+
else: return 1
|
| 605 |
+
else:
|
| 606 |
+
if ssign: return 1
|
| 607 |
+
else: return -1
|
| 608 |
+
# Check position of the highest set bit in each number. If
|
| 609 |
+
# different, there is certainly an inequality.
|
| 610 |
+
a = sbc + sexp
|
| 611 |
+
b = tbc + texp
|
| 612 |
+
if ssign:
|
| 613 |
+
if a < b: return 1
|
| 614 |
+
if a > b: return -1
|
| 615 |
+
else:
|
| 616 |
+
if a < b: return -1
|
| 617 |
+
if a > b: return 1
|
| 618 |
+
|
| 619 |
+
# Both numbers have the same highest bit. Subtract to find
|
| 620 |
+
# how the lower bits compare.
|
| 621 |
+
delta = mpf_sub(s, t, 5, round_floor)
|
| 622 |
+
if delta[0]:
|
| 623 |
+
return -1
|
| 624 |
+
return 1
|
| 625 |
+
|
| 626 |
+
def mpf_lt(s, t):
|
| 627 |
+
if s == fnan or t == fnan:
|
| 628 |
+
return False
|
| 629 |
+
return mpf_cmp(s, t) < 0
|
| 630 |
+
|
| 631 |
+
def mpf_le(s, t):
|
| 632 |
+
if s == fnan or t == fnan:
|
| 633 |
+
return False
|
| 634 |
+
return mpf_cmp(s, t) <= 0
|
| 635 |
+
|
| 636 |
+
def mpf_gt(s, t):
|
| 637 |
+
if s == fnan or t == fnan:
|
| 638 |
+
return False
|
| 639 |
+
return mpf_cmp(s, t) > 0
|
| 640 |
+
|
| 641 |
+
def mpf_ge(s, t):
|
| 642 |
+
if s == fnan or t == fnan:
|
| 643 |
+
return False
|
| 644 |
+
return mpf_cmp(s, t) >= 0
|
| 645 |
+
|
| 646 |
+
def mpf_min_max(seq):
|
| 647 |
+
min = max = seq[0]
|
| 648 |
+
for x in seq[1:]:
|
| 649 |
+
if mpf_lt(x, min): min = x
|
| 650 |
+
if mpf_gt(x, max): max = x
|
| 651 |
+
return min, max
|
| 652 |
+
|
| 653 |
+
def mpf_pos(s, prec=0, rnd=round_fast):
|
| 654 |
+
"""Calculate 0+s for a raw mpf (i.e., just round s to the specified
|
| 655 |
+
precision)."""
|
| 656 |
+
if prec:
|
| 657 |
+
sign, man, exp, bc = s
|
| 658 |
+
if (not man) and exp:
|
| 659 |
+
return s
|
| 660 |
+
return normalize1(sign, man, exp, bc, prec, rnd)
|
| 661 |
+
return s
|
| 662 |
+
|
| 663 |
+
def mpf_neg(s, prec=None, rnd=round_fast):
|
| 664 |
+
"""Negate a raw mpf (return -s), rounding the result to the
|
| 665 |
+
specified precision. The prec argument can be omitted to do the
|
| 666 |
+
operation exactly."""
|
| 667 |
+
sign, man, exp, bc = s
|
| 668 |
+
if not man:
|
| 669 |
+
if exp:
|
| 670 |
+
if s == finf: return fninf
|
| 671 |
+
if s == fninf: return finf
|
| 672 |
+
return s
|
| 673 |
+
if not prec:
|
| 674 |
+
return (1-sign, man, exp, bc)
|
| 675 |
+
return normalize1(1-sign, man, exp, bc, prec, rnd)
|
| 676 |
+
|
| 677 |
+
def mpf_abs(s, prec=None, rnd=round_fast):
|
| 678 |
+
"""Return abs(s) of the raw mpf s, rounded to the specified
|
| 679 |
+
precision. The prec argument can be omitted to generate an
|
| 680 |
+
exact result."""
|
| 681 |
+
sign, man, exp, bc = s
|
| 682 |
+
if (not man) and exp:
|
| 683 |
+
if s == fninf:
|
| 684 |
+
return finf
|
| 685 |
+
return s
|
| 686 |
+
if not prec:
|
| 687 |
+
if sign:
|
| 688 |
+
return (0, man, exp, bc)
|
| 689 |
+
return s
|
| 690 |
+
return normalize1(0, man, exp, bc, prec, rnd)
|
| 691 |
+
|
| 692 |
+
def mpf_sign(s):
|
| 693 |
+
"""Return -1, 0, or 1 (as a Python int, not a raw mpf) depending on
|
| 694 |
+
whether s is negative, zero, or positive. (Nan is taken to give 0.)"""
|
| 695 |
+
sign, man, exp, bc = s
|
| 696 |
+
if not man:
|
| 697 |
+
if s == finf: return 1
|
| 698 |
+
if s == fninf: return -1
|
| 699 |
+
return 0
|
| 700 |
+
return (-1) ** sign
|
| 701 |
+
|
| 702 |
+
def mpf_add(s, t, prec=0, rnd=round_fast, _sub=0):
|
| 703 |
+
"""
|
| 704 |
+
Add the two raw mpf values s and t.
|
| 705 |
+
|
| 706 |
+
With prec=0, no rounding is performed. Note that this can
|
| 707 |
+
produce a very large mantissa (potentially too large to fit
|
| 708 |
+
in memory) if exponents are far apart.
|
| 709 |
+
"""
|
| 710 |
+
ssign, sman, sexp, sbc = s
|
| 711 |
+
tsign, tman, texp, tbc = t
|
| 712 |
+
tsign ^= _sub
|
| 713 |
+
# Standard case: two nonzero, regular numbers
|
| 714 |
+
if sman and tman:
|
| 715 |
+
offset = sexp - texp
|
| 716 |
+
if offset:
|
| 717 |
+
if offset > 0:
|
| 718 |
+
# Outside precision range; only need to perturb
|
| 719 |
+
if offset > 100 and prec:
|
| 720 |
+
delta = sbc + sexp - tbc - texp
|
| 721 |
+
if delta > prec + 4:
|
| 722 |
+
offset = prec + 4
|
| 723 |
+
sman <<= offset
|
| 724 |
+
if tsign == ssign: sman += 1
|
| 725 |
+
else: sman -= 1
|
| 726 |
+
return normalize1(ssign, sman, sexp-offset,
|
| 727 |
+
bitcount(sman), prec, rnd)
|
| 728 |
+
# Add
|
| 729 |
+
if ssign == tsign:
|
| 730 |
+
man = tman + (sman << offset)
|
| 731 |
+
# Subtract
|
| 732 |
+
else:
|
| 733 |
+
if ssign: man = tman - (sman << offset)
|
| 734 |
+
else: man = (sman << offset) - tman
|
| 735 |
+
if man >= 0:
|
| 736 |
+
ssign = 0
|
| 737 |
+
else:
|
| 738 |
+
man = -man
|
| 739 |
+
ssign = 1
|
| 740 |
+
bc = bitcount(man)
|
| 741 |
+
return normalize1(ssign, man, texp, bc, prec or bc, rnd)
|
| 742 |
+
elif offset < 0:
|
| 743 |
+
# Outside precision range; only need to perturb
|
| 744 |
+
if offset < -100 and prec:
|
| 745 |
+
delta = tbc + texp - sbc - sexp
|
| 746 |
+
if delta > prec + 4:
|
| 747 |
+
offset = prec + 4
|
| 748 |
+
tman <<= offset
|
| 749 |
+
if ssign == tsign: tman += 1
|
| 750 |
+
else: tman -= 1
|
| 751 |
+
return normalize1(tsign, tman, texp-offset,
|
| 752 |
+
bitcount(tman), prec, rnd)
|
| 753 |
+
# Add
|
| 754 |
+
if ssign == tsign:
|
| 755 |
+
man = sman + (tman << -offset)
|
| 756 |
+
# Subtract
|
| 757 |
+
else:
|
| 758 |
+
if tsign: man = sman - (tman << -offset)
|
| 759 |
+
else: man = (tman << -offset) - sman
|
| 760 |
+
if man >= 0:
|
| 761 |
+
ssign = 0
|
| 762 |
+
else:
|
| 763 |
+
man = -man
|
| 764 |
+
ssign = 1
|
| 765 |
+
bc = bitcount(man)
|
| 766 |
+
return normalize1(ssign, man, sexp, bc, prec or bc, rnd)
|
| 767 |
+
# Equal exponents; no shifting necessary
|
| 768 |
+
if ssign == tsign:
|
| 769 |
+
man = tman + sman
|
| 770 |
+
else:
|
| 771 |
+
if ssign: man = tman - sman
|
| 772 |
+
else: man = sman - tman
|
| 773 |
+
if man >= 0:
|
| 774 |
+
ssign = 0
|
| 775 |
+
else:
|
| 776 |
+
man = -man
|
| 777 |
+
ssign = 1
|
| 778 |
+
bc = bitcount(man)
|
| 779 |
+
return normalize(ssign, man, texp, bc, prec or bc, rnd)
|
| 780 |
+
# Handle zeros and special numbers
|
| 781 |
+
if _sub:
|
| 782 |
+
t = mpf_neg(t)
|
| 783 |
+
if not sman:
|
| 784 |
+
if sexp:
|
| 785 |
+
if s == t or tman or not texp:
|
| 786 |
+
return s
|
| 787 |
+
return fnan
|
| 788 |
+
if tman:
|
| 789 |
+
return normalize1(tsign, tman, texp, tbc, prec or tbc, rnd)
|
| 790 |
+
return t
|
| 791 |
+
if texp:
|
| 792 |
+
return t
|
| 793 |
+
if sman:
|
| 794 |
+
return normalize1(ssign, sman, sexp, sbc, prec or sbc, rnd)
|
| 795 |
+
return s
|
| 796 |
+
|
| 797 |
+
def mpf_sub(s, t, prec=0, rnd=round_fast):
|
| 798 |
+
"""Return the difference of two raw mpfs, s-t. This function is
|
| 799 |
+
simply a wrapper of mpf_add that changes the sign of t."""
|
| 800 |
+
return mpf_add(s, t, prec, rnd, 1)
|
| 801 |
+
|
| 802 |
+
def mpf_sum(xs, prec=0, rnd=round_fast, absolute=False):
|
| 803 |
+
"""
|
| 804 |
+
Sum a list of mpf values efficiently and accurately
|
| 805 |
+
(typically no temporary roundoff occurs). If prec=0,
|
| 806 |
+
the final result will not be rounded either.
|
| 807 |
+
|
| 808 |
+
There may be roundoff error or cancellation if extremely
|
| 809 |
+
large exponent differences occur.
|
| 810 |
+
|
| 811 |
+
With absolute=True, sums the absolute values.
|
| 812 |
+
"""
|
| 813 |
+
man = 0
|
| 814 |
+
exp = 0
|
| 815 |
+
max_extra_prec = prec*2 or 1000000 # XXX
|
| 816 |
+
special = None
|
| 817 |
+
for x in xs:
|
| 818 |
+
xsign, xman, xexp, xbc = x
|
| 819 |
+
if xman:
|
| 820 |
+
if xsign and not absolute:
|
| 821 |
+
xman = -xman
|
| 822 |
+
delta = xexp - exp
|
| 823 |
+
if xexp >= exp:
|
| 824 |
+
# x much larger than existing sum?
|
| 825 |
+
# first: quick test
|
| 826 |
+
if (delta > max_extra_prec) and \
|
| 827 |
+
((not man) or delta-bitcount(abs(man)) > max_extra_prec):
|
| 828 |
+
man = xman
|
| 829 |
+
exp = xexp
|
| 830 |
+
else:
|
| 831 |
+
man += (xman << delta)
|
| 832 |
+
else:
|
| 833 |
+
delta = -delta
|
| 834 |
+
# x much smaller than existing sum?
|
| 835 |
+
if delta-xbc > max_extra_prec:
|
| 836 |
+
if not man:
|
| 837 |
+
man, exp = xman, xexp
|
| 838 |
+
else:
|
| 839 |
+
man = (man << delta) + xman
|
| 840 |
+
exp = xexp
|
| 841 |
+
elif xexp:
|
| 842 |
+
if absolute:
|
| 843 |
+
x = mpf_abs(x)
|
| 844 |
+
special = mpf_add(special or fzero, x, 1)
|
| 845 |
+
# Will be inf or nan
|
| 846 |
+
if special:
|
| 847 |
+
return special
|
| 848 |
+
return from_man_exp(man, exp, prec, rnd)
|
| 849 |
+
|
| 850 |
+
def gmpy_mpf_mul(s, t, prec=0, rnd=round_fast):
|
| 851 |
+
"""Multiply two raw mpfs"""
|
| 852 |
+
ssign, sman, sexp, sbc = s
|
| 853 |
+
tsign, tman, texp, tbc = t
|
| 854 |
+
sign = ssign ^ tsign
|
| 855 |
+
man = sman*tman
|
| 856 |
+
if man:
|
| 857 |
+
bc = bitcount(man)
|
| 858 |
+
if prec:
|
| 859 |
+
return normalize1(sign, man, sexp+texp, bc, prec, rnd)
|
| 860 |
+
else:
|
| 861 |
+
return (sign, man, sexp+texp, bc)
|
| 862 |
+
s_special = (not sman) and sexp
|
| 863 |
+
t_special = (not tman) and texp
|
| 864 |
+
if not s_special and not t_special:
|
| 865 |
+
return fzero
|
| 866 |
+
if fnan in (s, t): return fnan
|
| 867 |
+
if (not tman) and texp: s, t = t, s
|
| 868 |
+
if t == fzero: return fnan
|
| 869 |
+
return {1:finf, -1:fninf}[mpf_sign(s) * mpf_sign(t)]
|
| 870 |
+
|
| 871 |
+
def gmpy_mpf_mul_int(s, n, prec, rnd=round_fast):
|
| 872 |
+
"""Multiply by a Python integer."""
|
| 873 |
+
sign, man, exp, bc = s
|
| 874 |
+
if not man:
|
| 875 |
+
return mpf_mul(s, from_int(n), prec, rnd)
|
| 876 |
+
if not n:
|
| 877 |
+
return fzero
|
| 878 |
+
if n < 0:
|
| 879 |
+
sign ^= 1
|
| 880 |
+
n = -n
|
| 881 |
+
man *= n
|
| 882 |
+
return normalize(sign, man, exp, bitcount(man), prec, rnd)
|
| 883 |
+
|
| 884 |
+
def python_mpf_mul(s, t, prec=0, rnd=round_fast):
|
| 885 |
+
"""Multiply two raw mpfs"""
|
| 886 |
+
ssign, sman, sexp, sbc = s
|
| 887 |
+
tsign, tman, texp, tbc = t
|
| 888 |
+
sign = ssign ^ tsign
|
| 889 |
+
man = sman*tman
|
| 890 |
+
if man:
|
| 891 |
+
bc = sbc + tbc - 1
|
| 892 |
+
bc += int(man>>bc)
|
| 893 |
+
if prec:
|
| 894 |
+
return normalize1(sign, man, sexp+texp, bc, prec, rnd)
|
| 895 |
+
else:
|
| 896 |
+
return (sign, man, sexp+texp, bc)
|
| 897 |
+
s_special = (not sman) and sexp
|
| 898 |
+
t_special = (not tman) and texp
|
| 899 |
+
if not s_special and not t_special:
|
| 900 |
+
return fzero
|
| 901 |
+
if fnan in (s, t): return fnan
|
| 902 |
+
if (not tman) and texp: s, t = t, s
|
| 903 |
+
if t == fzero: return fnan
|
| 904 |
+
return {1:finf, -1:fninf}[mpf_sign(s) * mpf_sign(t)]
|
| 905 |
+
|
| 906 |
+
def python_mpf_mul_int(s, n, prec, rnd=round_fast):
|
| 907 |
+
"""Multiply by a Python integer."""
|
| 908 |
+
sign, man, exp, bc = s
|
| 909 |
+
if not man:
|
| 910 |
+
return mpf_mul(s, from_int(n), prec, rnd)
|
| 911 |
+
if not n:
|
| 912 |
+
return fzero
|
| 913 |
+
if n < 0:
|
| 914 |
+
sign ^= 1
|
| 915 |
+
n = -n
|
| 916 |
+
man *= n
|
| 917 |
+
# Generally n will be small
|
| 918 |
+
if n < 1024:
|
| 919 |
+
bc += bctable[int(n)] - 1
|
| 920 |
+
else:
|
| 921 |
+
bc += bitcount(n) - 1
|
| 922 |
+
bc += int(man>>bc)
|
| 923 |
+
return normalize(sign, man, exp, bc, prec, rnd)
|
| 924 |
+
|
| 925 |
+
|
| 926 |
+
if BACKEND == 'gmpy':
|
| 927 |
+
mpf_mul = gmpy_mpf_mul
|
| 928 |
+
mpf_mul_int = gmpy_mpf_mul_int
|
| 929 |
+
else:
|
| 930 |
+
mpf_mul = python_mpf_mul
|
| 931 |
+
mpf_mul_int = python_mpf_mul_int
|
| 932 |
+
|
| 933 |
+
def mpf_shift(s, n):
|
| 934 |
+
"""Quickly multiply the raw mpf s by 2**n without rounding."""
|
| 935 |
+
sign, man, exp, bc = s
|
| 936 |
+
if not man:
|
| 937 |
+
return s
|
| 938 |
+
return sign, man, exp+n, bc
|
| 939 |
+
|
| 940 |
+
def mpf_frexp(x):
|
| 941 |
+
"""Convert x = y*2**n to (y, n) with abs(y) in [0.5, 1) if nonzero"""
|
| 942 |
+
sign, man, exp, bc = x
|
| 943 |
+
if not man:
|
| 944 |
+
if x == fzero:
|
| 945 |
+
return (fzero, 0)
|
| 946 |
+
else:
|
| 947 |
+
raise ValueError
|
| 948 |
+
return mpf_shift(x, -bc-exp), bc+exp
|
| 949 |
+
|
| 950 |
+
def mpf_div(s, t, prec, rnd=round_fast):
|
| 951 |
+
"""Floating-point division"""
|
| 952 |
+
ssign, sman, sexp, sbc = s
|
| 953 |
+
tsign, tman, texp, tbc = t
|
| 954 |
+
if not sman or not tman:
|
| 955 |
+
if s == fzero:
|
| 956 |
+
if t == fzero: raise ZeroDivisionError
|
| 957 |
+
if t == fnan: return fnan
|
| 958 |
+
return fzero
|
| 959 |
+
if t == fzero:
|
| 960 |
+
raise ZeroDivisionError
|
| 961 |
+
s_special = (not sman) and sexp
|
| 962 |
+
t_special = (not tman) and texp
|
| 963 |
+
if s_special and t_special:
|
| 964 |
+
return fnan
|
| 965 |
+
if s == fnan or t == fnan:
|
| 966 |
+
return fnan
|
| 967 |
+
if not t_special:
|
| 968 |
+
if t == fzero:
|
| 969 |
+
return fnan
|
| 970 |
+
return {1:finf, -1:fninf}[mpf_sign(s) * mpf_sign(t)]
|
| 971 |
+
return fzero
|
| 972 |
+
sign = ssign ^ tsign
|
| 973 |
+
if tman == 1:
|
| 974 |
+
return normalize1(sign, sman, sexp-texp, sbc, prec, rnd)
|
| 975 |
+
# Same strategy as for addition: if there is a remainder, perturb
|
| 976 |
+
# the result a few bits outside the precision range before rounding
|
| 977 |
+
extra = prec - sbc + tbc + 5
|
| 978 |
+
if extra < 5:
|
| 979 |
+
extra = 5
|
| 980 |
+
quot, rem = divmod(sman<<extra, tman)
|
| 981 |
+
if rem:
|
| 982 |
+
quot = (quot<<1) + 1
|
| 983 |
+
extra += 1
|
| 984 |
+
return normalize1(sign, quot, sexp-texp-extra, bitcount(quot), prec, rnd)
|
| 985 |
+
return normalize(sign, quot, sexp-texp-extra, bitcount(quot), prec, rnd)
|
| 986 |
+
|
| 987 |
+
def mpf_rdiv_int(n, t, prec, rnd=round_fast):
|
| 988 |
+
"""Floating-point division n/t with a Python integer as numerator"""
|
| 989 |
+
sign, man, exp, bc = t
|
| 990 |
+
if not n or not man:
|
| 991 |
+
return mpf_div(from_int(n), t, prec, rnd)
|
| 992 |
+
if n < 0:
|
| 993 |
+
sign ^= 1
|
| 994 |
+
n = -n
|
| 995 |
+
extra = prec + bc + 5
|
| 996 |
+
quot, rem = divmod(n<<extra, man)
|
| 997 |
+
if rem:
|
| 998 |
+
quot = (quot<<1) + 1
|
| 999 |
+
extra += 1
|
| 1000 |
+
return normalize1(sign, quot, -exp-extra, bitcount(quot), prec, rnd)
|
| 1001 |
+
return normalize(sign, quot, -exp-extra, bitcount(quot), prec, rnd)
|
| 1002 |
+
|
| 1003 |
+
def mpf_mod(s, t, prec, rnd=round_fast):
|
| 1004 |
+
ssign, sman, sexp, sbc = s
|
| 1005 |
+
tsign, tman, texp, tbc = t
|
| 1006 |
+
if ((not sman) and sexp) or ((not tman) and texp):
|
| 1007 |
+
return fnan
|
| 1008 |
+
# Important special case: do nothing if t is larger
|
| 1009 |
+
if ssign == tsign and texp > sexp+sbc:
|
| 1010 |
+
return s
|
| 1011 |
+
# Another important special case: this allows us to do e.g. x % 1.0
|
| 1012 |
+
# to find the fractional part of x, and it will work when x is huge.
|
| 1013 |
+
if tman == 1 and sexp > texp+tbc:
|
| 1014 |
+
return fzero
|
| 1015 |
+
base = min(sexp, texp)
|
| 1016 |
+
sman = (-1)**ssign * sman
|
| 1017 |
+
tman = (-1)**tsign * tman
|
| 1018 |
+
man = (sman << (sexp-base)) % (tman << (texp-base))
|
| 1019 |
+
if man >= 0:
|
| 1020 |
+
sign = 0
|
| 1021 |
+
else:
|
| 1022 |
+
man = -man
|
| 1023 |
+
sign = 1
|
| 1024 |
+
return normalize(sign, man, base, bitcount(man), prec, rnd)
|
| 1025 |
+
|
| 1026 |
+
reciprocal_rnd = {
|
| 1027 |
+
round_down : round_up,
|
| 1028 |
+
round_up : round_down,
|
| 1029 |
+
round_floor : round_ceiling,
|
| 1030 |
+
round_ceiling : round_floor,
|
| 1031 |
+
round_nearest : round_nearest
|
| 1032 |
+
}
|
| 1033 |
+
|
| 1034 |
+
negative_rnd = {
|
| 1035 |
+
round_down : round_down,
|
| 1036 |
+
round_up : round_up,
|
| 1037 |
+
round_floor : round_ceiling,
|
| 1038 |
+
round_ceiling : round_floor,
|
| 1039 |
+
round_nearest : round_nearest
|
| 1040 |
+
}
|
| 1041 |
+
|
| 1042 |
+
def mpf_pow_int(s, n, prec, rnd=round_fast):
|
| 1043 |
+
"""Compute s**n, where s is a raw mpf and n is a Python integer."""
|
| 1044 |
+
sign, man, exp, bc = s
|
| 1045 |
+
|
| 1046 |
+
if (not man) and exp:
|
| 1047 |
+
if s == finf:
|
| 1048 |
+
if n > 0: return s
|
| 1049 |
+
if n == 0: return fnan
|
| 1050 |
+
return fzero
|
| 1051 |
+
if s == fninf:
|
| 1052 |
+
if n > 0: return [finf, fninf][n & 1]
|
| 1053 |
+
if n == 0: return fnan
|
| 1054 |
+
return fzero
|
| 1055 |
+
return fnan
|
| 1056 |
+
|
| 1057 |
+
n = int(n)
|
| 1058 |
+
if n == 0: return fone
|
| 1059 |
+
if n == 1: return mpf_pos(s, prec, rnd)
|
| 1060 |
+
if n == 2:
|
| 1061 |
+
_, man, exp, bc = s
|
| 1062 |
+
if not man:
|
| 1063 |
+
return fzero
|
| 1064 |
+
man = man*man
|
| 1065 |
+
if man == 1:
|
| 1066 |
+
return (0, MPZ_ONE, exp+exp, 1)
|
| 1067 |
+
bc = bc + bc - 2
|
| 1068 |
+
bc += bctable[int(man>>bc)]
|
| 1069 |
+
return normalize1(0, man, exp+exp, bc, prec, rnd)
|
| 1070 |
+
if n == -1: return mpf_div(fone, s, prec, rnd)
|
| 1071 |
+
if n < 0:
|
| 1072 |
+
inverse = mpf_pow_int(s, -n, prec+5, reciprocal_rnd[rnd])
|
| 1073 |
+
return mpf_div(fone, inverse, prec, rnd)
|
| 1074 |
+
|
| 1075 |
+
result_sign = sign & n
|
| 1076 |
+
|
| 1077 |
+
# Use exact integer power when the exact mantissa is small
|
| 1078 |
+
if man == 1:
|
| 1079 |
+
return (result_sign, MPZ_ONE, exp*n, 1)
|
| 1080 |
+
if bc*n < 1000:
|
| 1081 |
+
man **= n
|
| 1082 |
+
return normalize1(result_sign, man, exp*n, bitcount(man), prec, rnd)
|
| 1083 |
+
|
| 1084 |
+
# Use directed rounding all the way through to maintain rigorous
|
| 1085 |
+
# bounds for interval arithmetic
|
| 1086 |
+
rounds_down = (rnd == round_nearest) or \
|
| 1087 |
+
shifts_down[rnd][result_sign]
|
| 1088 |
+
|
| 1089 |
+
# Now we perform binary exponentiation. Need to estimate precision
|
| 1090 |
+
# to avoid rounding errors from temporary operations. Roughly log_2(n)
|
| 1091 |
+
# operations are performed.
|
| 1092 |
+
workprec = prec + 4*bitcount(n) + 4
|
| 1093 |
+
_, pm, pe, pbc = fone
|
| 1094 |
+
while 1:
|
| 1095 |
+
if n & 1:
|
| 1096 |
+
pm = pm*man
|
| 1097 |
+
pe = pe+exp
|
| 1098 |
+
pbc += bc - 2
|
| 1099 |
+
pbc = pbc + bctable[int(pm >> pbc)]
|
| 1100 |
+
if pbc > workprec:
|
| 1101 |
+
if rounds_down:
|
| 1102 |
+
pm = pm >> (pbc-workprec)
|
| 1103 |
+
else:
|
| 1104 |
+
pm = -((-pm) >> (pbc-workprec))
|
| 1105 |
+
pe += pbc - workprec
|
| 1106 |
+
pbc = workprec
|
| 1107 |
+
n -= 1
|
| 1108 |
+
if not n:
|
| 1109 |
+
break
|
| 1110 |
+
man = man*man
|
| 1111 |
+
exp = exp+exp
|
| 1112 |
+
bc = bc + bc - 2
|
| 1113 |
+
bc = bc + bctable[int(man >> bc)]
|
| 1114 |
+
if bc > workprec:
|
| 1115 |
+
if rounds_down:
|
| 1116 |
+
man = man >> (bc-workprec)
|
| 1117 |
+
else:
|
| 1118 |
+
man = -((-man) >> (bc-workprec))
|
| 1119 |
+
exp += bc - workprec
|
| 1120 |
+
bc = workprec
|
| 1121 |
+
n = n // 2
|
| 1122 |
+
|
| 1123 |
+
return normalize(result_sign, pm, pe, pbc, prec, rnd)
|
| 1124 |
+
|
| 1125 |
+
|
| 1126 |
+
def mpf_perturb(x, eps_sign, prec, rnd):
|
| 1127 |
+
"""
|
| 1128 |
+
For nonzero x, calculate x + eps with directed rounding, where
|
| 1129 |
+
eps < prec relatively and eps has the given sign (0 for
|
| 1130 |
+
positive, 1 for negative).
|
| 1131 |
+
|
| 1132 |
+
With rounding to nearest, this is taken to simply normalize
|
| 1133 |
+
x to the given precision.
|
| 1134 |
+
"""
|
| 1135 |
+
if rnd == round_nearest:
|
| 1136 |
+
return mpf_pos(x, prec, rnd)
|
| 1137 |
+
sign, man, exp, bc = x
|
| 1138 |
+
eps = (eps_sign, MPZ_ONE, exp+bc-prec-1, 1)
|
| 1139 |
+
if sign:
|
| 1140 |
+
away = (rnd in (round_down, round_ceiling)) ^ eps_sign
|
| 1141 |
+
else:
|
| 1142 |
+
away = (rnd in (round_up, round_ceiling)) ^ eps_sign
|
| 1143 |
+
if away:
|
| 1144 |
+
return mpf_add(x, eps, prec, rnd)
|
| 1145 |
+
else:
|
| 1146 |
+
return mpf_pos(x, prec, rnd)
|
| 1147 |
+
|
| 1148 |
+
|
| 1149 |
+
#----------------------------------------------------------------------------#
|
| 1150 |
+
# Radix conversion #
|
| 1151 |
+
#----------------------------------------------------------------------------#
|
| 1152 |
+
|
| 1153 |
+
def to_digits_exp(s, dps):
|
| 1154 |
+
"""Helper function for representing the floating-point number s as
|
| 1155 |
+
a decimal with dps digits. Returns (sign, string, exponent) where
|
| 1156 |
+
sign is '' or '-', string is the digit string, and exponent is
|
| 1157 |
+
the decimal exponent as an int.
|
| 1158 |
+
|
| 1159 |
+
If inexact, the decimal representation is rounded toward zero."""
|
| 1160 |
+
|
| 1161 |
+
# Extract sign first so it doesn't mess up the string digit count
|
| 1162 |
+
if s[0]:
|
| 1163 |
+
sign = '-'
|
| 1164 |
+
s = mpf_neg(s)
|
| 1165 |
+
else:
|
| 1166 |
+
sign = ''
|
| 1167 |
+
_sign, man, exp, bc = s
|
| 1168 |
+
|
| 1169 |
+
if not man:
|
| 1170 |
+
return '', '0', 0
|
| 1171 |
+
|
| 1172 |
+
bitprec = int(dps * math.log(10,2)) + 10
|
| 1173 |
+
|
| 1174 |
+
# Cut down to size
|
| 1175 |
+
# TODO: account for precision when doing this
|
| 1176 |
+
exp_from_1 = exp + bc
|
| 1177 |
+
if abs(exp_from_1) > 3500:
|
| 1178 |
+
from .libelefun import mpf_ln2, mpf_ln10
|
| 1179 |
+
# Set b = int(exp * log(2)/log(10))
|
| 1180 |
+
# If exp is huge, we must use high-precision arithmetic to
|
| 1181 |
+
# find the nearest power of ten
|
| 1182 |
+
expprec = bitcount(abs(exp)) + 5
|
| 1183 |
+
tmp = from_int(exp)
|
| 1184 |
+
tmp = mpf_mul(tmp, mpf_ln2(expprec))
|
| 1185 |
+
tmp = mpf_div(tmp, mpf_ln10(expprec), expprec)
|
| 1186 |
+
b = to_int(tmp)
|
| 1187 |
+
s = mpf_div(s, mpf_pow_int(ften, b, bitprec), bitprec)
|
| 1188 |
+
_sign, man, exp, bc = s
|
| 1189 |
+
exponent = b
|
| 1190 |
+
else:
|
| 1191 |
+
exponent = 0
|
| 1192 |
+
|
| 1193 |
+
# First, calculate mantissa digits by converting to a binary
|
| 1194 |
+
# fixed-point number and then converting that number to
|
| 1195 |
+
# a decimal fixed-point number.
|
| 1196 |
+
fixprec = max(bitprec - exp - bc, 0)
|
| 1197 |
+
fixdps = int(fixprec / math.log(10,2) + 0.5)
|
| 1198 |
+
sf = to_fixed(s, fixprec)
|
| 1199 |
+
sd = bin_to_radix(sf, fixprec, 10, fixdps)
|
| 1200 |
+
digits = numeral(sd, base=10, size=dps)
|
| 1201 |
+
|
| 1202 |
+
exponent += len(digits) - fixdps - 1
|
| 1203 |
+
return sign, digits, exponent
|
| 1204 |
+
|
| 1205 |
+
def to_str(s, dps, strip_zeros=True, min_fixed=None, max_fixed=None,
|
| 1206 |
+
show_zero_exponent=False):
|
| 1207 |
+
"""
|
| 1208 |
+
Convert a raw mpf to a decimal floating-point literal with at
|
| 1209 |
+
most `dps` decimal digits in the mantissa (not counting extra zeros
|
| 1210 |
+
that may be inserted for visual purposes).
|
| 1211 |
+
|
| 1212 |
+
The number will be printed in fixed-point format if the position
|
| 1213 |
+
of the leading digit is strictly between min_fixed
|
| 1214 |
+
(default = min(-dps/3,-5)) and max_fixed (default = dps).
|
| 1215 |
+
|
| 1216 |
+
To force fixed-point format always, set min_fixed = -inf,
|
| 1217 |
+
max_fixed = +inf. To force floating-point format, set
|
| 1218 |
+
min_fixed >= max_fixed.
|
| 1219 |
+
|
| 1220 |
+
The literal is formatted so that it can be parsed back to a number
|
| 1221 |
+
by to_str, float() or Decimal().
|
| 1222 |
+
"""
|
| 1223 |
+
|
| 1224 |
+
# Special numbers
|
| 1225 |
+
if not s[1]:
|
| 1226 |
+
if s == fzero:
|
| 1227 |
+
if dps: t = '0.0'
|
| 1228 |
+
else: t = '.0'
|
| 1229 |
+
if show_zero_exponent:
|
| 1230 |
+
t += 'e+0'
|
| 1231 |
+
return t
|
| 1232 |
+
if s == finf: return '+inf'
|
| 1233 |
+
if s == fninf: return '-inf'
|
| 1234 |
+
if s == fnan: return 'nan'
|
| 1235 |
+
raise ValueError
|
| 1236 |
+
|
| 1237 |
+
if min_fixed is None: min_fixed = min(-(dps//3), -5)
|
| 1238 |
+
if max_fixed is None: max_fixed = dps
|
| 1239 |
+
|
| 1240 |
+
# to_digits_exp rounds to floor.
|
| 1241 |
+
# This sometimes kills some instances of "...00001"
|
| 1242 |
+
sign, digits, exponent = to_digits_exp(s, dps+3)
|
| 1243 |
+
|
| 1244 |
+
# No digits: show only .0; round exponent to nearest
|
| 1245 |
+
if not dps:
|
| 1246 |
+
if digits[0] in '56789':
|
| 1247 |
+
exponent += 1
|
| 1248 |
+
digits = ".0"
|
| 1249 |
+
|
| 1250 |
+
else:
|
| 1251 |
+
# Rounding up kills some instances of "...99999"
|
| 1252 |
+
if len(digits) > dps and digits[dps] in '56789':
|
| 1253 |
+
digits = digits[:dps]
|
| 1254 |
+
i = dps - 1
|
| 1255 |
+
while i >= 0 and digits[i] == '9':
|
| 1256 |
+
i -= 1
|
| 1257 |
+
if i >= 0:
|
| 1258 |
+
digits = digits[:i] + str(int(digits[i]) + 1) + '0' * (dps - i - 1)
|
| 1259 |
+
else:
|
| 1260 |
+
digits = '1' + '0' * (dps - 1)
|
| 1261 |
+
exponent += 1
|
| 1262 |
+
else:
|
| 1263 |
+
digits = digits[:dps]
|
| 1264 |
+
|
| 1265 |
+
# Prettify numbers close to unit magnitude
|
| 1266 |
+
if min_fixed < exponent < max_fixed:
|
| 1267 |
+
if exponent < 0:
|
| 1268 |
+
digits = ("0"*int(-exponent)) + digits
|
| 1269 |
+
split = 1
|
| 1270 |
+
else:
|
| 1271 |
+
split = exponent + 1
|
| 1272 |
+
if split > dps:
|
| 1273 |
+
digits += "0"*(split-dps)
|
| 1274 |
+
exponent = 0
|
| 1275 |
+
else:
|
| 1276 |
+
split = 1
|
| 1277 |
+
|
| 1278 |
+
digits = (digits[:split] + "." + digits[split:])
|
| 1279 |
+
|
| 1280 |
+
if strip_zeros:
|
| 1281 |
+
# Clean up trailing zeros
|
| 1282 |
+
digits = digits.rstrip('0')
|
| 1283 |
+
if digits[-1] == ".":
|
| 1284 |
+
digits += "0"
|
| 1285 |
+
|
| 1286 |
+
if exponent == 0 and dps and not show_zero_exponent: return sign + digits
|
| 1287 |
+
if exponent >= 0: return sign + digits + "e+" + str(exponent)
|
| 1288 |
+
if exponent < 0: return sign + digits + "e" + str(exponent)
|
| 1289 |
+
|
| 1290 |
+
def str_to_man_exp(x, base=10):
|
| 1291 |
+
"""Helper function for from_str."""
|
| 1292 |
+
x = x.lower().rstrip('l')
|
| 1293 |
+
# Verify that the input is a valid float literal
|
| 1294 |
+
float(x)
|
| 1295 |
+
# Split into mantissa, exponent
|
| 1296 |
+
parts = x.split('e')
|
| 1297 |
+
if len(parts) == 1:
|
| 1298 |
+
exp = 0
|
| 1299 |
+
else: # == 2
|
| 1300 |
+
x = parts[0]
|
| 1301 |
+
exp = int(parts[1])
|
| 1302 |
+
# Look for radix point in mantissa
|
| 1303 |
+
parts = x.split('.')
|
| 1304 |
+
if len(parts) == 2:
|
| 1305 |
+
a, b = parts[0], parts[1].rstrip('0')
|
| 1306 |
+
exp -= len(b)
|
| 1307 |
+
x = a + b
|
| 1308 |
+
x = MPZ(int(x, base))
|
| 1309 |
+
return x, exp
|
| 1310 |
+
|
| 1311 |
+
special_str = {'inf':finf, '+inf':finf, '-inf':fninf, 'nan':fnan}
|
| 1312 |
+
|
| 1313 |
+
def from_str(x, prec, rnd=round_fast):
|
| 1314 |
+
"""Create a raw mpf from a decimal literal, rounding in the
|
| 1315 |
+
specified direction if the input number cannot be represented
|
| 1316 |
+
exactly as a binary floating-point number with the given number of
|
| 1317 |
+
bits. The literal syntax accepted is the same as for Python
|
| 1318 |
+
floats.
|
| 1319 |
+
|
| 1320 |
+
TODO: the rounding does not work properly for large exponents.
|
| 1321 |
+
"""
|
| 1322 |
+
x = x.lower().strip()
|
| 1323 |
+
if x in special_str:
|
| 1324 |
+
return special_str[x]
|
| 1325 |
+
|
| 1326 |
+
if '/' in x:
|
| 1327 |
+
p, q = x.split('/')
|
| 1328 |
+
p, q = p.rstrip('l'), q.rstrip('l')
|
| 1329 |
+
return from_rational(int(p), int(q), prec, rnd)
|
| 1330 |
+
|
| 1331 |
+
man, exp = str_to_man_exp(x, base=10)
|
| 1332 |
+
|
| 1333 |
+
# XXX: appropriate cutoffs & track direction
|
| 1334 |
+
# note no factors of 5
|
| 1335 |
+
if abs(exp) > 400:
|
| 1336 |
+
s = from_int(man, prec+10)
|
| 1337 |
+
s = mpf_mul(s, mpf_pow_int(ften, exp, prec+10), prec, rnd)
|
| 1338 |
+
else:
|
| 1339 |
+
if exp >= 0:
|
| 1340 |
+
s = from_int(man * 10**exp, prec, rnd)
|
| 1341 |
+
else:
|
| 1342 |
+
s = from_rational(man, 10**-exp, prec, rnd)
|
| 1343 |
+
return s
|
| 1344 |
+
|
| 1345 |
+
# Binary string conversion. These are currently mainly used for debugging
|
| 1346 |
+
# and could use some improvement in the future
|
| 1347 |
+
|
| 1348 |
+
def from_bstr(x):
|
| 1349 |
+
man, exp = str_to_man_exp(x, base=2)
|
| 1350 |
+
man = MPZ(man)
|
| 1351 |
+
sign = 0
|
| 1352 |
+
if man < 0:
|
| 1353 |
+
man = -man
|
| 1354 |
+
sign = 1
|
| 1355 |
+
bc = bitcount(man)
|
| 1356 |
+
return normalize(sign, man, exp, bc, bc, round_floor)
|
| 1357 |
+
|
| 1358 |
+
def to_bstr(x):
|
| 1359 |
+
sign, man, exp, bc = x
|
| 1360 |
+
return ['','-'][sign] + numeral(man, size=bitcount(man), base=2) + ("e%i" % exp)
|
| 1361 |
+
|
| 1362 |
+
|
| 1363 |
+
#----------------------------------------------------------------------------#
|
| 1364 |
+
# Square roots #
|
| 1365 |
+
#----------------------------------------------------------------------------#
|
| 1366 |
+
|
| 1367 |
+
|
| 1368 |
+
def mpf_sqrt(s, prec, rnd=round_fast):
|
| 1369 |
+
"""
|
| 1370 |
+
Compute the square root of a nonnegative mpf value. The
|
| 1371 |
+
result is correctly rounded.
|
| 1372 |
+
"""
|
| 1373 |
+
sign, man, exp, bc = s
|
| 1374 |
+
if sign:
|
| 1375 |
+
raise ComplexResult("square root of a negative number")
|
| 1376 |
+
if not man:
|
| 1377 |
+
return s
|
| 1378 |
+
if exp & 1:
|
| 1379 |
+
exp -= 1
|
| 1380 |
+
man <<= 1
|
| 1381 |
+
bc += 1
|
| 1382 |
+
elif man == 1:
|
| 1383 |
+
return normalize1(sign, man, exp//2, bc, prec, rnd)
|
| 1384 |
+
shift = max(4, 2*prec-bc+4)
|
| 1385 |
+
shift += shift & 1
|
| 1386 |
+
if rnd in 'fd':
|
| 1387 |
+
man = isqrt(man<<shift)
|
| 1388 |
+
else:
|
| 1389 |
+
man, rem = sqrtrem(man<<shift)
|
| 1390 |
+
# Perturb up
|
| 1391 |
+
if rem:
|
| 1392 |
+
man = (man<<1)+1
|
| 1393 |
+
shift += 2
|
| 1394 |
+
return from_man_exp(man, (exp-shift)//2, prec, rnd)
|
| 1395 |
+
|
| 1396 |
+
def mpf_hypot(x, y, prec, rnd=round_fast):
|
| 1397 |
+
"""Compute the Euclidean norm sqrt(x**2 + y**2) of two raw mpfs
|
| 1398 |
+
x and y."""
|
| 1399 |
+
if y == fzero: return mpf_abs(x, prec, rnd)
|
| 1400 |
+
if x == fzero: return mpf_abs(y, prec, rnd)
|
| 1401 |
+
hypot2 = mpf_add(mpf_mul(x,x), mpf_mul(y,y), prec+4)
|
| 1402 |
+
return mpf_sqrt(hypot2, prec, rnd)
|
| 1403 |
+
|
| 1404 |
+
|
| 1405 |
+
if BACKEND == 'sage':
|
| 1406 |
+
try:
|
| 1407 |
+
import sage.libs.mpmath.ext_libmp as ext_lib
|
| 1408 |
+
mpf_add = ext_lib.mpf_add
|
| 1409 |
+
mpf_sub = ext_lib.mpf_sub
|
| 1410 |
+
mpf_mul = ext_lib.mpf_mul
|
| 1411 |
+
mpf_div = ext_lib.mpf_div
|
| 1412 |
+
mpf_sqrt = ext_lib.mpf_sqrt
|
| 1413 |
+
except ImportError:
|
| 1414 |
+
pass
|
.venv/lib/python3.11/site-packages/mpmath/libmp/libmpi.py
ADDED
|
@@ -0,0 +1,935 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Computational functions for interval arithmetic.
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from .backend import xrange
|
| 7 |
+
|
| 8 |
+
from .libmpf import (
|
| 9 |
+
ComplexResult,
|
| 10 |
+
round_down, round_up, round_floor, round_ceiling, round_nearest,
|
| 11 |
+
prec_to_dps, repr_dps, dps_to_prec,
|
| 12 |
+
bitcount,
|
| 13 |
+
from_float,
|
| 14 |
+
fnan, finf, fninf, fzero, fhalf, fone, fnone,
|
| 15 |
+
mpf_sign, mpf_lt, mpf_le, mpf_gt, mpf_ge, mpf_eq, mpf_cmp,
|
| 16 |
+
mpf_min_max,
|
| 17 |
+
mpf_floor, from_int, to_int, to_str, from_str,
|
| 18 |
+
mpf_abs, mpf_neg, mpf_pos, mpf_add, mpf_sub, mpf_mul, mpf_mul_int,
|
| 19 |
+
mpf_div, mpf_shift, mpf_pow_int,
|
| 20 |
+
from_man_exp, MPZ_ONE)
|
| 21 |
+
|
| 22 |
+
from .libelefun import (
|
| 23 |
+
mpf_log, mpf_exp, mpf_sqrt, mpf_atan, mpf_atan2,
|
| 24 |
+
mpf_pi, mod_pi2, mpf_cos_sin
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
from .gammazeta import mpf_gamma, mpf_rgamma, mpf_loggamma, mpc_loggamma
|
| 28 |
+
|
| 29 |
+
def mpi_str(s, prec):
|
| 30 |
+
sa, sb = s
|
| 31 |
+
dps = prec_to_dps(prec) + 5
|
| 32 |
+
return "[%s, %s]" % (to_str(sa, dps), to_str(sb, dps))
|
| 33 |
+
#dps = prec_to_dps(prec)
|
| 34 |
+
#m = mpi_mid(s, prec)
|
| 35 |
+
#d = mpf_shift(mpi_delta(s, 20), -1)
|
| 36 |
+
#return "%s +/- %s" % (to_str(m, dps), to_str(d, 3))
|
| 37 |
+
|
| 38 |
+
mpi_zero = (fzero, fzero)
|
| 39 |
+
mpi_one = (fone, fone)
|
| 40 |
+
|
| 41 |
+
def mpi_eq(s, t):
|
| 42 |
+
return s == t
|
| 43 |
+
|
| 44 |
+
def mpi_ne(s, t):
|
| 45 |
+
return s != t
|
| 46 |
+
|
| 47 |
+
def mpi_lt(s, t):
|
| 48 |
+
sa, sb = s
|
| 49 |
+
ta, tb = t
|
| 50 |
+
if mpf_lt(sb, ta): return True
|
| 51 |
+
if mpf_ge(sa, tb): return False
|
| 52 |
+
return None
|
| 53 |
+
|
| 54 |
+
def mpi_le(s, t):
|
| 55 |
+
sa, sb = s
|
| 56 |
+
ta, tb = t
|
| 57 |
+
if mpf_le(sb, ta): return True
|
| 58 |
+
if mpf_gt(sa, tb): return False
|
| 59 |
+
return None
|
| 60 |
+
|
| 61 |
+
def mpi_gt(s, t): return mpi_lt(t, s)
|
| 62 |
+
def mpi_ge(s, t): return mpi_le(t, s)
|
| 63 |
+
|
| 64 |
+
def mpi_add(s, t, prec=0):
|
| 65 |
+
sa, sb = s
|
| 66 |
+
ta, tb = t
|
| 67 |
+
a = mpf_add(sa, ta, prec, round_floor)
|
| 68 |
+
b = mpf_add(sb, tb, prec, round_ceiling)
|
| 69 |
+
if a == fnan: a = fninf
|
| 70 |
+
if b == fnan: b = finf
|
| 71 |
+
return a, b
|
| 72 |
+
|
| 73 |
+
def mpi_sub(s, t, prec=0):
|
| 74 |
+
sa, sb = s
|
| 75 |
+
ta, tb = t
|
| 76 |
+
a = mpf_sub(sa, tb, prec, round_floor)
|
| 77 |
+
b = mpf_sub(sb, ta, prec, round_ceiling)
|
| 78 |
+
if a == fnan: a = fninf
|
| 79 |
+
if b == fnan: b = finf
|
| 80 |
+
return a, b
|
| 81 |
+
|
| 82 |
+
def mpi_delta(s, prec):
|
| 83 |
+
sa, sb = s
|
| 84 |
+
return mpf_sub(sb, sa, prec, round_up)
|
| 85 |
+
|
| 86 |
+
def mpi_mid(s, prec):
|
| 87 |
+
sa, sb = s
|
| 88 |
+
return mpf_shift(mpf_add(sa, sb, prec, round_nearest), -1)
|
| 89 |
+
|
| 90 |
+
def mpi_pos(s, prec):
|
| 91 |
+
sa, sb = s
|
| 92 |
+
a = mpf_pos(sa, prec, round_floor)
|
| 93 |
+
b = mpf_pos(sb, prec, round_ceiling)
|
| 94 |
+
return a, b
|
| 95 |
+
|
| 96 |
+
def mpi_neg(s, prec=0):
|
| 97 |
+
sa, sb = s
|
| 98 |
+
a = mpf_neg(sb, prec, round_floor)
|
| 99 |
+
b = mpf_neg(sa, prec, round_ceiling)
|
| 100 |
+
return a, b
|
| 101 |
+
|
| 102 |
+
def mpi_abs(s, prec=0):
|
| 103 |
+
sa, sb = s
|
| 104 |
+
sas = mpf_sign(sa)
|
| 105 |
+
sbs = mpf_sign(sb)
|
| 106 |
+
# Both points nonnegative?
|
| 107 |
+
if sas >= 0:
|
| 108 |
+
a = mpf_pos(sa, prec, round_floor)
|
| 109 |
+
b = mpf_pos(sb, prec, round_ceiling)
|
| 110 |
+
# Upper point nonnegative?
|
| 111 |
+
elif sbs >= 0:
|
| 112 |
+
a = fzero
|
| 113 |
+
negsa = mpf_neg(sa)
|
| 114 |
+
if mpf_lt(negsa, sb):
|
| 115 |
+
b = mpf_pos(sb, prec, round_ceiling)
|
| 116 |
+
else:
|
| 117 |
+
b = mpf_pos(negsa, prec, round_ceiling)
|
| 118 |
+
# Both negative?
|
| 119 |
+
else:
|
| 120 |
+
a = mpf_neg(sb, prec, round_floor)
|
| 121 |
+
b = mpf_neg(sa, prec, round_ceiling)
|
| 122 |
+
return a, b
|
| 123 |
+
|
| 124 |
+
# TODO: optimize
|
| 125 |
+
def mpi_mul_mpf(s, t, prec):
|
| 126 |
+
return mpi_mul(s, (t, t), prec)
|
| 127 |
+
|
| 128 |
+
def mpi_div_mpf(s, t, prec):
|
| 129 |
+
return mpi_div(s, (t, t), prec)
|
| 130 |
+
|
| 131 |
+
def mpi_mul(s, t, prec=0):
|
| 132 |
+
sa, sb = s
|
| 133 |
+
ta, tb = t
|
| 134 |
+
sas = mpf_sign(sa)
|
| 135 |
+
sbs = mpf_sign(sb)
|
| 136 |
+
tas = mpf_sign(ta)
|
| 137 |
+
tbs = mpf_sign(tb)
|
| 138 |
+
if sas == sbs == 0:
|
| 139 |
+
# Should maybe be undefined
|
| 140 |
+
if ta == fninf or tb == finf:
|
| 141 |
+
return fninf, finf
|
| 142 |
+
return fzero, fzero
|
| 143 |
+
if tas == tbs == 0:
|
| 144 |
+
# Should maybe be undefined
|
| 145 |
+
if sa == fninf or sb == finf:
|
| 146 |
+
return fninf, finf
|
| 147 |
+
return fzero, fzero
|
| 148 |
+
if sas >= 0:
|
| 149 |
+
# positive * positive
|
| 150 |
+
if tas >= 0:
|
| 151 |
+
a = mpf_mul(sa, ta, prec, round_floor)
|
| 152 |
+
b = mpf_mul(sb, tb, prec, round_ceiling)
|
| 153 |
+
if a == fnan: a = fzero
|
| 154 |
+
if b == fnan: b = finf
|
| 155 |
+
# positive * negative
|
| 156 |
+
elif tbs <= 0:
|
| 157 |
+
a = mpf_mul(sb, ta, prec, round_floor)
|
| 158 |
+
b = mpf_mul(sa, tb, prec, round_ceiling)
|
| 159 |
+
if a == fnan: a = fninf
|
| 160 |
+
if b == fnan: b = fzero
|
| 161 |
+
# positive * both signs
|
| 162 |
+
else:
|
| 163 |
+
a = mpf_mul(sb, ta, prec, round_floor)
|
| 164 |
+
b = mpf_mul(sb, tb, prec, round_ceiling)
|
| 165 |
+
if a == fnan: a = fninf
|
| 166 |
+
if b == fnan: b = finf
|
| 167 |
+
elif sbs <= 0:
|
| 168 |
+
# negative * positive
|
| 169 |
+
if tas >= 0:
|
| 170 |
+
a = mpf_mul(sa, tb, prec, round_floor)
|
| 171 |
+
b = mpf_mul(sb, ta, prec, round_ceiling)
|
| 172 |
+
if a == fnan: a = fninf
|
| 173 |
+
if b == fnan: b = fzero
|
| 174 |
+
# negative * negative
|
| 175 |
+
elif tbs <= 0:
|
| 176 |
+
a = mpf_mul(sb, tb, prec, round_floor)
|
| 177 |
+
b = mpf_mul(sa, ta, prec, round_ceiling)
|
| 178 |
+
if a == fnan: a = fzero
|
| 179 |
+
if b == fnan: b = finf
|
| 180 |
+
# negative * both signs
|
| 181 |
+
else:
|
| 182 |
+
a = mpf_mul(sa, tb, prec, round_floor)
|
| 183 |
+
b = mpf_mul(sa, ta, prec, round_ceiling)
|
| 184 |
+
if a == fnan: a = fninf
|
| 185 |
+
if b == fnan: b = finf
|
| 186 |
+
else:
|
| 187 |
+
# General case: perform all cross-multiplications and compare
|
| 188 |
+
# Since the multiplications can be done exactly, we need only
|
| 189 |
+
# do 4 (instead of 8: two for each rounding mode)
|
| 190 |
+
cases = [mpf_mul(sa, ta), mpf_mul(sa, tb), mpf_mul(sb, ta), mpf_mul(sb, tb)]
|
| 191 |
+
if fnan in cases:
|
| 192 |
+
a, b = (fninf, finf)
|
| 193 |
+
else:
|
| 194 |
+
a, b = mpf_min_max(cases)
|
| 195 |
+
a = mpf_pos(a, prec, round_floor)
|
| 196 |
+
b = mpf_pos(b, prec, round_ceiling)
|
| 197 |
+
return a, b
|
| 198 |
+
|
| 199 |
+
def mpi_square(s, prec=0):
|
| 200 |
+
sa, sb = s
|
| 201 |
+
if mpf_ge(sa, fzero):
|
| 202 |
+
a = mpf_mul(sa, sa, prec, round_floor)
|
| 203 |
+
b = mpf_mul(sb, sb, prec, round_ceiling)
|
| 204 |
+
elif mpf_le(sb, fzero):
|
| 205 |
+
a = mpf_mul(sb, sb, prec, round_floor)
|
| 206 |
+
b = mpf_mul(sa, sa, prec, round_ceiling)
|
| 207 |
+
else:
|
| 208 |
+
sa = mpf_neg(sa)
|
| 209 |
+
sa, sb = mpf_min_max([sa, sb])
|
| 210 |
+
a = fzero
|
| 211 |
+
b = mpf_mul(sb, sb, prec, round_ceiling)
|
| 212 |
+
return a, b
|
| 213 |
+
|
| 214 |
+
def mpi_div(s, t, prec):
|
| 215 |
+
sa, sb = s
|
| 216 |
+
ta, tb = t
|
| 217 |
+
sas = mpf_sign(sa)
|
| 218 |
+
sbs = mpf_sign(sb)
|
| 219 |
+
tas = mpf_sign(ta)
|
| 220 |
+
tbs = mpf_sign(tb)
|
| 221 |
+
# 0 / X
|
| 222 |
+
if sas == sbs == 0:
|
| 223 |
+
# 0 / <interval containing 0>
|
| 224 |
+
if (tas < 0 and tbs > 0) or (tas == 0 or tbs == 0):
|
| 225 |
+
return fninf, finf
|
| 226 |
+
return fzero, fzero
|
| 227 |
+
# Denominator contains both negative and positive numbers;
|
| 228 |
+
# this should properly be a multi-interval, but the closest
|
| 229 |
+
# match is the entire (extended) real line
|
| 230 |
+
if tas < 0 and tbs > 0:
|
| 231 |
+
return fninf, finf
|
| 232 |
+
# Assume denominator to be nonnegative
|
| 233 |
+
if tas < 0:
|
| 234 |
+
return mpi_div(mpi_neg(s), mpi_neg(t), prec)
|
| 235 |
+
# Division by zero
|
| 236 |
+
# XXX: make sure all results make sense
|
| 237 |
+
if tas == 0:
|
| 238 |
+
# Numerator contains both signs?
|
| 239 |
+
if sas < 0 and sbs > 0:
|
| 240 |
+
return fninf, finf
|
| 241 |
+
if tas == tbs:
|
| 242 |
+
return fninf, finf
|
| 243 |
+
# Numerator positive?
|
| 244 |
+
if sas >= 0:
|
| 245 |
+
a = mpf_div(sa, tb, prec, round_floor)
|
| 246 |
+
b = finf
|
| 247 |
+
if sbs <= 0:
|
| 248 |
+
a = fninf
|
| 249 |
+
b = mpf_div(sb, tb, prec, round_ceiling)
|
| 250 |
+
# Division with positive denominator
|
| 251 |
+
# We still have to handle nans resulting from inf/0 or inf/inf
|
| 252 |
+
else:
|
| 253 |
+
# Nonnegative numerator
|
| 254 |
+
if sas >= 0:
|
| 255 |
+
a = mpf_div(sa, tb, prec, round_floor)
|
| 256 |
+
b = mpf_div(sb, ta, prec, round_ceiling)
|
| 257 |
+
if a == fnan: a = fzero
|
| 258 |
+
if b == fnan: b = finf
|
| 259 |
+
# Nonpositive numerator
|
| 260 |
+
elif sbs <= 0:
|
| 261 |
+
a = mpf_div(sa, ta, prec, round_floor)
|
| 262 |
+
b = mpf_div(sb, tb, prec, round_ceiling)
|
| 263 |
+
if a == fnan: a = fninf
|
| 264 |
+
if b == fnan: b = fzero
|
| 265 |
+
# Numerator contains both signs?
|
| 266 |
+
else:
|
| 267 |
+
a = mpf_div(sa, ta, prec, round_floor)
|
| 268 |
+
b = mpf_div(sb, ta, prec, round_ceiling)
|
| 269 |
+
if a == fnan: a = fninf
|
| 270 |
+
if b == fnan: b = finf
|
| 271 |
+
return a, b
|
| 272 |
+
|
| 273 |
+
def mpi_pi(prec):
|
| 274 |
+
a = mpf_pi(prec, round_floor)
|
| 275 |
+
b = mpf_pi(prec, round_ceiling)
|
| 276 |
+
return a, b
|
| 277 |
+
|
| 278 |
+
def mpi_exp(s, prec):
|
| 279 |
+
sa, sb = s
|
| 280 |
+
# exp is monotonic
|
| 281 |
+
a = mpf_exp(sa, prec, round_floor)
|
| 282 |
+
b = mpf_exp(sb, prec, round_ceiling)
|
| 283 |
+
return a, b
|
| 284 |
+
|
| 285 |
+
def mpi_log(s, prec):
|
| 286 |
+
sa, sb = s
|
| 287 |
+
# log is monotonic
|
| 288 |
+
a = mpf_log(sa, prec, round_floor)
|
| 289 |
+
b = mpf_log(sb, prec, round_ceiling)
|
| 290 |
+
return a, b
|
| 291 |
+
|
| 292 |
+
def mpi_sqrt(s, prec):
|
| 293 |
+
sa, sb = s
|
| 294 |
+
# sqrt is monotonic
|
| 295 |
+
a = mpf_sqrt(sa, prec, round_floor)
|
| 296 |
+
b = mpf_sqrt(sb, prec, round_ceiling)
|
| 297 |
+
return a, b
|
| 298 |
+
|
| 299 |
+
def mpi_atan(s, prec):
|
| 300 |
+
sa, sb = s
|
| 301 |
+
a = mpf_atan(sa, prec, round_floor)
|
| 302 |
+
b = mpf_atan(sb, prec, round_ceiling)
|
| 303 |
+
return a, b
|
| 304 |
+
|
| 305 |
+
def mpi_pow_int(s, n, prec):
|
| 306 |
+
sa, sb = s
|
| 307 |
+
if n < 0:
|
| 308 |
+
return mpi_div((fone, fone), mpi_pow_int(s, -n, prec+20), prec)
|
| 309 |
+
if n == 0:
|
| 310 |
+
return (fone, fone)
|
| 311 |
+
if n == 1:
|
| 312 |
+
return s
|
| 313 |
+
if n == 2:
|
| 314 |
+
return mpi_square(s, prec)
|
| 315 |
+
# Odd -- signs are preserved
|
| 316 |
+
if n & 1:
|
| 317 |
+
a = mpf_pow_int(sa, n, prec, round_floor)
|
| 318 |
+
b = mpf_pow_int(sb, n, prec, round_ceiling)
|
| 319 |
+
# Even -- important to ensure positivity
|
| 320 |
+
else:
|
| 321 |
+
sas = mpf_sign(sa)
|
| 322 |
+
sbs = mpf_sign(sb)
|
| 323 |
+
# Nonnegative?
|
| 324 |
+
if sas >= 0:
|
| 325 |
+
a = mpf_pow_int(sa, n, prec, round_floor)
|
| 326 |
+
b = mpf_pow_int(sb, n, prec, round_ceiling)
|
| 327 |
+
# Nonpositive?
|
| 328 |
+
elif sbs <= 0:
|
| 329 |
+
a = mpf_pow_int(sb, n, prec, round_floor)
|
| 330 |
+
b = mpf_pow_int(sa, n, prec, round_ceiling)
|
| 331 |
+
# Mixed signs?
|
| 332 |
+
else:
|
| 333 |
+
a = fzero
|
| 334 |
+
# max(-a,b)**n
|
| 335 |
+
sa = mpf_neg(sa)
|
| 336 |
+
if mpf_ge(sa, sb):
|
| 337 |
+
b = mpf_pow_int(sa, n, prec, round_ceiling)
|
| 338 |
+
else:
|
| 339 |
+
b = mpf_pow_int(sb, n, prec, round_ceiling)
|
| 340 |
+
return a, b
|
| 341 |
+
|
| 342 |
+
def mpi_pow(s, t, prec):
|
| 343 |
+
ta, tb = t
|
| 344 |
+
if ta == tb and ta not in (finf, fninf):
|
| 345 |
+
if ta == from_int(to_int(ta)):
|
| 346 |
+
return mpi_pow_int(s, to_int(ta), prec)
|
| 347 |
+
if ta == fhalf:
|
| 348 |
+
return mpi_sqrt(s, prec)
|
| 349 |
+
u = mpi_log(s, prec + 20)
|
| 350 |
+
v = mpi_mul(u, t, prec + 20)
|
| 351 |
+
return mpi_exp(v, prec)
|
| 352 |
+
|
| 353 |
+
def MIN(x, y):
|
| 354 |
+
if mpf_le(x, y):
|
| 355 |
+
return x
|
| 356 |
+
return y
|
| 357 |
+
|
| 358 |
+
def MAX(x, y):
|
| 359 |
+
if mpf_ge(x, y):
|
| 360 |
+
return x
|
| 361 |
+
return y
|
| 362 |
+
|
| 363 |
+
def cos_sin_quadrant(x, wp):
|
| 364 |
+
sign, man, exp, bc = x
|
| 365 |
+
if x == fzero:
|
| 366 |
+
return fone, fzero, 0
|
| 367 |
+
# TODO: combine evaluation code to avoid duplicate modulo
|
| 368 |
+
c, s = mpf_cos_sin(x, wp)
|
| 369 |
+
t, n, wp_ = mod_pi2(man, exp, exp+bc, 15)
|
| 370 |
+
if sign:
|
| 371 |
+
n = -1-n
|
| 372 |
+
return c, s, n
|
| 373 |
+
|
| 374 |
+
def mpi_cos_sin(x, prec):
|
| 375 |
+
a, b = x
|
| 376 |
+
if a == b == fzero:
|
| 377 |
+
return (fone, fone), (fzero, fzero)
|
| 378 |
+
# Guaranteed to contain both -1 and 1
|
| 379 |
+
if (finf in x) or (fninf in x):
|
| 380 |
+
return (fnone, fone), (fnone, fone)
|
| 381 |
+
wp = prec + 20
|
| 382 |
+
ca, sa, na = cos_sin_quadrant(a, wp)
|
| 383 |
+
cb, sb, nb = cos_sin_quadrant(b, wp)
|
| 384 |
+
ca, cb = mpf_min_max([ca, cb])
|
| 385 |
+
sa, sb = mpf_min_max([sa, sb])
|
| 386 |
+
# Both functions are monotonic within one quadrant
|
| 387 |
+
if na == nb:
|
| 388 |
+
pass
|
| 389 |
+
# Guaranteed to contain both -1 and 1
|
| 390 |
+
elif nb - na >= 4:
|
| 391 |
+
return (fnone, fone), (fnone, fone)
|
| 392 |
+
else:
|
| 393 |
+
# cos has maximum between a and b
|
| 394 |
+
if na//4 != nb//4:
|
| 395 |
+
cb = fone
|
| 396 |
+
# cos has minimum
|
| 397 |
+
if (na-2)//4 != (nb-2)//4:
|
| 398 |
+
ca = fnone
|
| 399 |
+
# sin has maximum
|
| 400 |
+
if (na-1)//4 != (nb-1)//4:
|
| 401 |
+
sb = fone
|
| 402 |
+
# sin has minimum
|
| 403 |
+
if (na-3)//4 != (nb-3)//4:
|
| 404 |
+
sa = fnone
|
| 405 |
+
# Perturb to force interval rounding
|
| 406 |
+
more = from_man_exp((MPZ_ONE<<wp) + (MPZ_ONE<<10), -wp)
|
| 407 |
+
less = from_man_exp((MPZ_ONE<<wp) - (MPZ_ONE<<10), -wp)
|
| 408 |
+
def finalize(v, rounding):
|
| 409 |
+
if bool(v[0]) == (rounding == round_floor):
|
| 410 |
+
p = more
|
| 411 |
+
else:
|
| 412 |
+
p = less
|
| 413 |
+
v = mpf_mul(v, p, prec, rounding)
|
| 414 |
+
sign, man, exp, bc = v
|
| 415 |
+
if exp+bc >= 1:
|
| 416 |
+
if sign:
|
| 417 |
+
return fnone
|
| 418 |
+
return fone
|
| 419 |
+
return v
|
| 420 |
+
ca = finalize(ca, round_floor)
|
| 421 |
+
cb = finalize(cb, round_ceiling)
|
| 422 |
+
sa = finalize(sa, round_floor)
|
| 423 |
+
sb = finalize(sb, round_ceiling)
|
| 424 |
+
return (ca,cb), (sa,sb)
|
| 425 |
+
|
| 426 |
+
def mpi_cos(x, prec):
|
| 427 |
+
return mpi_cos_sin(x, prec)[0]
|
| 428 |
+
|
| 429 |
+
def mpi_sin(x, prec):
|
| 430 |
+
return mpi_cos_sin(x, prec)[1]
|
| 431 |
+
|
| 432 |
+
def mpi_tan(x, prec):
|
| 433 |
+
cos, sin = mpi_cos_sin(x, prec+20)
|
| 434 |
+
return mpi_div(sin, cos, prec)
|
| 435 |
+
|
| 436 |
+
def mpi_cot(x, prec):
|
| 437 |
+
cos, sin = mpi_cos_sin(x, prec+20)
|
| 438 |
+
return mpi_div(cos, sin, prec)
|
| 439 |
+
|
| 440 |
+
def mpi_from_str_a_b(x, y, percent, prec):
|
| 441 |
+
wp = prec + 20
|
| 442 |
+
xa = from_str(x, wp, round_floor)
|
| 443 |
+
xb = from_str(x, wp, round_ceiling)
|
| 444 |
+
#ya = from_str(y, wp, round_floor)
|
| 445 |
+
y = from_str(y, wp, round_ceiling)
|
| 446 |
+
assert mpf_ge(y, fzero)
|
| 447 |
+
if percent:
|
| 448 |
+
y = mpf_mul(MAX(mpf_abs(xa), mpf_abs(xb)), y, wp, round_ceiling)
|
| 449 |
+
y = mpf_div(y, from_int(100), wp, round_ceiling)
|
| 450 |
+
a = mpf_sub(xa, y, prec, round_floor)
|
| 451 |
+
b = mpf_add(xb, y, prec, round_ceiling)
|
| 452 |
+
return a, b
|
| 453 |
+
|
| 454 |
+
def mpi_from_str(s, prec):
|
| 455 |
+
"""
|
| 456 |
+
Parse an interval number given as a string.
|
| 457 |
+
|
| 458 |
+
Allowed forms are
|
| 459 |
+
|
| 460 |
+
"-1.23e-27"
|
| 461 |
+
Any single decimal floating-point literal.
|
| 462 |
+
"a +- b" or "a (b)"
|
| 463 |
+
a is the midpoint of the interval and b is the half-width
|
| 464 |
+
"a +- b%" or "a (b%)"
|
| 465 |
+
a is the midpoint of the interval and the half-width
|
| 466 |
+
is b percent of a (`a \times b / 100`).
|
| 467 |
+
"[a, b]"
|
| 468 |
+
The interval indicated directly.
|
| 469 |
+
"x[y,z]e"
|
| 470 |
+
x are shared digits, y and z are unequal digits, e is the exponent.
|
| 471 |
+
|
| 472 |
+
"""
|
| 473 |
+
e = ValueError("Improperly formed interval number '%s'" % s)
|
| 474 |
+
s = s.replace(" ", "")
|
| 475 |
+
wp = prec + 20
|
| 476 |
+
if "+-" in s:
|
| 477 |
+
x, y = s.split("+-")
|
| 478 |
+
return mpi_from_str_a_b(x, y, False, prec)
|
| 479 |
+
# case 2
|
| 480 |
+
elif "(" in s:
|
| 481 |
+
# Don't confuse with a complex number (x,y)
|
| 482 |
+
if s[0] == "(" or ")" not in s:
|
| 483 |
+
raise e
|
| 484 |
+
s = s.replace(")", "")
|
| 485 |
+
percent = False
|
| 486 |
+
if "%" in s:
|
| 487 |
+
if s[-1] != "%":
|
| 488 |
+
raise e
|
| 489 |
+
percent = True
|
| 490 |
+
s = s.replace("%", "")
|
| 491 |
+
x, y = s.split("(")
|
| 492 |
+
return mpi_from_str_a_b(x, y, percent, prec)
|
| 493 |
+
elif "," in s:
|
| 494 |
+
if ('[' not in s) or (']' not in s):
|
| 495 |
+
raise e
|
| 496 |
+
if s[0] == '[':
|
| 497 |
+
# case 3
|
| 498 |
+
s = s.replace("[", "")
|
| 499 |
+
s = s.replace("]", "")
|
| 500 |
+
a, b = s.split(",")
|
| 501 |
+
a = from_str(a, prec, round_floor)
|
| 502 |
+
b = from_str(b, prec, round_ceiling)
|
| 503 |
+
return a, b
|
| 504 |
+
else:
|
| 505 |
+
# case 4
|
| 506 |
+
x, y = s.split('[')
|
| 507 |
+
y, z = y.split(',')
|
| 508 |
+
if 'e' in s:
|
| 509 |
+
z, e = z.split(']')
|
| 510 |
+
else:
|
| 511 |
+
z, e = z.rstrip(']'), ''
|
| 512 |
+
a = from_str(x+y+e, prec, round_floor)
|
| 513 |
+
b = from_str(x+z+e, prec, round_ceiling)
|
| 514 |
+
return a, b
|
| 515 |
+
else:
|
| 516 |
+
a = from_str(s, prec, round_floor)
|
| 517 |
+
b = from_str(s, prec, round_ceiling)
|
| 518 |
+
return a, b
|
| 519 |
+
|
| 520 |
+
def mpi_to_str(x, dps, use_spaces=True, brackets='[]', mode='brackets', error_dps=4, **kwargs):
|
| 521 |
+
"""
|
| 522 |
+
Convert a mpi interval to a string.
|
| 523 |
+
|
| 524 |
+
**Arguments**
|
| 525 |
+
|
| 526 |
+
*dps*
|
| 527 |
+
decimal places to use for printing
|
| 528 |
+
*use_spaces*
|
| 529 |
+
use spaces for more readable output, defaults to true
|
| 530 |
+
*brackets*
|
| 531 |
+
pair of strings (or two-character string) giving left and right brackets
|
| 532 |
+
*mode*
|
| 533 |
+
mode of display: 'plusminus', 'percent', 'brackets' (default) or 'diff'
|
| 534 |
+
*error_dps*
|
| 535 |
+
limit the error to *error_dps* digits (mode 'plusminus and 'percent')
|
| 536 |
+
|
| 537 |
+
Additional keyword arguments are forwarded to the mpf-to-string conversion
|
| 538 |
+
for the components of the output.
|
| 539 |
+
|
| 540 |
+
**Examples**
|
| 541 |
+
|
| 542 |
+
>>> from mpmath import mpi, mp
|
| 543 |
+
>>> mp.dps = 30
|
| 544 |
+
>>> x = mpi(1, 2)._mpi_
|
| 545 |
+
>>> mpi_to_str(x, 2, mode='plusminus')
|
| 546 |
+
'1.5 +- 0.5'
|
| 547 |
+
>>> mpi_to_str(x, 2, mode='percent')
|
| 548 |
+
'1.5 (33.33%)'
|
| 549 |
+
>>> mpi_to_str(x, 2, mode='brackets')
|
| 550 |
+
'[1.0, 2.0]'
|
| 551 |
+
>>> mpi_to_str(x, 2, mode='brackets' , brackets=('<', '>'))
|
| 552 |
+
'<1.0, 2.0>'
|
| 553 |
+
>>> x = mpi('5.2582327113062393041', '5.2582327113062749951')._mpi_
|
| 554 |
+
>>> mpi_to_str(x, 15, mode='diff')
|
| 555 |
+
'5.2582327113062[4, 7]'
|
| 556 |
+
>>> mpi_to_str(mpi(0)._mpi_, 2, mode='percent')
|
| 557 |
+
'0.0 (0.0%)'
|
| 558 |
+
|
| 559 |
+
"""
|
| 560 |
+
prec = dps_to_prec(dps)
|
| 561 |
+
wp = prec + 20
|
| 562 |
+
a, b = x
|
| 563 |
+
mid = mpi_mid(x, prec)
|
| 564 |
+
delta = mpi_delta(x, prec)
|
| 565 |
+
a_str = to_str(a, dps, **kwargs)
|
| 566 |
+
b_str = to_str(b, dps, **kwargs)
|
| 567 |
+
mid_str = to_str(mid, dps, **kwargs)
|
| 568 |
+
sp = ""
|
| 569 |
+
if use_spaces:
|
| 570 |
+
sp = " "
|
| 571 |
+
br1, br2 = brackets
|
| 572 |
+
if mode == 'plusminus':
|
| 573 |
+
delta_str = to_str(mpf_shift(delta,-1), dps, **kwargs)
|
| 574 |
+
s = mid_str + sp + "+-" + sp + delta_str
|
| 575 |
+
elif mode == 'percent':
|
| 576 |
+
if mid == fzero:
|
| 577 |
+
p = fzero
|
| 578 |
+
else:
|
| 579 |
+
# p = 100 * delta(x) / (2*mid(x))
|
| 580 |
+
p = mpf_mul(delta, from_int(100))
|
| 581 |
+
p = mpf_div(p, mpf_mul(mid, from_int(2)), wp)
|
| 582 |
+
s = mid_str + sp + "(" + to_str(p, error_dps) + "%)"
|
| 583 |
+
elif mode == 'brackets':
|
| 584 |
+
s = br1 + a_str + "," + sp + b_str + br2
|
| 585 |
+
elif mode == 'diff':
|
| 586 |
+
# use more digits if str(x.a) and str(x.b) are equal
|
| 587 |
+
if a_str == b_str:
|
| 588 |
+
a_str = to_str(a, dps+3, **kwargs)
|
| 589 |
+
b_str = to_str(b, dps+3, **kwargs)
|
| 590 |
+
# separate mantissa and exponent
|
| 591 |
+
a = a_str.split('e')
|
| 592 |
+
if len(a) == 1:
|
| 593 |
+
a.append('')
|
| 594 |
+
b = b_str.split('e')
|
| 595 |
+
if len(b) == 1:
|
| 596 |
+
b.append('')
|
| 597 |
+
if a[1] == b[1]:
|
| 598 |
+
if a[0] != b[0]:
|
| 599 |
+
for i in xrange(len(a[0]) + 1):
|
| 600 |
+
if a[0][i] != b[0][i]:
|
| 601 |
+
break
|
| 602 |
+
s = (a[0][:i] + br1 + a[0][i:] + ',' + sp + b[0][i:] + br2
|
| 603 |
+
+ 'e'*min(len(a[1]), 1) + a[1])
|
| 604 |
+
else: # no difference
|
| 605 |
+
s = a[0] + br1 + br2 + 'e'*min(len(a[1]), 1) + a[1]
|
| 606 |
+
else:
|
| 607 |
+
s = br1 + 'e'.join(a) + ',' + sp + 'e'.join(b) + br2
|
| 608 |
+
else:
|
| 609 |
+
raise ValueError("'%s' is unknown mode for printing mpi" % mode)
|
| 610 |
+
return s
|
| 611 |
+
|
| 612 |
+
def mpci_add(x, y, prec):
|
| 613 |
+
a, b = x
|
| 614 |
+
c, d = y
|
| 615 |
+
return mpi_add(a, c, prec), mpi_add(b, d, prec)
|
| 616 |
+
|
| 617 |
+
def mpci_sub(x, y, prec):
|
| 618 |
+
a, b = x
|
| 619 |
+
c, d = y
|
| 620 |
+
return mpi_sub(a, c, prec), mpi_sub(b, d, prec)
|
| 621 |
+
|
| 622 |
+
def mpci_neg(x, prec=0):
|
| 623 |
+
a, b = x
|
| 624 |
+
return mpi_neg(a, prec), mpi_neg(b, prec)
|
| 625 |
+
|
| 626 |
+
def mpci_pos(x, prec):
|
| 627 |
+
a, b = x
|
| 628 |
+
return mpi_pos(a, prec), mpi_pos(b, prec)
|
| 629 |
+
|
| 630 |
+
def mpci_mul(x, y, prec):
|
| 631 |
+
# TODO: optimize for real/imag cases
|
| 632 |
+
a, b = x
|
| 633 |
+
c, d = y
|
| 634 |
+
r1 = mpi_mul(a,c)
|
| 635 |
+
r2 = mpi_mul(b,d)
|
| 636 |
+
re = mpi_sub(r1,r2,prec)
|
| 637 |
+
i1 = mpi_mul(a,d)
|
| 638 |
+
i2 = mpi_mul(b,c)
|
| 639 |
+
im = mpi_add(i1,i2,prec)
|
| 640 |
+
return re, im
|
| 641 |
+
|
| 642 |
+
def mpci_div(x, y, prec):
|
| 643 |
+
# TODO: optimize for real/imag cases
|
| 644 |
+
a, b = x
|
| 645 |
+
c, d = y
|
| 646 |
+
wp = prec+20
|
| 647 |
+
m1 = mpi_square(c)
|
| 648 |
+
m2 = mpi_square(d)
|
| 649 |
+
m = mpi_add(m1,m2,wp)
|
| 650 |
+
re = mpi_add(mpi_mul(a,c), mpi_mul(b,d), wp)
|
| 651 |
+
im = mpi_sub(mpi_mul(b,c), mpi_mul(a,d), wp)
|
| 652 |
+
re = mpi_div(re, m, prec)
|
| 653 |
+
im = mpi_div(im, m, prec)
|
| 654 |
+
return re, im
|
| 655 |
+
|
| 656 |
+
def mpci_exp(x, prec):
|
| 657 |
+
a, b = x
|
| 658 |
+
wp = prec+20
|
| 659 |
+
r = mpi_exp(a, wp)
|
| 660 |
+
c, s = mpi_cos_sin(b, wp)
|
| 661 |
+
a = mpi_mul(r, c, prec)
|
| 662 |
+
b = mpi_mul(r, s, prec)
|
| 663 |
+
return a, b
|
| 664 |
+
|
| 665 |
+
def mpi_shift(x, n):
|
| 666 |
+
a, b = x
|
| 667 |
+
return mpf_shift(a,n), mpf_shift(b,n)
|
| 668 |
+
|
| 669 |
+
def mpi_cosh_sinh(x, prec):
|
| 670 |
+
# TODO: accuracy for small x
|
| 671 |
+
wp = prec+20
|
| 672 |
+
e1 = mpi_exp(x, wp)
|
| 673 |
+
e2 = mpi_div(mpi_one, e1, wp)
|
| 674 |
+
c = mpi_add(e1, e2, prec)
|
| 675 |
+
s = mpi_sub(e1, e2, prec)
|
| 676 |
+
c = mpi_shift(c, -1)
|
| 677 |
+
s = mpi_shift(s, -1)
|
| 678 |
+
return c, s
|
| 679 |
+
|
| 680 |
+
def mpci_cos(x, prec):
|
| 681 |
+
a, b = x
|
| 682 |
+
wp = prec+10
|
| 683 |
+
c, s = mpi_cos_sin(a, wp)
|
| 684 |
+
ch, sh = mpi_cosh_sinh(b, wp)
|
| 685 |
+
re = mpi_mul(c, ch, prec)
|
| 686 |
+
im = mpi_mul(s, sh, prec)
|
| 687 |
+
return re, mpi_neg(im)
|
| 688 |
+
|
| 689 |
+
def mpci_sin(x, prec):
|
| 690 |
+
a, b = x
|
| 691 |
+
wp = prec+10
|
| 692 |
+
c, s = mpi_cos_sin(a, wp)
|
| 693 |
+
ch, sh = mpi_cosh_sinh(b, wp)
|
| 694 |
+
re = mpi_mul(s, ch, prec)
|
| 695 |
+
im = mpi_mul(c, sh, prec)
|
| 696 |
+
return re, im
|
| 697 |
+
|
| 698 |
+
def mpci_abs(x, prec):
|
| 699 |
+
a, b = x
|
| 700 |
+
if a == mpi_zero:
|
| 701 |
+
return mpi_abs(b)
|
| 702 |
+
if b == mpi_zero:
|
| 703 |
+
return mpi_abs(a)
|
| 704 |
+
# Important: nonnegative
|
| 705 |
+
a = mpi_square(a)
|
| 706 |
+
b = mpi_square(b)
|
| 707 |
+
t = mpi_add(a, b, prec+20)
|
| 708 |
+
return mpi_sqrt(t, prec)
|
| 709 |
+
|
| 710 |
+
def mpi_atan2(y, x, prec):
|
| 711 |
+
ya, yb = y
|
| 712 |
+
xa, xb = x
|
| 713 |
+
# Constrained to the real line
|
| 714 |
+
if ya == yb == fzero:
|
| 715 |
+
if mpf_ge(xa, fzero):
|
| 716 |
+
return mpi_zero
|
| 717 |
+
return mpi_pi(prec)
|
| 718 |
+
# Right half-plane
|
| 719 |
+
if mpf_ge(xa, fzero):
|
| 720 |
+
if mpf_ge(ya, fzero):
|
| 721 |
+
a = mpf_atan2(ya, xb, prec, round_floor)
|
| 722 |
+
else:
|
| 723 |
+
a = mpf_atan2(ya, xa, prec, round_floor)
|
| 724 |
+
if mpf_ge(yb, fzero):
|
| 725 |
+
b = mpf_atan2(yb, xa, prec, round_ceiling)
|
| 726 |
+
else:
|
| 727 |
+
b = mpf_atan2(yb, xb, prec, round_ceiling)
|
| 728 |
+
# Upper half-plane
|
| 729 |
+
elif mpf_ge(ya, fzero):
|
| 730 |
+
b = mpf_atan2(ya, xa, prec, round_ceiling)
|
| 731 |
+
if mpf_le(xb, fzero):
|
| 732 |
+
a = mpf_atan2(yb, xb, prec, round_floor)
|
| 733 |
+
else:
|
| 734 |
+
a = mpf_atan2(ya, xb, prec, round_floor)
|
| 735 |
+
# Lower half-plane
|
| 736 |
+
elif mpf_le(yb, fzero):
|
| 737 |
+
a = mpf_atan2(yb, xa, prec, round_floor)
|
| 738 |
+
if mpf_le(xb, fzero):
|
| 739 |
+
b = mpf_atan2(ya, xb, prec, round_ceiling)
|
| 740 |
+
else:
|
| 741 |
+
b = mpf_atan2(yb, xb, prec, round_ceiling)
|
| 742 |
+
# Covering the origin
|
| 743 |
+
else:
|
| 744 |
+
b = mpf_pi(prec, round_ceiling)
|
| 745 |
+
a = mpf_neg(b)
|
| 746 |
+
return a, b
|
| 747 |
+
|
| 748 |
+
def mpci_arg(z, prec):
|
| 749 |
+
x, y = z
|
| 750 |
+
return mpi_atan2(y, x, prec)
|
| 751 |
+
|
| 752 |
+
def mpci_log(z, prec):
|
| 753 |
+
x, y = z
|
| 754 |
+
re = mpi_log(mpci_abs(z, prec+20), prec)
|
| 755 |
+
im = mpci_arg(z, prec)
|
| 756 |
+
return re, im
|
| 757 |
+
|
| 758 |
+
def mpci_pow(x, y, prec):
|
| 759 |
+
# TODO: recognize/speed up real cases, integer y
|
| 760 |
+
yre, yim = y
|
| 761 |
+
if yim == mpi_zero:
|
| 762 |
+
ya, yb = yre
|
| 763 |
+
if ya == yb:
|
| 764 |
+
sign, man, exp, bc = yb
|
| 765 |
+
if man and exp >= 0:
|
| 766 |
+
return mpci_pow_int(x, (-1)**sign * int(man<<exp), prec)
|
| 767 |
+
# x^0
|
| 768 |
+
if yb == fzero:
|
| 769 |
+
return mpci_pow_int(x, 0, prec)
|
| 770 |
+
wp = prec+20
|
| 771 |
+
return mpci_exp(mpci_mul(y, mpci_log(x, wp), wp), prec)
|
| 772 |
+
|
| 773 |
+
def mpci_square(x, prec):
|
| 774 |
+
a, b = x
|
| 775 |
+
# (a+bi)^2 = (a^2-b^2) + 2abi
|
| 776 |
+
re = mpi_sub(mpi_square(a), mpi_square(b), prec)
|
| 777 |
+
im = mpi_mul(a, b, prec)
|
| 778 |
+
im = mpi_shift(im, 1)
|
| 779 |
+
return re, im
|
| 780 |
+
|
| 781 |
+
def mpci_pow_int(x, n, prec):
|
| 782 |
+
if n < 0:
|
| 783 |
+
return mpci_div((mpi_one,mpi_zero), mpci_pow_int(x, -n, prec+20), prec)
|
| 784 |
+
if n == 0:
|
| 785 |
+
return mpi_one, mpi_zero
|
| 786 |
+
if n == 1:
|
| 787 |
+
return mpci_pos(x, prec)
|
| 788 |
+
if n == 2:
|
| 789 |
+
return mpci_square(x, prec)
|
| 790 |
+
wp = prec + 20
|
| 791 |
+
result = (mpi_one, mpi_zero)
|
| 792 |
+
while n:
|
| 793 |
+
if n & 1:
|
| 794 |
+
result = mpci_mul(result, x, wp)
|
| 795 |
+
n -= 1
|
| 796 |
+
x = mpci_square(x, wp)
|
| 797 |
+
n >>= 1
|
| 798 |
+
return mpci_pos(result, prec)
|
| 799 |
+
|
| 800 |
+
gamma_min_a = from_float(1.46163214496)
|
| 801 |
+
gamma_min_b = from_float(1.46163214497)
|
| 802 |
+
gamma_min = (gamma_min_a, gamma_min_b)
|
| 803 |
+
gamma_mono_imag_a = from_float(-1.1)
|
| 804 |
+
gamma_mono_imag_b = from_float(1.1)
|
| 805 |
+
|
| 806 |
+
def mpi_overlap(x, y):
|
| 807 |
+
a, b = x
|
| 808 |
+
c, d = y
|
| 809 |
+
if mpf_lt(d, a): return False
|
| 810 |
+
if mpf_gt(c, b): return False
|
| 811 |
+
return True
|
| 812 |
+
|
| 813 |
+
# type = 0 -- gamma
|
| 814 |
+
# type = 1 -- factorial
|
| 815 |
+
# type = 2 -- 1/gamma
|
| 816 |
+
# type = 3 -- log-gamma
|
| 817 |
+
|
| 818 |
+
def mpi_gamma(z, prec, type=0):
|
| 819 |
+
a, b = z
|
| 820 |
+
wp = prec+20
|
| 821 |
+
|
| 822 |
+
if type == 1:
|
| 823 |
+
return mpi_gamma(mpi_add(z, mpi_one, wp), prec, 0)
|
| 824 |
+
|
| 825 |
+
# increasing
|
| 826 |
+
if mpf_gt(a, gamma_min_b):
|
| 827 |
+
if type == 0:
|
| 828 |
+
c = mpf_gamma(a, prec, round_floor)
|
| 829 |
+
d = mpf_gamma(b, prec, round_ceiling)
|
| 830 |
+
elif type == 2:
|
| 831 |
+
c = mpf_rgamma(b, prec, round_floor)
|
| 832 |
+
d = mpf_rgamma(a, prec, round_ceiling)
|
| 833 |
+
elif type == 3:
|
| 834 |
+
c = mpf_loggamma(a, prec, round_floor)
|
| 835 |
+
d = mpf_loggamma(b, prec, round_ceiling)
|
| 836 |
+
# decreasing
|
| 837 |
+
elif mpf_gt(a, fzero) and mpf_lt(b, gamma_min_a):
|
| 838 |
+
if type == 0:
|
| 839 |
+
c = mpf_gamma(b, prec, round_floor)
|
| 840 |
+
d = mpf_gamma(a, prec, round_ceiling)
|
| 841 |
+
elif type == 2:
|
| 842 |
+
c = mpf_rgamma(a, prec, round_floor)
|
| 843 |
+
d = mpf_rgamma(b, prec, round_ceiling)
|
| 844 |
+
elif type == 3:
|
| 845 |
+
c = mpf_loggamma(b, prec, round_floor)
|
| 846 |
+
d = mpf_loggamma(a, prec, round_ceiling)
|
| 847 |
+
else:
|
| 848 |
+
# TODO: reflection formula
|
| 849 |
+
znew = mpi_add(z, mpi_one, wp)
|
| 850 |
+
if type == 0: return mpi_div(mpi_gamma(znew, prec+2, 0), z, prec)
|
| 851 |
+
if type == 2: return mpi_mul(mpi_gamma(znew, prec+2, 2), z, prec)
|
| 852 |
+
if type == 3: return mpi_sub(mpi_gamma(znew, prec+2, 3), mpi_log(z, prec+2), prec)
|
| 853 |
+
return c, d
|
| 854 |
+
|
| 855 |
+
def mpci_gamma(z, prec, type=0):
|
| 856 |
+
(a1,a2), (b1,b2) = z
|
| 857 |
+
|
| 858 |
+
# Real case
|
| 859 |
+
if b1 == b2 == fzero and (type != 3 or mpf_gt(a1,fzero)):
|
| 860 |
+
return mpi_gamma(z, prec, type), mpi_zero
|
| 861 |
+
|
| 862 |
+
# Estimate precision
|
| 863 |
+
wp = prec+20
|
| 864 |
+
if type != 3:
|
| 865 |
+
amag = a2[2]+a2[3]
|
| 866 |
+
bmag = b2[2]+b2[3]
|
| 867 |
+
if a2 != fzero:
|
| 868 |
+
mag = max(amag, bmag)
|
| 869 |
+
else:
|
| 870 |
+
mag = bmag
|
| 871 |
+
an = abs(to_int(a2))
|
| 872 |
+
bn = abs(to_int(b2))
|
| 873 |
+
absn = max(an, bn)
|
| 874 |
+
gamma_size = max(0,absn*mag)
|
| 875 |
+
wp += bitcount(gamma_size)
|
| 876 |
+
|
| 877 |
+
# Assume type != 1
|
| 878 |
+
if type == 1:
|
| 879 |
+
(a1,a2) = mpi_add((a1,a2), mpi_one, wp); z = (a1,a2), (b1,b2)
|
| 880 |
+
type = 0
|
| 881 |
+
|
| 882 |
+
# Avoid non-monotonic region near the negative real axis
|
| 883 |
+
if mpf_lt(a1, gamma_min_b):
|
| 884 |
+
if mpi_overlap((b1,b2), (gamma_mono_imag_a, gamma_mono_imag_b)):
|
| 885 |
+
# TODO: reflection formula
|
| 886 |
+
#if mpf_lt(a2, mpf_shift(fone,-1)):
|
| 887 |
+
# znew = mpci_sub((mpi_one,mpi_zero),z,wp)
|
| 888 |
+
# ...
|
| 889 |
+
# Recurrence:
|
| 890 |
+
# gamma(z) = gamma(z+1)/z
|
| 891 |
+
znew = mpi_add((a1,a2), mpi_one, wp), (b1,b2)
|
| 892 |
+
if type == 0: return mpci_div(mpci_gamma(znew, prec+2, 0), z, prec)
|
| 893 |
+
if type == 2: return mpci_mul(mpci_gamma(znew, prec+2, 2), z, prec)
|
| 894 |
+
if type == 3: return mpci_sub(mpci_gamma(znew, prec+2, 3), mpci_log(z,prec+2), prec)
|
| 895 |
+
|
| 896 |
+
# Use monotonicity (except for a small region close to the
|
| 897 |
+
# origin and near poles)
|
| 898 |
+
# upper half-plane
|
| 899 |
+
if mpf_ge(b1, fzero):
|
| 900 |
+
minre = mpc_loggamma((a1,b2), wp, round_floor)
|
| 901 |
+
maxre = mpc_loggamma((a2,b1), wp, round_ceiling)
|
| 902 |
+
minim = mpc_loggamma((a1,b1), wp, round_floor)
|
| 903 |
+
maxim = mpc_loggamma((a2,b2), wp, round_ceiling)
|
| 904 |
+
# lower half-plane
|
| 905 |
+
elif mpf_le(b2, fzero):
|
| 906 |
+
minre = mpc_loggamma((a1,b1), wp, round_floor)
|
| 907 |
+
maxre = mpc_loggamma((a2,b2), wp, round_ceiling)
|
| 908 |
+
minim = mpc_loggamma((a2,b1), wp, round_floor)
|
| 909 |
+
maxim = mpc_loggamma((a1,b2), wp, round_ceiling)
|
| 910 |
+
# crosses real axis
|
| 911 |
+
else:
|
| 912 |
+
maxre = mpc_loggamma((a2,fzero), wp, round_ceiling)
|
| 913 |
+
# stretches more into the lower half-plane
|
| 914 |
+
if mpf_gt(mpf_neg(b1), b2):
|
| 915 |
+
minre = mpc_loggamma((a1,b1), wp, round_ceiling)
|
| 916 |
+
else:
|
| 917 |
+
minre = mpc_loggamma((a1,b2), wp, round_ceiling)
|
| 918 |
+
minim = mpc_loggamma((a2,b1), wp, round_floor)
|
| 919 |
+
maxim = mpc_loggamma((a2,b2), wp, round_floor)
|
| 920 |
+
|
| 921 |
+
w = (minre[0], maxre[0]), (minim[1], maxim[1])
|
| 922 |
+
if type == 3:
|
| 923 |
+
return mpi_pos(w[0], prec), mpi_pos(w[1], prec)
|
| 924 |
+
if type == 2:
|
| 925 |
+
w = mpci_neg(w)
|
| 926 |
+
return mpci_exp(w, prec)
|
| 927 |
+
|
| 928 |
+
def mpi_loggamma(z, prec): return mpi_gamma(z, prec, type=3)
|
| 929 |
+
def mpci_loggamma(z, prec): return mpci_gamma(z, prec, type=3)
|
| 930 |
+
|
| 931 |
+
def mpi_rgamma(z, prec): return mpi_gamma(z, prec, type=2)
|
| 932 |
+
def mpci_rgamma(z, prec): return mpci_gamma(z, prec, type=2)
|
| 933 |
+
|
| 934 |
+
def mpi_factorial(z, prec): return mpi_gamma(z, prec, type=1)
|
| 935 |
+
def mpci_factorial(z, prec): return mpci_gamma(z, prec, type=1)
|
.venv/lib/python3.11/site-packages/mpmath/math2.py
ADDED
|
@@ -0,0 +1,672 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This module complements the math and cmath builtin modules by providing
|
| 3 |
+
fast machine precision versions of some additional functions (gamma, ...)
|
| 4 |
+
and wrapping math/cmath functions so that they can be called with either
|
| 5 |
+
real or complex arguments.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import operator
|
| 9 |
+
import math
|
| 10 |
+
import cmath
|
| 11 |
+
|
| 12 |
+
# Irrational (?) constants
|
| 13 |
+
pi = 3.1415926535897932385
|
| 14 |
+
e = 2.7182818284590452354
|
| 15 |
+
sqrt2 = 1.4142135623730950488
|
| 16 |
+
sqrt5 = 2.2360679774997896964
|
| 17 |
+
phi = 1.6180339887498948482
|
| 18 |
+
ln2 = 0.69314718055994530942
|
| 19 |
+
ln10 = 2.302585092994045684
|
| 20 |
+
euler = 0.57721566490153286061
|
| 21 |
+
catalan = 0.91596559417721901505
|
| 22 |
+
khinchin = 2.6854520010653064453
|
| 23 |
+
apery = 1.2020569031595942854
|
| 24 |
+
|
| 25 |
+
logpi = 1.1447298858494001741
|
| 26 |
+
|
| 27 |
+
def _mathfun_real(f_real, f_complex):
|
| 28 |
+
def f(x, **kwargs):
|
| 29 |
+
if type(x) is float:
|
| 30 |
+
return f_real(x)
|
| 31 |
+
if type(x) is complex:
|
| 32 |
+
return f_complex(x)
|
| 33 |
+
try:
|
| 34 |
+
x = float(x)
|
| 35 |
+
return f_real(x)
|
| 36 |
+
except (TypeError, ValueError):
|
| 37 |
+
x = complex(x)
|
| 38 |
+
return f_complex(x)
|
| 39 |
+
f.__name__ = f_real.__name__
|
| 40 |
+
return f
|
| 41 |
+
|
| 42 |
+
def _mathfun(f_real, f_complex):
|
| 43 |
+
def f(x, **kwargs):
|
| 44 |
+
if type(x) is complex:
|
| 45 |
+
return f_complex(x)
|
| 46 |
+
try:
|
| 47 |
+
return f_real(float(x))
|
| 48 |
+
except (TypeError, ValueError):
|
| 49 |
+
return f_complex(complex(x))
|
| 50 |
+
f.__name__ = f_real.__name__
|
| 51 |
+
return f
|
| 52 |
+
|
| 53 |
+
def _mathfun_n(f_real, f_complex):
|
| 54 |
+
def f(*args, **kwargs):
|
| 55 |
+
try:
|
| 56 |
+
return f_real(*(float(x) for x in args))
|
| 57 |
+
except (TypeError, ValueError):
|
| 58 |
+
return f_complex(*(complex(x) for x in args))
|
| 59 |
+
f.__name__ = f_real.__name__
|
| 60 |
+
return f
|
| 61 |
+
|
| 62 |
+
# Workaround for non-raising log and sqrt in Python 2.5 and 2.4
|
| 63 |
+
# on Unix system
|
| 64 |
+
try:
|
| 65 |
+
math.log(-2.0)
|
| 66 |
+
def math_log(x):
|
| 67 |
+
if x <= 0.0:
|
| 68 |
+
raise ValueError("math domain error")
|
| 69 |
+
return math.log(x)
|
| 70 |
+
def math_sqrt(x):
|
| 71 |
+
if x < 0.0:
|
| 72 |
+
raise ValueError("math domain error")
|
| 73 |
+
return math.sqrt(x)
|
| 74 |
+
except (ValueError, TypeError):
|
| 75 |
+
math_log = math.log
|
| 76 |
+
math_sqrt = math.sqrt
|
| 77 |
+
|
| 78 |
+
pow = _mathfun_n(operator.pow, lambda x, y: complex(x)**y)
|
| 79 |
+
log = _mathfun_n(math_log, cmath.log)
|
| 80 |
+
sqrt = _mathfun(math_sqrt, cmath.sqrt)
|
| 81 |
+
exp = _mathfun_real(math.exp, cmath.exp)
|
| 82 |
+
|
| 83 |
+
cos = _mathfun_real(math.cos, cmath.cos)
|
| 84 |
+
sin = _mathfun_real(math.sin, cmath.sin)
|
| 85 |
+
tan = _mathfun_real(math.tan, cmath.tan)
|
| 86 |
+
|
| 87 |
+
acos = _mathfun(math.acos, cmath.acos)
|
| 88 |
+
asin = _mathfun(math.asin, cmath.asin)
|
| 89 |
+
atan = _mathfun_real(math.atan, cmath.atan)
|
| 90 |
+
|
| 91 |
+
cosh = _mathfun_real(math.cosh, cmath.cosh)
|
| 92 |
+
sinh = _mathfun_real(math.sinh, cmath.sinh)
|
| 93 |
+
tanh = _mathfun_real(math.tanh, cmath.tanh)
|
| 94 |
+
|
| 95 |
+
floor = _mathfun_real(math.floor,
|
| 96 |
+
lambda z: complex(math.floor(z.real), math.floor(z.imag)))
|
| 97 |
+
ceil = _mathfun_real(math.ceil,
|
| 98 |
+
lambda z: complex(math.ceil(z.real), math.ceil(z.imag)))
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
cos_sin = _mathfun_real(lambda x: (math.cos(x), math.sin(x)),
|
| 102 |
+
lambda z: (cmath.cos(z), cmath.sin(z)))
|
| 103 |
+
|
| 104 |
+
cbrt = _mathfun(lambda x: x**(1./3), lambda z: z**(1./3))
|
| 105 |
+
|
| 106 |
+
def nthroot(x, n):
|
| 107 |
+
r = 1./n
|
| 108 |
+
try:
|
| 109 |
+
return float(x) ** r
|
| 110 |
+
except (ValueError, TypeError):
|
| 111 |
+
return complex(x) ** r
|
| 112 |
+
|
| 113 |
+
def _sinpi_real(x):
|
| 114 |
+
if x < 0:
|
| 115 |
+
return -_sinpi_real(-x)
|
| 116 |
+
n, r = divmod(x, 0.5)
|
| 117 |
+
r *= pi
|
| 118 |
+
n %= 4
|
| 119 |
+
if n == 0: return math.sin(r)
|
| 120 |
+
if n == 1: return math.cos(r)
|
| 121 |
+
if n == 2: return -math.sin(r)
|
| 122 |
+
if n == 3: return -math.cos(r)
|
| 123 |
+
|
| 124 |
+
def _cospi_real(x):
|
| 125 |
+
if x < 0:
|
| 126 |
+
x = -x
|
| 127 |
+
n, r = divmod(x, 0.5)
|
| 128 |
+
r *= pi
|
| 129 |
+
n %= 4
|
| 130 |
+
if n == 0: return math.cos(r)
|
| 131 |
+
if n == 1: return -math.sin(r)
|
| 132 |
+
if n == 2: return -math.cos(r)
|
| 133 |
+
if n == 3: return math.sin(r)
|
| 134 |
+
|
| 135 |
+
def _sinpi_complex(z):
|
| 136 |
+
if z.real < 0:
|
| 137 |
+
return -_sinpi_complex(-z)
|
| 138 |
+
n, r = divmod(z.real, 0.5)
|
| 139 |
+
z = pi*complex(r, z.imag)
|
| 140 |
+
n %= 4
|
| 141 |
+
if n == 0: return cmath.sin(z)
|
| 142 |
+
if n == 1: return cmath.cos(z)
|
| 143 |
+
if n == 2: return -cmath.sin(z)
|
| 144 |
+
if n == 3: return -cmath.cos(z)
|
| 145 |
+
|
| 146 |
+
def _cospi_complex(z):
|
| 147 |
+
if z.real < 0:
|
| 148 |
+
z = -z
|
| 149 |
+
n, r = divmod(z.real, 0.5)
|
| 150 |
+
z = pi*complex(r, z.imag)
|
| 151 |
+
n %= 4
|
| 152 |
+
if n == 0: return cmath.cos(z)
|
| 153 |
+
if n == 1: return -cmath.sin(z)
|
| 154 |
+
if n == 2: return -cmath.cos(z)
|
| 155 |
+
if n == 3: return cmath.sin(z)
|
| 156 |
+
|
| 157 |
+
cospi = _mathfun_real(_cospi_real, _cospi_complex)
|
| 158 |
+
sinpi = _mathfun_real(_sinpi_real, _sinpi_complex)
|
| 159 |
+
|
| 160 |
+
def tanpi(x):
|
| 161 |
+
try:
|
| 162 |
+
return sinpi(x) / cospi(x)
|
| 163 |
+
except OverflowError:
|
| 164 |
+
if complex(x).imag > 10:
|
| 165 |
+
return 1j
|
| 166 |
+
if complex(x).imag < 10:
|
| 167 |
+
return -1j
|
| 168 |
+
raise
|
| 169 |
+
|
| 170 |
+
def cotpi(x):
|
| 171 |
+
try:
|
| 172 |
+
return cospi(x) / sinpi(x)
|
| 173 |
+
except OverflowError:
|
| 174 |
+
if complex(x).imag > 10:
|
| 175 |
+
return -1j
|
| 176 |
+
if complex(x).imag < 10:
|
| 177 |
+
return 1j
|
| 178 |
+
raise
|
| 179 |
+
|
| 180 |
+
INF = 1e300*1e300
|
| 181 |
+
NINF = -INF
|
| 182 |
+
NAN = INF-INF
|
| 183 |
+
EPS = 2.2204460492503131e-16
|
| 184 |
+
|
| 185 |
+
_exact_gamma = (INF, 1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0,
|
| 186 |
+
362880.0, 3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0,
|
| 187 |
+
1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0,
|
| 188 |
+
121645100408832000.0, 2432902008176640000.0)
|
| 189 |
+
|
| 190 |
+
_max_exact_gamma = len(_exact_gamma)-1
|
| 191 |
+
|
| 192 |
+
# Lanczos coefficients used by the GNU Scientific Library
|
| 193 |
+
_lanczos_g = 7
|
| 194 |
+
_lanczos_p = (0.99999999999980993, 676.5203681218851, -1259.1392167224028,
|
| 195 |
+
771.32342877765313, -176.61502916214059, 12.507343278686905,
|
| 196 |
+
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7)
|
| 197 |
+
|
| 198 |
+
def _gamma_real(x):
|
| 199 |
+
_intx = int(x)
|
| 200 |
+
if _intx == x:
|
| 201 |
+
if _intx <= 0:
|
| 202 |
+
#return (-1)**_intx * INF
|
| 203 |
+
raise ZeroDivisionError("gamma function pole")
|
| 204 |
+
if _intx <= _max_exact_gamma:
|
| 205 |
+
return _exact_gamma[_intx]
|
| 206 |
+
if x < 0.5:
|
| 207 |
+
# TODO: sinpi
|
| 208 |
+
return pi / (_sinpi_real(x)*_gamma_real(1-x))
|
| 209 |
+
else:
|
| 210 |
+
x -= 1.0
|
| 211 |
+
r = _lanczos_p[0]
|
| 212 |
+
for i in range(1, _lanczos_g+2):
|
| 213 |
+
r += _lanczos_p[i]/(x+i)
|
| 214 |
+
t = x + _lanczos_g + 0.5
|
| 215 |
+
return 2.506628274631000502417 * t**(x+0.5) * math.exp(-t) * r
|
| 216 |
+
|
| 217 |
+
def _gamma_complex(x):
|
| 218 |
+
if not x.imag:
|
| 219 |
+
return complex(_gamma_real(x.real))
|
| 220 |
+
if x.real < 0.5:
|
| 221 |
+
# TODO: sinpi
|
| 222 |
+
return pi / (_sinpi_complex(x)*_gamma_complex(1-x))
|
| 223 |
+
else:
|
| 224 |
+
x -= 1.0
|
| 225 |
+
r = _lanczos_p[0]
|
| 226 |
+
for i in range(1, _lanczos_g+2):
|
| 227 |
+
r += _lanczos_p[i]/(x+i)
|
| 228 |
+
t = x + _lanczos_g + 0.5
|
| 229 |
+
return 2.506628274631000502417 * t**(x+0.5) * cmath.exp(-t) * r
|
| 230 |
+
|
| 231 |
+
gamma = _mathfun_real(_gamma_real, _gamma_complex)
|
| 232 |
+
|
| 233 |
+
def rgamma(x):
|
| 234 |
+
try:
|
| 235 |
+
return 1./gamma(x)
|
| 236 |
+
except ZeroDivisionError:
|
| 237 |
+
return x*0.0
|
| 238 |
+
|
| 239 |
+
def factorial(x):
|
| 240 |
+
return gamma(x+1.0)
|
| 241 |
+
|
| 242 |
+
def arg(x):
|
| 243 |
+
if type(x) is float:
|
| 244 |
+
return math.atan2(0.0,x)
|
| 245 |
+
return math.atan2(x.imag,x.real)
|
| 246 |
+
|
| 247 |
+
# XXX: broken for negatives
|
| 248 |
+
def loggamma(x):
|
| 249 |
+
if type(x) not in (float, complex):
|
| 250 |
+
try:
|
| 251 |
+
x = float(x)
|
| 252 |
+
except (ValueError, TypeError):
|
| 253 |
+
x = complex(x)
|
| 254 |
+
try:
|
| 255 |
+
xreal = x.real
|
| 256 |
+
ximag = x.imag
|
| 257 |
+
except AttributeError: # py2.5
|
| 258 |
+
xreal = x
|
| 259 |
+
ximag = 0.0
|
| 260 |
+
# Reflection formula
|
| 261 |
+
# http://functions.wolfram.com/GammaBetaErf/LogGamma/16/01/01/0003/
|
| 262 |
+
if xreal < 0.0:
|
| 263 |
+
if abs(x) < 0.5:
|
| 264 |
+
v = log(gamma(x))
|
| 265 |
+
if ximag == 0:
|
| 266 |
+
v = v.conjugate()
|
| 267 |
+
return v
|
| 268 |
+
z = 1-x
|
| 269 |
+
try:
|
| 270 |
+
re = z.real
|
| 271 |
+
im = z.imag
|
| 272 |
+
except AttributeError: # py2.5
|
| 273 |
+
re = z
|
| 274 |
+
im = 0.0
|
| 275 |
+
refloor = floor(re)
|
| 276 |
+
if im == 0.0:
|
| 277 |
+
imsign = 0
|
| 278 |
+
elif im < 0.0:
|
| 279 |
+
imsign = -1
|
| 280 |
+
else:
|
| 281 |
+
imsign = 1
|
| 282 |
+
return (-pi*1j)*abs(refloor)*(1-abs(imsign)) + logpi - \
|
| 283 |
+
log(sinpi(z-refloor)) - loggamma(z) + 1j*pi*refloor*imsign
|
| 284 |
+
if x == 1.0 or x == 2.0:
|
| 285 |
+
return x*0
|
| 286 |
+
p = 0.
|
| 287 |
+
while abs(x) < 11:
|
| 288 |
+
p -= log(x)
|
| 289 |
+
x += 1.0
|
| 290 |
+
s = 0.918938533204672742 + (x-0.5)*log(x) - x
|
| 291 |
+
r = 1./x
|
| 292 |
+
r2 = r*r
|
| 293 |
+
s += 0.083333333333333333333*r; r *= r2
|
| 294 |
+
s += -0.0027777777777777777778*r; r *= r2
|
| 295 |
+
s += 0.00079365079365079365079*r; r *= r2
|
| 296 |
+
s += -0.0005952380952380952381*r; r *= r2
|
| 297 |
+
s += 0.00084175084175084175084*r; r *= r2
|
| 298 |
+
s += -0.0019175269175269175269*r; r *= r2
|
| 299 |
+
s += 0.0064102564102564102564*r; r *= r2
|
| 300 |
+
s += -0.02955065359477124183*r
|
| 301 |
+
return s + p
|
| 302 |
+
|
| 303 |
+
_psi_coeff = [
|
| 304 |
+
0.083333333333333333333,
|
| 305 |
+
-0.0083333333333333333333,
|
| 306 |
+
0.003968253968253968254,
|
| 307 |
+
-0.0041666666666666666667,
|
| 308 |
+
0.0075757575757575757576,
|
| 309 |
+
-0.021092796092796092796,
|
| 310 |
+
0.083333333333333333333,
|
| 311 |
+
-0.44325980392156862745,
|
| 312 |
+
3.0539543302701197438,
|
| 313 |
+
-26.456212121212121212]
|
| 314 |
+
|
| 315 |
+
def _digamma_real(x):
|
| 316 |
+
_intx = int(x)
|
| 317 |
+
if _intx == x:
|
| 318 |
+
if _intx <= 0:
|
| 319 |
+
raise ZeroDivisionError("polygamma pole")
|
| 320 |
+
if x < 0.5:
|
| 321 |
+
x = 1.0-x
|
| 322 |
+
s = pi*cotpi(x)
|
| 323 |
+
else:
|
| 324 |
+
s = 0.0
|
| 325 |
+
while x < 10.0:
|
| 326 |
+
s -= 1.0/x
|
| 327 |
+
x += 1.0
|
| 328 |
+
x2 = x**-2
|
| 329 |
+
t = x2
|
| 330 |
+
for c in _psi_coeff:
|
| 331 |
+
s -= c*t
|
| 332 |
+
if t < 1e-20:
|
| 333 |
+
break
|
| 334 |
+
t *= x2
|
| 335 |
+
return s + math_log(x) - 0.5/x
|
| 336 |
+
|
| 337 |
+
def _digamma_complex(x):
|
| 338 |
+
if not x.imag:
|
| 339 |
+
return complex(_digamma_real(x.real))
|
| 340 |
+
if x.real < 0.5:
|
| 341 |
+
x = 1.0-x
|
| 342 |
+
s = pi*cotpi(x)
|
| 343 |
+
else:
|
| 344 |
+
s = 0.0
|
| 345 |
+
while abs(x) < 10.0:
|
| 346 |
+
s -= 1.0/x
|
| 347 |
+
x += 1.0
|
| 348 |
+
x2 = x**-2
|
| 349 |
+
t = x2
|
| 350 |
+
for c in _psi_coeff:
|
| 351 |
+
s -= c*t
|
| 352 |
+
if abs(t) < 1e-20:
|
| 353 |
+
break
|
| 354 |
+
t *= x2
|
| 355 |
+
return s + cmath.log(x) - 0.5/x
|
| 356 |
+
|
| 357 |
+
digamma = _mathfun_real(_digamma_real, _digamma_complex)
|
| 358 |
+
|
| 359 |
+
# TODO: could implement complex erf and erfc here. Need
|
| 360 |
+
# to find an accurate method (avoiding cancellation)
|
| 361 |
+
# for approx. 1 < abs(x) < 9.
|
| 362 |
+
|
| 363 |
+
_erfc_coeff_P = [
|
| 364 |
+
1.0000000161203922312,
|
| 365 |
+
2.1275306946297962644,
|
| 366 |
+
2.2280433377390253297,
|
| 367 |
+
1.4695509105618423961,
|
| 368 |
+
0.66275911699770787537,
|
| 369 |
+
0.20924776504163751585,
|
| 370 |
+
0.045459713768411264339,
|
| 371 |
+
0.0063065951710717791934,
|
| 372 |
+
0.00044560259661560421715][::-1]
|
| 373 |
+
|
| 374 |
+
_erfc_coeff_Q = [
|
| 375 |
+
1.0000000000000000000,
|
| 376 |
+
3.2559100272784894318,
|
| 377 |
+
4.9019435608903239131,
|
| 378 |
+
4.4971472894498014205,
|
| 379 |
+
2.7845640601891186528,
|
| 380 |
+
1.2146026030046904138,
|
| 381 |
+
0.37647108453729465912,
|
| 382 |
+
0.080970149639040548613,
|
| 383 |
+
0.011178148899483545902,
|
| 384 |
+
0.00078981003831980423513][::-1]
|
| 385 |
+
|
| 386 |
+
def _polyval(coeffs, x):
|
| 387 |
+
p = coeffs[0]
|
| 388 |
+
for c in coeffs[1:]:
|
| 389 |
+
p = c + x*p
|
| 390 |
+
return p
|
| 391 |
+
|
| 392 |
+
def _erf_taylor(x):
|
| 393 |
+
# Taylor series assuming 0 <= x <= 1
|
| 394 |
+
x2 = x*x
|
| 395 |
+
s = t = x
|
| 396 |
+
n = 1
|
| 397 |
+
while abs(t) > 1e-17:
|
| 398 |
+
t *= x2/n
|
| 399 |
+
s -= t/(n+n+1)
|
| 400 |
+
n += 1
|
| 401 |
+
t *= x2/n
|
| 402 |
+
s += t/(n+n+1)
|
| 403 |
+
n += 1
|
| 404 |
+
return 1.1283791670955125739*s
|
| 405 |
+
|
| 406 |
+
def _erfc_mid(x):
|
| 407 |
+
# Rational approximation assuming 0 <= x <= 9
|
| 408 |
+
return exp(-x*x)*_polyval(_erfc_coeff_P,x)/_polyval(_erfc_coeff_Q,x)
|
| 409 |
+
|
| 410 |
+
def _erfc_asymp(x):
|
| 411 |
+
# Asymptotic expansion assuming x >= 9
|
| 412 |
+
x2 = x*x
|
| 413 |
+
v = exp(-x2)/x*0.56418958354775628695
|
| 414 |
+
r = t = 0.5 / x2
|
| 415 |
+
s = 1.0
|
| 416 |
+
for n in range(1,22,4):
|
| 417 |
+
s -= t
|
| 418 |
+
t *= r * (n+2)
|
| 419 |
+
s += t
|
| 420 |
+
t *= r * (n+4)
|
| 421 |
+
if abs(t) < 1e-17:
|
| 422 |
+
break
|
| 423 |
+
return s * v
|
| 424 |
+
|
| 425 |
+
def erf(x):
|
| 426 |
+
"""
|
| 427 |
+
erf of a real number.
|
| 428 |
+
"""
|
| 429 |
+
x = float(x)
|
| 430 |
+
if x != x:
|
| 431 |
+
return x
|
| 432 |
+
if x < 0.0:
|
| 433 |
+
return -erf(-x)
|
| 434 |
+
if x >= 1.0:
|
| 435 |
+
if x >= 6.0:
|
| 436 |
+
return 1.0
|
| 437 |
+
return 1.0 - _erfc_mid(x)
|
| 438 |
+
return _erf_taylor(x)
|
| 439 |
+
|
| 440 |
+
def erfc(x):
|
| 441 |
+
"""
|
| 442 |
+
erfc of a real number.
|
| 443 |
+
"""
|
| 444 |
+
x = float(x)
|
| 445 |
+
if x != x:
|
| 446 |
+
return x
|
| 447 |
+
if x < 0.0:
|
| 448 |
+
if x < -6.0:
|
| 449 |
+
return 2.0
|
| 450 |
+
return 2.0-erfc(-x)
|
| 451 |
+
if x > 9.0:
|
| 452 |
+
return _erfc_asymp(x)
|
| 453 |
+
if x >= 1.0:
|
| 454 |
+
return _erfc_mid(x)
|
| 455 |
+
return 1.0 - _erf_taylor(x)
|
| 456 |
+
|
| 457 |
+
gauss42 = [\
|
| 458 |
+
(0.99839961899006235, 0.0041059986046490839),
|
| 459 |
+
(-0.99839961899006235, 0.0041059986046490839),
|
| 460 |
+
(0.9915772883408609, 0.009536220301748501),
|
| 461 |
+
(-0.9915772883408609,0.009536220301748501),
|
| 462 |
+
(0.97934250806374812, 0.014922443697357493),
|
| 463 |
+
(-0.97934250806374812, 0.014922443697357493),
|
| 464 |
+
(0.96175936533820439,0.020227869569052644),
|
| 465 |
+
(-0.96175936533820439, 0.020227869569052644),
|
| 466 |
+
(0.93892355735498811, 0.025422959526113047),
|
| 467 |
+
(-0.93892355735498811,0.025422959526113047),
|
| 468 |
+
(0.91095972490412735, 0.030479240699603467),
|
| 469 |
+
(-0.91095972490412735, 0.030479240699603467),
|
| 470 |
+
(0.87802056981217269,0.03536907109759211),
|
| 471 |
+
(-0.87802056981217269, 0.03536907109759211),
|
| 472 |
+
(0.8402859832618168, 0.040065735180692258),
|
| 473 |
+
(-0.8402859832618168,0.040065735180692258),
|
| 474 |
+
(0.7979620532554873, 0.044543577771965874),
|
| 475 |
+
(-0.7979620532554873, 0.044543577771965874),
|
| 476 |
+
(0.75127993568948048,0.048778140792803244),
|
| 477 |
+
(-0.75127993568948048, 0.048778140792803244),
|
| 478 |
+
(0.70049459055617114, 0.052746295699174064),
|
| 479 |
+
(-0.70049459055617114,0.052746295699174064),
|
| 480 |
+
(0.64588338886924779, 0.056426369358018376),
|
| 481 |
+
(-0.64588338886924779, 0.056426369358018376),
|
| 482 |
+
(0.58774459748510932, 0.059798262227586649),
|
| 483 |
+
(-0.58774459748510932, 0.059798262227586649),
|
| 484 |
+
(0.5263957499311922, 0.062843558045002565),
|
| 485 |
+
(-0.5263957499311922, 0.062843558045002565),
|
| 486 |
+
(0.46217191207042191, 0.065545624364908975),
|
| 487 |
+
(-0.46217191207042191, 0.065545624364908975),
|
| 488 |
+
(0.39542385204297503, 0.067889703376521934),
|
| 489 |
+
(-0.39542385204297503, 0.067889703376521934),
|
| 490 |
+
(0.32651612446541151, 0.069862992492594159),
|
| 491 |
+
(-0.32651612446541151, 0.069862992492594159),
|
| 492 |
+
(0.25582507934287907, 0.071454714265170971),
|
| 493 |
+
(-0.25582507934287907, 0.071454714265170971),
|
| 494 |
+
(0.18373680656485453, 0.072656175243804091),
|
| 495 |
+
(-0.18373680656485453, 0.072656175243804091),
|
| 496 |
+
(0.11064502720851986, 0.073460813453467527),
|
| 497 |
+
(-0.11064502720851986, 0.073460813453467527),
|
| 498 |
+
(0.036948943165351772, 0.073864234232172879),
|
| 499 |
+
(-0.036948943165351772, 0.073864234232172879)]
|
| 500 |
+
|
| 501 |
+
EI_ASYMP_CONVERGENCE_RADIUS = 40.0
|
| 502 |
+
|
| 503 |
+
def ei_asymp(z, _e1=False):
|
| 504 |
+
r = 1./z
|
| 505 |
+
s = t = 1.0
|
| 506 |
+
k = 1
|
| 507 |
+
while 1:
|
| 508 |
+
t *= k*r
|
| 509 |
+
s += t
|
| 510 |
+
if abs(t) < 1e-16:
|
| 511 |
+
break
|
| 512 |
+
k += 1
|
| 513 |
+
v = s*exp(z)/z
|
| 514 |
+
if _e1:
|
| 515 |
+
if type(z) is complex:
|
| 516 |
+
zreal = z.real
|
| 517 |
+
zimag = z.imag
|
| 518 |
+
else:
|
| 519 |
+
zreal = z
|
| 520 |
+
zimag = 0.0
|
| 521 |
+
if zimag == 0.0 and zreal > 0.0:
|
| 522 |
+
v += pi*1j
|
| 523 |
+
else:
|
| 524 |
+
if type(z) is complex:
|
| 525 |
+
if z.imag > 0:
|
| 526 |
+
v += pi*1j
|
| 527 |
+
if z.imag < 0:
|
| 528 |
+
v -= pi*1j
|
| 529 |
+
return v
|
| 530 |
+
|
| 531 |
+
def ei_taylor(z, _e1=False):
|
| 532 |
+
s = t = z
|
| 533 |
+
k = 2
|
| 534 |
+
while 1:
|
| 535 |
+
t = t*z/k
|
| 536 |
+
term = t/k
|
| 537 |
+
if abs(term) < 1e-17:
|
| 538 |
+
break
|
| 539 |
+
s += term
|
| 540 |
+
k += 1
|
| 541 |
+
s += euler
|
| 542 |
+
if _e1:
|
| 543 |
+
s += log(-z)
|
| 544 |
+
else:
|
| 545 |
+
if type(z) is float or z.imag == 0.0:
|
| 546 |
+
s += math_log(abs(z))
|
| 547 |
+
else:
|
| 548 |
+
s += cmath.log(z)
|
| 549 |
+
return s
|
| 550 |
+
|
| 551 |
+
def ei(z, _e1=False):
|
| 552 |
+
typez = type(z)
|
| 553 |
+
if typez not in (float, complex):
|
| 554 |
+
try:
|
| 555 |
+
z = float(z)
|
| 556 |
+
typez = float
|
| 557 |
+
except (TypeError, ValueError):
|
| 558 |
+
z = complex(z)
|
| 559 |
+
typez = complex
|
| 560 |
+
if not z:
|
| 561 |
+
return -INF
|
| 562 |
+
absz = abs(z)
|
| 563 |
+
if absz > EI_ASYMP_CONVERGENCE_RADIUS:
|
| 564 |
+
return ei_asymp(z, _e1)
|
| 565 |
+
elif absz <= 2.0 or (typez is float and z > 0.0):
|
| 566 |
+
return ei_taylor(z, _e1)
|
| 567 |
+
# Integrate, starting from whichever is smaller of a Taylor
|
| 568 |
+
# series value or an asymptotic series value
|
| 569 |
+
if typez is complex and z.real > 0.0:
|
| 570 |
+
zref = z / absz
|
| 571 |
+
ref = ei_taylor(zref, _e1)
|
| 572 |
+
else:
|
| 573 |
+
zref = EI_ASYMP_CONVERGENCE_RADIUS * z / absz
|
| 574 |
+
ref = ei_asymp(zref, _e1)
|
| 575 |
+
C = (zref-z)*0.5
|
| 576 |
+
D = (zref+z)*0.5
|
| 577 |
+
s = 0.0
|
| 578 |
+
if type(z) is complex:
|
| 579 |
+
_exp = cmath.exp
|
| 580 |
+
else:
|
| 581 |
+
_exp = math.exp
|
| 582 |
+
for x,w in gauss42:
|
| 583 |
+
t = C*x+D
|
| 584 |
+
s += w*_exp(t)/t
|
| 585 |
+
ref -= C*s
|
| 586 |
+
return ref
|
| 587 |
+
|
| 588 |
+
def e1(z):
|
| 589 |
+
# hack to get consistent signs if the imaginary part if 0
|
| 590 |
+
# and signed
|
| 591 |
+
typez = type(z)
|
| 592 |
+
if type(z) not in (float, complex):
|
| 593 |
+
try:
|
| 594 |
+
z = float(z)
|
| 595 |
+
typez = float
|
| 596 |
+
except (TypeError, ValueError):
|
| 597 |
+
z = complex(z)
|
| 598 |
+
typez = complex
|
| 599 |
+
if typez is complex and not z.imag:
|
| 600 |
+
z = complex(z.real, 0.0)
|
| 601 |
+
# end hack
|
| 602 |
+
return -ei(-z, _e1=True)
|
| 603 |
+
|
| 604 |
+
_zeta_int = [\
|
| 605 |
+
-0.5,
|
| 606 |
+
0.0,
|
| 607 |
+
1.6449340668482264365,1.2020569031595942854,1.0823232337111381915,
|
| 608 |
+
1.0369277551433699263,1.0173430619844491397,1.0083492773819228268,
|
| 609 |
+
1.0040773561979443394,1.0020083928260822144,1.0009945751278180853,
|
| 610 |
+
1.0004941886041194646,1.0002460865533080483,1.0001227133475784891,
|
| 611 |
+
1.0000612481350587048,1.0000305882363070205,1.0000152822594086519,
|
| 612 |
+
1.0000076371976378998,1.0000038172932649998,1.0000019082127165539,
|
| 613 |
+
1.0000009539620338728,1.0000004769329867878,1.0000002384505027277,
|
| 614 |
+
1.0000001192199259653,1.0000000596081890513,1.0000000298035035147,
|
| 615 |
+
1.0000000149015548284]
|
| 616 |
+
|
| 617 |
+
_zeta_P = [-3.50000000087575873, -0.701274355654678147,
|
| 618 |
+
-0.0672313458590012612, -0.00398731457954257841,
|
| 619 |
+
-0.000160948723019303141, -4.67633010038383371e-6,
|
| 620 |
+
-1.02078104417700585e-7, -1.68030037095896287e-9,
|
| 621 |
+
-1.85231868742346722e-11][::-1]
|
| 622 |
+
|
| 623 |
+
_zeta_Q = [1.00000000000000000, -0.936552848762465319,
|
| 624 |
+
-0.0588835413263763741, -0.00441498861482948666,
|
| 625 |
+
-0.000143416758067432622, -5.10691659585090782e-6,
|
| 626 |
+
-9.58813053268913799e-8, -1.72963791443181972e-9,
|
| 627 |
+
-1.83527919681474132e-11][::-1]
|
| 628 |
+
|
| 629 |
+
_zeta_1 = [3.03768838606128127e-10, -1.21924525236601262e-8,
|
| 630 |
+
2.01201845887608893e-7, -1.53917240683468381e-6,
|
| 631 |
+
-5.09890411005967954e-7, 0.000122464707271619326,
|
| 632 |
+
-0.000905721539353130232, -0.00239315326074843037,
|
| 633 |
+
0.084239750013159168, 0.418938517907442414, 0.500000001921884009]
|
| 634 |
+
|
| 635 |
+
_zeta_0 = [-3.46092485016748794e-10, -6.42610089468292485e-9,
|
| 636 |
+
1.76409071536679773e-7, -1.47141263991560698e-6, -6.38880222546167613e-7,
|
| 637 |
+
0.000122641099800668209, -0.000905894913516772796, -0.00239303348507992713,
|
| 638 |
+
0.0842396947501199816, 0.418938533204660256, 0.500000000000000052]
|
| 639 |
+
|
| 640 |
+
def zeta(s):
|
| 641 |
+
"""
|
| 642 |
+
Riemann zeta function, real argument
|
| 643 |
+
"""
|
| 644 |
+
if not isinstance(s, (float, int)):
|
| 645 |
+
try:
|
| 646 |
+
s = float(s)
|
| 647 |
+
except (ValueError, TypeError):
|
| 648 |
+
try:
|
| 649 |
+
s = complex(s)
|
| 650 |
+
if not s.imag:
|
| 651 |
+
return complex(zeta(s.real))
|
| 652 |
+
except (ValueError, TypeError):
|
| 653 |
+
pass
|
| 654 |
+
raise NotImplementedError
|
| 655 |
+
if s == 1:
|
| 656 |
+
raise ValueError("zeta(1) pole")
|
| 657 |
+
if s >= 27:
|
| 658 |
+
return 1.0 + 2.0**(-s) + 3.0**(-s)
|
| 659 |
+
n = int(s)
|
| 660 |
+
if n == s:
|
| 661 |
+
if n >= 0:
|
| 662 |
+
return _zeta_int[n]
|
| 663 |
+
if not (n % 2):
|
| 664 |
+
return 0.0
|
| 665 |
+
if s <= 0.0:
|
| 666 |
+
return 2.**s*pi**(s-1)*_sinpi_real(0.5*s)*_gamma_real(1-s)*zeta(1-s)
|
| 667 |
+
if s <= 2.0:
|
| 668 |
+
if s <= 1.0:
|
| 669 |
+
return _polyval(_zeta_0,s)/(s-1)
|
| 670 |
+
return _polyval(_zeta_1,s)/(s-1)
|
| 671 |
+
z = _polyval(_zeta_P,s) / _polyval(_zeta_Q,s)
|
| 672 |
+
return 1.0 + 2.0**(-s) + 3.0**(-s) + 4.0**(-s)*z
|
.venv/lib/python3.11/site-packages/mpmath/rational.py
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import operator
|
| 2 |
+
import sys
|
| 3 |
+
from .libmp import int_types, mpf_hash, bitcount, from_man_exp, HASH_MODULUS
|
| 4 |
+
|
| 5 |
+
new = object.__new__
|
| 6 |
+
|
| 7 |
+
def create_reduced(p, q, _cache={}):
|
| 8 |
+
key = p, q
|
| 9 |
+
if key in _cache:
|
| 10 |
+
return _cache[key]
|
| 11 |
+
x, y = p, q
|
| 12 |
+
while y:
|
| 13 |
+
x, y = y, x % y
|
| 14 |
+
if x != 1:
|
| 15 |
+
p //= x
|
| 16 |
+
q //= x
|
| 17 |
+
v = new(mpq)
|
| 18 |
+
v._mpq_ = p, q
|
| 19 |
+
# Speedup integers, half-integers and other small fractions
|
| 20 |
+
if q <= 4 and abs(key[0]) < 100:
|
| 21 |
+
_cache[key] = v
|
| 22 |
+
return v
|
| 23 |
+
|
| 24 |
+
class mpq(object):
|
| 25 |
+
"""
|
| 26 |
+
Exact rational type, currently only intended for internal use.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
__slots__ = ["_mpq_"]
|
| 30 |
+
|
| 31 |
+
def __new__(cls, p, q=1):
|
| 32 |
+
if type(p) is tuple:
|
| 33 |
+
p, q = p
|
| 34 |
+
elif hasattr(p, '_mpq_'):
|
| 35 |
+
p, q = p._mpq_
|
| 36 |
+
return create_reduced(p, q)
|
| 37 |
+
|
| 38 |
+
def __repr__(s):
|
| 39 |
+
return "mpq(%s,%s)" % s._mpq_
|
| 40 |
+
|
| 41 |
+
def __str__(s):
|
| 42 |
+
return "(%s/%s)" % s._mpq_
|
| 43 |
+
|
| 44 |
+
def __int__(s):
|
| 45 |
+
a, b = s._mpq_
|
| 46 |
+
return a // b
|
| 47 |
+
|
| 48 |
+
def __nonzero__(s):
|
| 49 |
+
return bool(s._mpq_[0])
|
| 50 |
+
|
| 51 |
+
__bool__ = __nonzero__
|
| 52 |
+
|
| 53 |
+
def __hash__(s):
|
| 54 |
+
a, b = s._mpq_
|
| 55 |
+
if sys.version_info >= (3, 2):
|
| 56 |
+
inverse = pow(b, HASH_MODULUS-2, HASH_MODULUS)
|
| 57 |
+
if not inverse:
|
| 58 |
+
h = sys.hash_info.inf
|
| 59 |
+
else:
|
| 60 |
+
h = (abs(a) * inverse) % HASH_MODULUS
|
| 61 |
+
if a < 0: h = -h
|
| 62 |
+
if h == -1: h = -2
|
| 63 |
+
return h
|
| 64 |
+
else:
|
| 65 |
+
if b == 1:
|
| 66 |
+
return hash(a)
|
| 67 |
+
# Power of two: mpf compatible hash
|
| 68 |
+
if not (b & (b-1)):
|
| 69 |
+
return mpf_hash(from_man_exp(a, 1-bitcount(b)))
|
| 70 |
+
return hash((a,b))
|
| 71 |
+
|
| 72 |
+
def __eq__(s, t):
|
| 73 |
+
ttype = type(t)
|
| 74 |
+
if ttype is mpq:
|
| 75 |
+
return s._mpq_ == t._mpq_
|
| 76 |
+
if ttype in int_types:
|
| 77 |
+
a, b = s._mpq_
|
| 78 |
+
if b != 1:
|
| 79 |
+
return False
|
| 80 |
+
return a == t
|
| 81 |
+
return NotImplemented
|
| 82 |
+
|
| 83 |
+
def __ne__(s, t):
|
| 84 |
+
ttype = type(t)
|
| 85 |
+
if ttype is mpq:
|
| 86 |
+
return s._mpq_ != t._mpq_
|
| 87 |
+
if ttype in int_types:
|
| 88 |
+
a, b = s._mpq_
|
| 89 |
+
if b != 1:
|
| 90 |
+
return True
|
| 91 |
+
return a != t
|
| 92 |
+
return NotImplemented
|
| 93 |
+
|
| 94 |
+
def _cmp(s, t, op):
|
| 95 |
+
ttype = type(t)
|
| 96 |
+
if ttype in int_types:
|
| 97 |
+
a, b = s._mpq_
|
| 98 |
+
return op(a, t*b)
|
| 99 |
+
if ttype is mpq:
|
| 100 |
+
a, b = s._mpq_
|
| 101 |
+
c, d = t._mpq_
|
| 102 |
+
return op(a*d, b*c)
|
| 103 |
+
return NotImplementedError
|
| 104 |
+
|
| 105 |
+
def __lt__(s, t): return s._cmp(t, operator.lt)
|
| 106 |
+
def __le__(s, t): return s._cmp(t, operator.le)
|
| 107 |
+
def __gt__(s, t): return s._cmp(t, operator.gt)
|
| 108 |
+
def __ge__(s, t): return s._cmp(t, operator.ge)
|
| 109 |
+
|
| 110 |
+
def __abs__(s):
|
| 111 |
+
a, b = s._mpq_
|
| 112 |
+
if a >= 0:
|
| 113 |
+
return s
|
| 114 |
+
v = new(mpq)
|
| 115 |
+
v._mpq_ = -a, b
|
| 116 |
+
return v
|
| 117 |
+
|
| 118 |
+
def __neg__(s):
|
| 119 |
+
a, b = s._mpq_
|
| 120 |
+
v = new(mpq)
|
| 121 |
+
v._mpq_ = -a, b
|
| 122 |
+
return v
|
| 123 |
+
|
| 124 |
+
def __pos__(s):
|
| 125 |
+
return s
|
| 126 |
+
|
| 127 |
+
def __add__(s, t):
|
| 128 |
+
ttype = type(t)
|
| 129 |
+
if ttype is mpq:
|
| 130 |
+
a, b = s._mpq_
|
| 131 |
+
c, d = t._mpq_
|
| 132 |
+
return create_reduced(a*d+b*c, b*d)
|
| 133 |
+
if ttype in int_types:
|
| 134 |
+
a, b = s._mpq_
|
| 135 |
+
v = new(mpq)
|
| 136 |
+
v._mpq_ = a+b*t, b
|
| 137 |
+
return v
|
| 138 |
+
return NotImplemented
|
| 139 |
+
|
| 140 |
+
__radd__ = __add__
|
| 141 |
+
|
| 142 |
+
def __sub__(s, t):
|
| 143 |
+
ttype = type(t)
|
| 144 |
+
if ttype is mpq:
|
| 145 |
+
a, b = s._mpq_
|
| 146 |
+
c, d = t._mpq_
|
| 147 |
+
return create_reduced(a*d-b*c, b*d)
|
| 148 |
+
if ttype in int_types:
|
| 149 |
+
a, b = s._mpq_
|
| 150 |
+
v = new(mpq)
|
| 151 |
+
v._mpq_ = a-b*t, b
|
| 152 |
+
return v
|
| 153 |
+
return NotImplemented
|
| 154 |
+
|
| 155 |
+
def __rsub__(s, t):
|
| 156 |
+
ttype = type(t)
|
| 157 |
+
if ttype is mpq:
|
| 158 |
+
a, b = s._mpq_
|
| 159 |
+
c, d = t._mpq_
|
| 160 |
+
return create_reduced(b*c-a*d, b*d)
|
| 161 |
+
if ttype in int_types:
|
| 162 |
+
a, b = s._mpq_
|
| 163 |
+
v = new(mpq)
|
| 164 |
+
v._mpq_ = b*t-a, b
|
| 165 |
+
return v
|
| 166 |
+
return NotImplemented
|
| 167 |
+
|
| 168 |
+
def __mul__(s, t):
|
| 169 |
+
ttype = type(t)
|
| 170 |
+
if ttype is mpq:
|
| 171 |
+
a, b = s._mpq_
|
| 172 |
+
c, d = t._mpq_
|
| 173 |
+
return create_reduced(a*c, b*d)
|
| 174 |
+
if ttype in int_types:
|
| 175 |
+
a, b = s._mpq_
|
| 176 |
+
return create_reduced(a*t, b)
|
| 177 |
+
return NotImplemented
|
| 178 |
+
|
| 179 |
+
__rmul__ = __mul__
|
| 180 |
+
|
| 181 |
+
def __div__(s, t):
|
| 182 |
+
ttype = type(t)
|
| 183 |
+
if ttype is mpq:
|
| 184 |
+
a, b = s._mpq_
|
| 185 |
+
c, d = t._mpq_
|
| 186 |
+
return create_reduced(a*d, b*c)
|
| 187 |
+
if ttype in int_types:
|
| 188 |
+
a, b = s._mpq_
|
| 189 |
+
return create_reduced(a, b*t)
|
| 190 |
+
return NotImplemented
|
| 191 |
+
|
| 192 |
+
def __rdiv__(s, t):
|
| 193 |
+
ttype = type(t)
|
| 194 |
+
if ttype is mpq:
|
| 195 |
+
a, b = s._mpq_
|
| 196 |
+
c, d = t._mpq_
|
| 197 |
+
return create_reduced(b*c, a*d)
|
| 198 |
+
if ttype in int_types:
|
| 199 |
+
a, b = s._mpq_
|
| 200 |
+
return create_reduced(b*t, a)
|
| 201 |
+
return NotImplemented
|
| 202 |
+
|
| 203 |
+
def __pow__(s, t):
|
| 204 |
+
ttype = type(t)
|
| 205 |
+
if ttype in int_types:
|
| 206 |
+
a, b = s._mpq_
|
| 207 |
+
if t:
|
| 208 |
+
if t < 0:
|
| 209 |
+
a, b, t = b, a, -t
|
| 210 |
+
v = new(mpq)
|
| 211 |
+
v._mpq_ = a**t, b**t
|
| 212 |
+
return v
|
| 213 |
+
raise ZeroDivisionError
|
| 214 |
+
return NotImplemented
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
mpq_1 = mpq((1,1))
|
| 218 |
+
mpq_0 = mpq((0,1))
|
| 219 |
+
mpq_1_2 = mpq((1,2))
|
| 220 |
+
mpq_3_2 = mpq((3,2))
|
| 221 |
+
mpq_1_4 = mpq((1,4))
|
| 222 |
+
mpq_1_16 = mpq((1,16))
|
| 223 |
+
mpq_3_16 = mpq((3,16))
|
| 224 |
+
mpq_5_2 = mpq((5,2))
|
| 225 |
+
mpq_3_4 = mpq((3,4))
|
| 226 |
+
mpq_7_4 = mpq((7,4))
|
| 227 |
+
mpq_5_4 = mpq((5,4))
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
# Register with "numbers" ABC
|
| 231 |
+
# We do not subclass, hence we do not use the @abstractmethod checks. While
|
| 232 |
+
# this is less invasive it may turn out that we do not actually support
|
| 233 |
+
# parts of the expected interfaces. See
|
| 234 |
+
# http://docs.python.org/2/library/numbers.html for list of abstract
|
| 235 |
+
# methods.
|
| 236 |
+
try:
|
| 237 |
+
import numbers
|
| 238 |
+
numbers.Rational.register(mpq)
|
| 239 |
+
except ImportError:
|
| 240 |
+
pass
|
.venv/lib/python3.11/site-packages/mpmath/tests/test_calculus.py
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
from mpmath import *
|
| 3 |
+
|
| 4 |
+
def test_approximation():
|
| 5 |
+
mp.dps = 15
|
| 6 |
+
f = lambda x: cos(2-2*x)/x
|
| 7 |
+
p, err = chebyfit(f, [2, 4], 8, error=True)
|
| 8 |
+
assert err < 1e-5
|
| 9 |
+
for i in range(10):
|
| 10 |
+
x = 2 + i/5.
|
| 11 |
+
assert abs(polyval(p, x) - f(x)) < err
|
| 12 |
+
|
| 13 |
+
def test_limits():
|
| 14 |
+
mp.dps = 15
|
| 15 |
+
assert limit(lambda x: (x-sin(x))/x**3, 0).ae(mpf(1)/6)
|
| 16 |
+
assert limit(lambda n: (1+1/n)**n, inf).ae(e)
|
| 17 |
+
|
| 18 |
+
def test_polyval():
|
| 19 |
+
assert polyval([], 3) == 0
|
| 20 |
+
assert polyval([0], 3) == 0
|
| 21 |
+
assert polyval([5], 3) == 5
|
| 22 |
+
# 4x^3 - 2x + 5
|
| 23 |
+
p = [4, 0, -2, 5]
|
| 24 |
+
assert polyval(p,4) == 253
|
| 25 |
+
assert polyval(p,4,derivative=True) == (253, 190)
|
| 26 |
+
|
| 27 |
+
def test_polyroots():
|
| 28 |
+
p = polyroots([1,-4])
|
| 29 |
+
assert p[0].ae(4)
|
| 30 |
+
p, q = polyroots([1,2,3])
|
| 31 |
+
assert p.ae(-1 - sqrt(2)*j)
|
| 32 |
+
assert q.ae(-1 + sqrt(2)*j)
|
| 33 |
+
#this is not a real test, it only tests a specific case
|
| 34 |
+
assert polyroots([1]) == []
|
| 35 |
+
pytest.raises(ValueError, lambda: polyroots([0]))
|
| 36 |
+
|
| 37 |
+
def test_polyroots_legendre():
|
| 38 |
+
n = 64
|
| 39 |
+
coeffs = [11975573020964041433067793888190275875, 0,
|
| 40 |
+
-190100434726484311252477736051902332000, 0,
|
| 41 |
+
1437919688271127330313741595496589239248, 0,
|
| 42 |
+
-6897338342113537600691931230430793911840, 0,
|
| 43 |
+
23556405536185284408974715545252277554280, 0,
|
| 44 |
+
-60969520211303089058522793175947071316960, 0,
|
| 45 |
+
124284021969194758465450309166353645376880, 0,
|
| 46 |
+
-204721258548015217049921875719981284186016, 0,
|
| 47 |
+
277415422258095841688223780704620656114900, 0,
|
| 48 |
+
-313237834141273382807123548182995095192800, 0,
|
| 49 |
+
297432255354328395601259515935229287637200, 0,
|
| 50 |
+
-239057700565161140389797367947941296605600, 0,
|
| 51 |
+
163356095386193445933028201431093219347160, 0,
|
| 52 |
+
-95158890516229191805647495979277603503200, 0,
|
| 53 |
+
47310254620162038075933656063247634556400, 0,
|
| 54 |
+
-20071017111583894941305187420771723751200, 0,
|
| 55 |
+
7255051932731034189479516844750603752850, 0,
|
| 56 |
+
-2228176940331017311443863996901733412640, 0,
|
| 57 |
+
579006552594977616773047095969088431600, 0,
|
| 58 |
+
-126584428502545713788439446082310831200, 0,
|
| 59 |
+
23112325428835593809686977515028663000, 0,
|
| 60 |
+
-3491517141958743235617737161547844000, 0,
|
| 61 |
+
431305058712550634988073414073557200, 0,
|
| 62 |
+
-42927166660756742088912492757452000, 0,
|
| 63 |
+
3378527005707706553294038781836500, 0,
|
| 64 |
+
-205277590220215081719131470288800, 0,
|
| 65 |
+
9330799555464321896324157740400, 0,
|
| 66 |
+
-304114948474392713657972548576, 0,
|
| 67 |
+
6695289961520387531608984680, 0,
|
| 68 |
+
-91048139350447232095702560, 0,
|
| 69 |
+
659769125727878493447120, 0,
|
| 70 |
+
-1905929106580294155360, 0,
|
| 71 |
+
916312070471295267]
|
| 72 |
+
|
| 73 |
+
with mp.workdps(3):
|
| 74 |
+
with pytest.raises(mp.NoConvergence):
|
| 75 |
+
polyroots(coeffs, maxsteps=5, cleanup=True, error=False,
|
| 76 |
+
extraprec=n*10)
|
| 77 |
+
|
| 78 |
+
roots = polyroots(coeffs, maxsteps=50, cleanup=True, error=False,
|
| 79 |
+
extraprec=n*10)
|
| 80 |
+
roots = [str(r) for r in roots]
|
| 81 |
+
assert roots == \
|
| 82 |
+
['-0.999', '-0.996', '-0.991', '-0.983', '-0.973', '-0.961',
|
| 83 |
+
'-0.946', '-0.93', '-0.911', '-0.889', '-0.866', '-0.841',
|
| 84 |
+
'-0.813', '-0.784', '-0.753', '-0.72', '-0.685', '-0.649',
|
| 85 |
+
'-0.611', '-0.572', '-0.531', '-0.489', '-0.446', '-0.402',
|
| 86 |
+
'-0.357', '-0.311', '-0.265', '-0.217', '-0.17', '-0.121',
|
| 87 |
+
'-0.073', '-0.0243', '0.0243', '0.073', '0.121', '0.17', '0.217',
|
| 88 |
+
'0.265', '0.311', '0.357', '0.402', '0.446', '0.489', '0.531',
|
| 89 |
+
'0.572', '0.611', '0.649', '0.685', '0.72', '0.753', '0.784',
|
| 90 |
+
'0.813', '0.841', '0.866', '0.889', '0.911', '0.93', '0.946',
|
| 91 |
+
'0.961', '0.973', '0.983', '0.991', '0.996', '0.999']
|
| 92 |
+
|
| 93 |
+
def test_polyroots_legendre_init():
|
| 94 |
+
extra_prec = 100
|
| 95 |
+
coeffs = [11975573020964041433067793888190275875, 0,
|
| 96 |
+
-190100434726484311252477736051902332000, 0,
|
| 97 |
+
1437919688271127330313741595496589239248, 0,
|
| 98 |
+
-6897338342113537600691931230430793911840, 0,
|
| 99 |
+
23556405536185284408974715545252277554280, 0,
|
| 100 |
+
-60969520211303089058522793175947071316960, 0,
|
| 101 |
+
124284021969194758465450309166353645376880, 0,
|
| 102 |
+
-204721258548015217049921875719981284186016, 0,
|
| 103 |
+
277415422258095841688223780704620656114900, 0,
|
| 104 |
+
-313237834141273382807123548182995095192800, 0,
|
| 105 |
+
297432255354328395601259515935229287637200, 0,
|
| 106 |
+
-239057700565161140389797367947941296605600, 0,
|
| 107 |
+
163356095386193445933028201431093219347160, 0,
|
| 108 |
+
-95158890516229191805647495979277603503200, 0,
|
| 109 |
+
47310254620162038075933656063247634556400, 0,
|
| 110 |
+
-20071017111583894941305187420771723751200, 0,
|
| 111 |
+
7255051932731034189479516844750603752850, 0,
|
| 112 |
+
-2228176940331017311443863996901733412640, 0,
|
| 113 |
+
579006552594977616773047095969088431600, 0,
|
| 114 |
+
-126584428502545713788439446082310831200, 0,
|
| 115 |
+
23112325428835593809686977515028663000, 0,
|
| 116 |
+
-3491517141958743235617737161547844000, 0,
|
| 117 |
+
431305058712550634988073414073557200, 0,
|
| 118 |
+
-42927166660756742088912492757452000, 0,
|
| 119 |
+
3378527005707706553294038781836500, 0,
|
| 120 |
+
-205277590220215081719131470288800, 0,
|
| 121 |
+
9330799555464321896324157740400, 0,
|
| 122 |
+
-304114948474392713657972548576, 0,
|
| 123 |
+
6695289961520387531608984680, 0,
|
| 124 |
+
-91048139350447232095702560, 0,
|
| 125 |
+
659769125727878493447120, 0,
|
| 126 |
+
-1905929106580294155360, 0,
|
| 127 |
+
916312070471295267]
|
| 128 |
+
|
| 129 |
+
roots_init = matrix(['-0.999', '-0.996', '-0.991', '-0.983', '-0.973',
|
| 130 |
+
'-0.961', '-0.946', '-0.93', '-0.911', '-0.889',
|
| 131 |
+
'-0.866', '-0.841', '-0.813', '-0.784', '-0.753',
|
| 132 |
+
'-0.72', '-0.685', '-0.649', '-0.611', '-0.572',
|
| 133 |
+
'-0.531', '-0.489', '-0.446', '-0.402', '-0.357',
|
| 134 |
+
'-0.311', '-0.265', '-0.217', '-0.17', '-0.121',
|
| 135 |
+
'-0.073', '-0.0243', '0.0243', '0.073', '0.121',
|
| 136 |
+
'0.17', '0.217', '0.265', ' 0.311', '0.357',
|
| 137 |
+
'0.402', '0.446', '0.489', '0.531', '0.572',
|
| 138 |
+
'0.611', '0.649', '0.685', '0.72', '0.753',
|
| 139 |
+
'0.784', '0.813', '0.841', '0.866', '0.889',
|
| 140 |
+
'0.911', '0.93', '0.946', '0.961', '0.973',
|
| 141 |
+
'0.983', '0.991', '0.996', '0.999', '1.0'])
|
| 142 |
+
with mp.workdps(2*mp.dps):
|
| 143 |
+
roots_exact = polyroots(coeffs, maxsteps=50, cleanup=True, error=False,
|
| 144 |
+
extraprec=2*extra_prec)
|
| 145 |
+
with pytest.raises(mp.NoConvergence):
|
| 146 |
+
polyroots(coeffs, maxsteps=5, cleanup=True, error=False,
|
| 147 |
+
extraprec=extra_prec)
|
| 148 |
+
roots,err = polyroots(coeffs, maxsteps=5, cleanup=True, error=True,
|
| 149 |
+
extraprec=extra_prec,roots_init=roots_init)
|
| 150 |
+
assert max(matrix(roots_exact)-matrix(roots).apply(abs)) < err
|
| 151 |
+
roots1,err1 = polyroots(coeffs, maxsteps=25, cleanup=True, error=True,
|
| 152 |
+
extraprec=extra_prec,roots_init=roots_init[:60])
|
| 153 |
+
assert max(matrix(roots_exact)-matrix(roots1).apply(abs)) < err1
|
| 154 |
+
|
| 155 |
+
def test_pade():
|
| 156 |
+
one = mpf(1)
|
| 157 |
+
mp.dps = 20
|
| 158 |
+
N = 10
|
| 159 |
+
a = [one]
|
| 160 |
+
k = 1
|
| 161 |
+
for i in range(1, N+1):
|
| 162 |
+
k *= i
|
| 163 |
+
a.append(one/k)
|
| 164 |
+
p, q = pade(a, N//2, N//2)
|
| 165 |
+
for x in arange(0, 1, 0.1):
|
| 166 |
+
r = polyval(p[::-1], x)/polyval(q[::-1], x)
|
| 167 |
+
assert(r.ae(exp(x), 1.0e-10))
|
| 168 |
+
mp.dps = 15
|
| 169 |
+
|
| 170 |
+
def test_fourier():
|
| 171 |
+
mp.dps = 15
|
| 172 |
+
c, s = fourier(lambda x: x+1, [-1, 2], 2)
|
| 173 |
+
#plot([lambda x: x+1, lambda x: fourierval((c, s), [-1, 2], x)], [-1, 2])
|
| 174 |
+
assert c[0].ae(1.5)
|
| 175 |
+
assert c[1].ae(-3*sqrt(3)/(2*pi))
|
| 176 |
+
assert c[2].ae(3*sqrt(3)/(4*pi))
|
| 177 |
+
assert s[0] == 0
|
| 178 |
+
assert s[1].ae(3/(2*pi))
|
| 179 |
+
assert s[2].ae(3/(4*pi))
|
| 180 |
+
assert fourierval((c, s), [-1, 2], 1).ae(1.9134966715663442)
|
| 181 |
+
|
| 182 |
+
def test_differint():
|
| 183 |
+
mp.dps = 15
|
| 184 |
+
assert differint(lambda t: t, 2, -0.5).ae(8*sqrt(2/pi)/3)
|
| 185 |
+
|
| 186 |
+
def test_invlap():
|
| 187 |
+
mp.dps = 15
|
| 188 |
+
t = 0.01
|
| 189 |
+
fp = lambda p: 1/(p+1)**2
|
| 190 |
+
ft = lambda t: t*exp(-t)
|
| 191 |
+
ftt = ft(t)
|
| 192 |
+
assert invertlaplace(fp,t,method='talbot').ae(ftt)
|
| 193 |
+
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
|
| 194 |
+
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
|
| 195 |
+
assert invertlaplace(fp,t,method='cohen').ae(ftt)
|
| 196 |
+
t = 1.0
|
| 197 |
+
ftt = ft(t)
|
| 198 |
+
assert invertlaplace(fp,t,method='talbot').ae(ftt)
|
| 199 |
+
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
|
| 200 |
+
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
|
| 201 |
+
assert invertlaplace(fp,t,method='cohen').ae(ftt)
|
| 202 |
+
|
| 203 |
+
t = 0.01
|
| 204 |
+
fp = lambda p: log(p)/p
|
| 205 |
+
ft = lambda t: -euler-log(t)
|
| 206 |
+
ftt = ft(t)
|
| 207 |
+
assert invertlaplace(fp,t,method='talbot').ae(ftt)
|
| 208 |
+
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
|
| 209 |
+
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
|
| 210 |
+
assert invertlaplace(fp,t,method='cohen').ae(ftt)
|
| 211 |
+
t = 1.0
|
| 212 |
+
ftt = ft(t)
|
| 213 |
+
assert invertlaplace(fp,t,method='talbot').ae(ftt)
|
| 214 |
+
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
|
| 215 |
+
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
|
| 216 |
+
assert invertlaplace(fp,t,method='cohen').ae(ftt)
|
.venv/lib/python3.11/site-packages/mpmath/tests/test_division.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from mpmath.libmp import *
|
| 2 |
+
from mpmath import mpf, mp
|
| 3 |
+
|
| 4 |
+
from random import randint, choice, seed
|
| 5 |
+
|
| 6 |
+
all_modes = [round_floor, round_ceiling, round_down, round_up, round_nearest]
|
| 7 |
+
|
| 8 |
+
fb = from_bstr
|
| 9 |
+
fi = from_int
|
| 10 |
+
ff = from_float
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def test_div_1_3():
|
| 14 |
+
a = fi(1)
|
| 15 |
+
b = fi(3)
|
| 16 |
+
c = fi(-1)
|
| 17 |
+
|
| 18 |
+
# floor rounds down, ceiling rounds up
|
| 19 |
+
assert mpf_div(a, b, 7, round_floor) == fb('0.01010101')
|
| 20 |
+
assert mpf_div(a, b, 7, round_ceiling) == fb('0.01010110')
|
| 21 |
+
assert mpf_div(a, b, 7, round_down) == fb('0.01010101')
|
| 22 |
+
assert mpf_div(a, b, 7, round_up) == fb('0.01010110')
|
| 23 |
+
assert mpf_div(a, b, 7, round_nearest) == fb('0.01010101')
|
| 24 |
+
|
| 25 |
+
# floor rounds up, ceiling rounds down
|
| 26 |
+
assert mpf_div(c, b, 7, round_floor) == fb('-0.01010110')
|
| 27 |
+
assert mpf_div(c, b, 7, round_ceiling) == fb('-0.01010101')
|
| 28 |
+
assert mpf_div(c, b, 7, round_down) == fb('-0.01010101')
|
| 29 |
+
assert mpf_div(c, b, 7, round_up) == fb('-0.01010110')
|
| 30 |
+
assert mpf_div(c, b, 7, round_nearest) == fb('-0.01010101')
|
| 31 |
+
|
| 32 |
+
def test_mpf_divi_1_3():
|
| 33 |
+
a = 1
|
| 34 |
+
b = fi(3)
|
| 35 |
+
c = -1
|
| 36 |
+
assert mpf_rdiv_int(a, b, 7, round_floor) == fb('0.01010101')
|
| 37 |
+
assert mpf_rdiv_int(a, b, 7, round_ceiling) == fb('0.01010110')
|
| 38 |
+
assert mpf_rdiv_int(a, b, 7, round_down) == fb('0.01010101')
|
| 39 |
+
assert mpf_rdiv_int(a, b, 7, round_up) == fb('0.01010110')
|
| 40 |
+
assert mpf_rdiv_int(a, b, 7, round_nearest) == fb('0.01010101')
|
| 41 |
+
assert mpf_rdiv_int(c, b, 7, round_floor) == fb('-0.01010110')
|
| 42 |
+
assert mpf_rdiv_int(c, b, 7, round_ceiling) == fb('-0.01010101')
|
| 43 |
+
assert mpf_rdiv_int(c, b, 7, round_down) == fb('-0.01010101')
|
| 44 |
+
assert mpf_rdiv_int(c, b, 7, round_up) == fb('-0.01010110')
|
| 45 |
+
assert mpf_rdiv_int(c, b, 7, round_nearest) == fb('-0.01010101')
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def test_div_300():
|
| 49 |
+
|
| 50 |
+
q = fi(1000000)
|
| 51 |
+
a = fi(300499999) # a/q is a little less than a half-integer
|
| 52 |
+
b = fi(300500000) # b/q exactly a half-integer
|
| 53 |
+
c = fi(300500001) # c/q is a little more than a half-integer
|
| 54 |
+
|
| 55 |
+
# Check nearest integer rounding (prec=9 as 2**8 < 300 < 2**9)
|
| 56 |
+
|
| 57 |
+
assert mpf_div(a, q, 9, round_down) == fi(300)
|
| 58 |
+
assert mpf_div(b, q, 9, round_down) == fi(300)
|
| 59 |
+
assert mpf_div(c, q, 9, round_down) == fi(300)
|
| 60 |
+
assert mpf_div(a, q, 9, round_up) == fi(301)
|
| 61 |
+
assert mpf_div(b, q, 9, round_up) == fi(301)
|
| 62 |
+
assert mpf_div(c, q, 9, round_up) == fi(301)
|
| 63 |
+
|
| 64 |
+
# Nearest even integer is down
|
| 65 |
+
assert mpf_div(a, q, 9, round_nearest) == fi(300)
|
| 66 |
+
assert mpf_div(b, q, 9, round_nearest) == fi(300)
|
| 67 |
+
assert mpf_div(c, q, 9, round_nearest) == fi(301)
|
| 68 |
+
|
| 69 |
+
# Nearest even integer is up
|
| 70 |
+
a = fi(301499999)
|
| 71 |
+
b = fi(301500000)
|
| 72 |
+
c = fi(301500001)
|
| 73 |
+
assert mpf_div(a, q, 9, round_nearest) == fi(301)
|
| 74 |
+
assert mpf_div(b, q, 9, round_nearest) == fi(302)
|
| 75 |
+
assert mpf_div(c, q, 9, round_nearest) == fi(302)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def test_tight_integer_division():
|
| 79 |
+
# Test that integer division at tightest possible precision is exact
|
| 80 |
+
N = 100
|
| 81 |
+
seed(1)
|
| 82 |
+
for i in range(N):
|
| 83 |
+
a = choice([1, -1]) * randint(1, 1<<randint(10, 100))
|
| 84 |
+
b = choice([1, -1]) * randint(1, 1<<randint(10, 100))
|
| 85 |
+
p = a * b
|
| 86 |
+
width = bitcount(abs(b)) - trailing(b)
|
| 87 |
+
a = fi(a); b = fi(b); p = fi(p)
|
| 88 |
+
for mode in all_modes:
|
| 89 |
+
assert mpf_div(p, a, width, mode) == b
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def test_epsilon_rounding():
|
| 93 |
+
# Verify that mpf_div uses infinite precision; this result will
|
| 94 |
+
# appear to be exactly 0.101 to a near-sighted algorithm
|
| 95 |
+
|
| 96 |
+
a = fb('0.101' + ('0'*200) + '1')
|
| 97 |
+
b = fb('1.10101')
|
| 98 |
+
c = mpf_mul(a, b, 250, round_floor) # exact
|
| 99 |
+
assert mpf_div(c, b, bitcount(a[1]), round_floor) == a # exact
|
| 100 |
+
|
| 101 |
+
assert mpf_div(c, b, 2, round_down) == fb('0.10')
|
| 102 |
+
assert mpf_div(c, b, 3, round_down) == fb('0.101')
|
| 103 |
+
assert mpf_div(c, b, 2, round_up) == fb('0.11')
|
| 104 |
+
assert mpf_div(c, b, 3, round_up) == fb('0.110')
|
| 105 |
+
assert mpf_div(c, b, 2, round_floor) == fb('0.10')
|
| 106 |
+
assert mpf_div(c, b, 3, round_floor) == fb('0.101')
|
| 107 |
+
assert mpf_div(c, b, 2, round_ceiling) == fb('0.11')
|
| 108 |
+
assert mpf_div(c, b, 3, round_ceiling) == fb('0.110')
|
| 109 |
+
|
| 110 |
+
# The same for negative numbers
|
| 111 |
+
a = fb('-0.101' + ('0'*200) + '1')
|
| 112 |
+
b = fb('1.10101')
|
| 113 |
+
c = mpf_mul(a, b, 250, round_floor)
|
| 114 |
+
assert mpf_div(c, b, bitcount(a[1]), round_floor) == a
|
| 115 |
+
|
| 116 |
+
assert mpf_div(c, b, 2, round_down) == fb('-0.10')
|
| 117 |
+
assert mpf_div(c, b, 3, round_up) == fb('-0.110')
|
| 118 |
+
|
| 119 |
+
# Floor goes up, ceiling goes down
|
| 120 |
+
assert mpf_div(c, b, 2, round_floor) == fb('-0.11')
|
| 121 |
+
assert mpf_div(c, b, 3, round_floor) == fb('-0.110')
|
| 122 |
+
assert mpf_div(c, b, 2, round_ceiling) == fb('-0.10')
|
| 123 |
+
assert mpf_div(c, b, 3, round_ceiling) == fb('-0.101')
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def test_mod():
|
| 127 |
+
mp.dps = 15
|
| 128 |
+
assert mpf(234) % 1 == 0
|
| 129 |
+
assert mpf(-3) % 256 == 253
|
| 130 |
+
assert mpf(0.25) % 23490.5 == 0.25
|
| 131 |
+
assert mpf(0.25) % -23490.5 == -23490.25
|
| 132 |
+
assert mpf(-0.25) % 23490.5 == 23490.25
|
| 133 |
+
assert mpf(-0.25) % -23490.5 == -0.25
|
| 134 |
+
# Check that these cases are handled efficiently
|
| 135 |
+
assert mpf('1e10000000000') % 1 == 0
|
| 136 |
+
assert mpf('1.23e-1000000000') % 1 == mpf('1.23e-1000000000')
|
| 137 |
+
# test __rmod__
|
| 138 |
+
assert 3 % mpf('1.75') == 1.25
|
| 139 |
+
|
| 140 |
+
def test_div_negative_rnd_bug():
|
| 141 |
+
mp.dps = 15
|
| 142 |
+
assert (-3) / mpf('0.1531879017645047') == mpf('-19.583791966887116')
|
| 143 |
+
assert mpf('-2.6342475750861301') / mpf('0.35126216427941814') == mpf('-7.4993775104985909')
|