pax_global_header00006660000000000000000000000064134037524560014523gustar00rootroot0000000000000052 comment=475527a7b5d373d702021d4cd11a0b43ba29eb48 mpmath-1.1.0/000077500000000000000000000000001340375245600130105ustar00rootroot00000000000000mpmath-1.1.0/.gitattributes000066400000000000000000000000531340375245600157010ustar00rootroot00000000000000* text=auto *.py diff=python text mpmath-1.1.0/.gitignore000066400000000000000000000020461340375245600150020ustar00rootroot00000000000000# This file tells git what files to ignore (e.g., you won't see them as # untracked with "git status"). Add anything to it that can be cleared # without any worry (e.g., by "git clean -Xdf"), because it can be # regenerated. Lines beginning with # are comments. You can also ignore # files on a per-repository basis by modifying the core.excludesfile # configuration option (see "git help config"). If you need to make git # track a file that is ignored for some reason, you have to use # "git add -f". See "git help gitignore" for more information. # Regular Python bytecode file *.pyc # Optimized Python bytecode file *.pyo # Vim's swap files *.sw[op] # Generated files from Jython *$py.class # File generated by setup.py using MANIFEST.in MANIFEST # Generated by ctags (used to improve autocompletion in vim) tags my/ # Files generated by setup.py dist/ build/ # Tox files .tox/ # Mac OS X Junk .DS_Store # Backup files *~ .cache/ .coverage doc/source/_build/ # Pytest cache .pytest_cache/ # Files generated by setupegg.py mpmath.egg-info/ mpmath-1.1.0/.travis.yml000066400000000000000000000005071340375245600151230ustar00rootroot00000000000000language: python sudo: false python: - 2.7 - 3.3 - 3.4 - 3.5 - 3.6 - 3.7-dev - pypy - pypy3.5 install: - pip install pep8 - pip install -e . script: # Guard against invalid escapes in strings, like '\s'. - python -We:invalid -m compileall -f mpmath -q - pep8 - py.test notifications: email: false mpmath-1.1.0/CHANGES000066400000000000000000001221311340375245600140030ustar00rootroot00000000000000--1.1.0-- Released December 11, 2018 Bugs: * Fixed severe bug in householder() for complex matrices (Michael Kagalenko) * Fixed frequently-reported bug where findroot() mysteriously raised UnboundLocalError (Sergey B Kirpichev) * Corrected rounding in binary-to-decimal conversion above 500 digits * Fixed minor loss of accuracy affecting rf(), ff(), binomial(), beta() * Fixed incorrect computation of the Hurwitz zeta function in some cases * Fixed accuracy of digamma function near 0 * Fixed RuntimeError in qfac() in Python 3.7 caused by raising StopIteration (Zbigniew Jędrzejewski-Szmek) * Fix to allow NumPy arrays in fdot() (Nico Schlömer) Features and improvements: * Added more automatic conversions from Fraction, Decimal, NumPy types (Jonathan Warner) * Support creating mpf from a long literal (ylemkimon) * Implemented log1p() * Slight speedup of eig() * Implement polylog() for general complex s and z by using Hurwitz zeta algorithm as a fallback Library: * Test more CPython and PyPy versions (Sergey B Kirpichev, Aaron Meurer) * Drop support for Python 2.6 and 3.2 (Sergey B Kirpichev) * Use py.test for test code; lots of code cleanup (Sergey B Kirpichev) * Corrections to the documentation (Paul Masson, Connor Behan, Warren Weckesser, Aaron Meurer) --1.0.0-- Released September 27, 2017 * Bumped to major version number for 10 year anniversary * Added module for inverse Laplace transforms, including the top level function invertlaplace() as well as several different algorithms (Talbot, Gaver-Stehfest and de Hoog) implemented in mpmath.calculus.inverselaplace (Kris Kuhlman) * Fixed bugs in elliprg() giving incorrect values for certain input * Fixed wrong degree 1 nodes for Gaussian quadrature * Made make acot(0) and acoth(0) return a finite result * Fixed sieved zeta sum not being used in Python 3, and added cutoff for sieved zeta sum on 32-bit systems when too much memory would be used * Fixed zeta(0,0.5) to return correct value instead of raising NoConvergence exception * Added detection of exact zeros in gammainc(), in particular fixing NoConvergence error for gammainc(3,-1+1j) * Fixed wrong values from besseli() due to improper internal precision * Fixed bessely(0,1j) to return complex nan instead of raising NameError (Paul Masson) * Changed float() and complex() applied to an mpf or mpc to use rounding to nearest (or the context rounding mode) instead truncating * Fix imaginary part of gammainc(n,x), n negative odd int, x < 0 * Added alternative "phase" color scheme to cplot() * Better error message for int(inf) or int(nan) (Aaron Meurer) * Fixed polyroots() with error=True * Added support to pass optional initial values to polyroots() (Michael Kagalenko) * Rewrote the Python major version selection to make it work if something else has redefined xrange (Arne Brys) * Switched documentation formula rendering to MathJax (Sergey B Kirpichev) * Fixed documentation TeX build (Sergey B Kirpichev) * Added PEP8 conformity testing (Sergey B Kirpichev) * Various fixes for the test code and test infrastructure on different platforms and Python versions (Sergey B Kirpichev) * Fixed module paths in setup.py (Aaron Meurer) * Documented more options for methods such as nstr() and hyper() * Miscellaneous corrections to the documentation (various) --0.19-- Released June 10, 2014 * Moved issue tracking to github and the main website to mpmath.org. Several URLs and issue numbers were updated in the documentation (Sergey B Kirpichev) * Enabled automatic testing with Travis CI (Sergey B Kirpichev) * Fixed many doctest issues (Sergey B Kirpichev) * Converted line endings to LF (Ondrej Certik) * Made polyroots() more robust (Ondrej Certik) --0.18-- Released December 31, 2013 Linear algebra: * added qr() for matrix QR factorization (contributed by Ken Allen) * added functions eigsy(), eighe(), eig() to compute matrix eigenvalues (contributed by Timo Hartmann) * added functions svd(), svd_r(), svd_c() for singular value decomposition of matrices (contributed by Timo Hartmann) * added calculation of Gaussian quadrature rules for various weight functions (contributed by Timo Hartmann) * improved precision selection in exp_pade() (contributed by Mario Pernici) Special functions: * fixed ellippi() to return an inf instead of raising an exception * fixed a crash in zeta() with huge arguments * added functions for computing Stirling numbers (stirling1(), stirling2()) * improved the computation of zeros of zeta at high precision (contributed by Juan Arias de Reyna) * fixed zeta(-x) raising an exception for tiny x * recognize when lerchphi() can call zeta() or polylog(), handling those cases faster Compatibility: * fixed gmpy2 compatibility issues (contributed by Case Van Horsen) * better solutions for python 2/3 compatibility, using Benjamin Peterson's six.py * fixes to allow mpmath to run in non-sage mode when sage is available * support abstract base classes (contributed by Stefan Krastanov) * use new-style classes to improve pypy performance Other: * added Levin, Sidi-S and Cohen/Villegas/Zagier series transformations (contributed by Timo Hartmann) * added isfinite() utility function * fixed a problem with bisection root-finding * fixed several documentation errors * corrected number of coefficients returned by diffs() with method='quad' * fixed repr(constant) being slow at high precision * made intervals hashable --0.17-- Released February 1, 2011 Compatibility: * Python 3 is now supported * Dropped Python 2.4 compatibility * Fixed Python 2.5 compatibility in matrix slicing code * Implemented Python 3.2-compatible hashing, making mpmath numbers hash compatible with extremely large integers and with fractions in Python versions >= 3.2 (contributed by Case Vanhorsen) Special functions: * Implemented the von Mangoldt function (mangoldt()) * Implemented the "secondary zeta function" (secondzeta()) (contributed by Juan Arias de Reyna). * Implemented zeta zero counting (nzeros()) and the Backlund S function (backlunds()) (contributed by Juan Arias de Reyna) * Implemented derivatives of order 1-4 for siegelz() and siegeltheta() (contributed by Juan Arias de Reyna) * Improved Euler-Maclaurin summation for zeta() to give more accurate results in the right half-plane when the reflection formula cannot be used * Implemented the Lerch transcendent (lerchphi()) * Fixed polygamma function to return a complex NaN at complex infinity or NaN, instead of raising an unrelated exception. --0.16-- Released September 24, 2010 Backends and distribution: * Added Sage hooks for Cython versions of exp, ln, cos, sin, hypergeometric series, and some related functions * Fixed imports for gmpy2 compatibility (contributed by Case Van Horsen) * Removed documentation from main mpmath package to save space (a separate tar.gz file is now provided for the documentation sources) * Fixed matplotlib version detection * Converted files to Unix line endings Special functions: * Started adding plots of special functions to the documentation * Added Anger and Weber functions (angerj(), webere()) * Added Lommel functions (lommels1(), lommels2()) * Added interval versions of gamma(), loggamma(), rgamma() and factorial() * Rewritten Airy functions to improve speed and accuracy * Support for arbitrary-order derivatives of airyai(), airybi() * Added Airy function zeros (airyaizero(), airybizero()) * Added Scorer functions (scorergi(), scorerhi()) * Added computation of Bessel function zeros and Bessel function derivative zeros (besseljzero(), besselyzero()) * Fixed besselj(mpc(n), z) * Rewritten lambertw() to fix various subtle bugs and robustly handle numerical difficulties near branch cuts and branch points. * Fixed fp.lambertw() to behave the same on branch cuts on systems with and without signed-zero floats * Added Carlson symmetric incomplete elliptic integrals (elliprf(), elliprc(), elliprj(), elliprd(), elliprg()) * Added Legendre incomplete elliptic integrals (ellipf(), ellippi(), ellipe() with two arguments) * Implemented Parabolic cylinder functions (pcfd(), pcfu(), pcfv(), pcfw()) * Implemented Euler-Maclaurin summation for hypergeometric functions of order (p,p-1) to support evaluation with z close to 1 in remaining cases * Fixed a bug in hypergeometric series summation, causing occasional inaccurate results and incorrect detection of zeros * Fixed qfrom(m=...) Calculus: * Implemented generators diffs_exp(), diffs_prod() for composing derivatives * Implemented Abel-Plana summation for infinite series (sumap()) Basic arithmetic and functions: * Implemented matrix slice indexing, supporting submatrix extraction and assignment (contributed by Ioannis Tziakos) * Added missing constant fp.glaisher * Fixed a bug preventing internal rational numbers from being hashable * Fixed bug in isnpint() * Fixed a bug in cos_sin() for pure imaginary argument * Slightly improved performance for elementary functions of pure real or pure imaginary mpc inputs * Fixed plot() with real-valued mpc instances * Fixed cplot() to work with endpoints of other type than float/int --0.15-- Released June 6, 2010 Basic transcendental functions: * Reimplemented all elementary functions except log, reducing overhead and giving asymptotic speedups at high precision * Reimplemented gamma() and loggamma(), improving speed and fixing accuracy in corner cases * Added rgamma() (reciprocal gamma function) * Added a stress test suite for the gamma function * Provided top-level functions cos_sin() and cospi_sinpi() for fast simultaneous computation Riemann zeta function: * New zetazeros() implementation, supporting arbitrarily large indices (contributed by Juan Arias de Reyna) * Tuned algorithm selection in zeta() for complex arguments (contributed by Juan Arias de Reyna) * Accelerated computation of zeta function series using sieving Special functions: * Added qfrom(), qbarfrom(), mfrom(), kfrom(), taufrom() for elliptic argument conversion * Merged jsn(), jcn(), jdn() -> ellipfun() and generalized it to compute all 12 Jacobi elliptic functions * Implemented the Klein j-invariant (kleinj()) * Implemented the q-Pochhammer symbol (qp()) * Implemented q-factorial (qfac()) and q--gamma (qgamma()) * Implemented q-hypergeometric series (qhyper()) * Implemented bilateral hypergeometric series (bihyper()) * Implemented Appell 2D hypergeometric series F2-F4 (appellf2()-appellf4()) * Implemented generalized 2D hypergeometric series (hyper2d()) * Fixed gammainc() for integer-valued complex argument (contributed by Juan Arias de Reyna) * Fixed asymptotic expansion of hyp1f1() (contributed by Juan Arias de Reyna) Numerical calculus: * Added support for multidimensional series in nsum() * Made nprod() faster by default by extrapolating directly instead of calling nsum() * Changed some options for diff()/diffs() * Made taylor() chop tiny coefficients by default * Added support for partial derivatives in diff() Interval arithmetic: * All interval arithmetic functionality moved to a separate context namespace (iv) * Preliminary support for complex intervals (iv.mpc) * Fixed interval cos/sin to support intervals overlapping zeros/extreme points * Implemented interval atan2 * Implemented exp/log/cos/sin for complex intervals * Some other interface changes to interval code Utility functions: * Made chop() use relative rather than absolute tolerance for real/imaginary parts * Optimized floor(), ceil(), isinf(), isnan(), isint() * Implemented nint(), frac(), isnormal() * Fixed and documented semantics for isinf(), isin(), isnan() * Added utility functions autoprec(), maxcalls(), memoize() Miscellaneous tweaks and fixes: * Support complex conjugation in fdot() * Added support for Cholesky decomposition of complex matrices * Fixed a small precision bug in linear algebra functions * Suppress NoConvergence exception when plotting * Removed some dirty code to improve PyPy compatibility * Fixed plotting to work with mpmath numbers in the interval specification * Fixed fp arithmetic on systems where math.log and math.sqrt return NaN instead of raising an exception * Fixed fp.conj for Python 2.4 and 2.5 * Fixed quadrature to work with reversed infinite intervals such as [0,-inf] * Renamed modf() -> fmod() for consistency --0.14-- Released February 5, 2010 General changes: * Fully separated the code into "low-level" and "high-level", permitting the use of alternative contexts (the mpmath.mp object provides the default implementation) * Implemented a context for fast double-precision arithmetic using Python types (mpmath.fp) * Implemented hooks for importing a faster version of mp arithmetic from Sage * Implemented optimized fp versions of certain functions (including erf, erfc, gamma, digamma, ei, e1) * Renamed and reorganized various internal modules and methods (including merging low-level modules into mpmath.libmp). This should not affect most external code using top-level imports. Plotting: * Implemented splot() for 3D surface plots (contributed by Jorn Baayen) * Permit calling plot functions with custom axes (contributed by Jorn Baayen) Matrices: * Fixed lu_solve for overdetermined systems (contributed by Vinzent Steinberg) * Added conjugate matrix transpose (contributed by Vinzent Steinberg) * Implemented matrix functions (expm, cosm, sinm, sqrtm, logm, powm) Miscellaneous: * Prettier printing of numbers with leading zeros at small precisions * Made nstr pass on kwargs, permitting more formatting options * Fixed wrong directed rounding of addition of numbers with large magnitude differences * Fixed several docstring typos (contributed by Chris Smith) * Fixed a bug that prevented caching of quadrature nodes to work optimally. Special functions: * Implemented fast evaluation for large imaginary heights of the Riemann zeta function, Z function and derived functions using the Riemann-Siegel (contributed by Juan Arias de Reyna) * Unified the zeta() and hurwitz() functions, automatically selecting a fast algorithm * Improved altzeta() to fall back to zeta() for large arguments * Fixed accuracy of zeta(s) for s ~= 1 * Implemented exact evaluation of Euler numbers (contributed by Juan Arias de Reyna) * Implemented numerical evaluation of Euler numbers and Euler polynomials (eulernum(), eulerpoly()) * Fixed bernpoly() and eulerpoly() to compute accurate values for large parameters * Fixed accuracy problems for hypergeometric functions with large parameters * Faster evaluation of hypergeometric series using on-the-fly code generation * Optimized hypercomb to detect certain zero terms symbolically * Removed the djtheta function (jtheta() accepts a derivative parameter) * Implemented li(x, offset=True) to compute the offset logarithmic integral * Fixed wrong branch in Lambert W function for certain complex inputs * Implemented the reflection formula for the Barnes G-function, superfactorials, hyperfactorials, permitting large arguments in the left half-plane * Implemented analytic continuation to |z| >= 1 for hypergeometric functions pFq with p=q+1; added hyp3f2() * Implemented Borel summation of divergent pFq functions with p > q+1 * Implemented automatic degree reduction of hypergeometric functions with repeated parameters * Added convenience functions expj(), expjpi() * Use Mathematica's convention for the continuation of the Meijer G-function * Added phase(), polar(), rect() functions for compatibility with the Python 2.6 cmath module * Implemented spherical harmonics (spherharm()) * Optimized ci(), si(), chi(), shi() for complex arguments by evaluating them in terms of ei() * Optimized hyp2f1 for z ~= -1 --0.13-- Released August 13, 2009 New special functions: * The generalized exponential integral E_n (expint(), e1() for E_1) * The generalized incomplete beta function (betainc()) * Whittaker functions (whitm(), whitw()) * Struve functions (struveh(), struvel()) * Kelvin functions (ber(), bei(), ker(), kei()) * Cyclotomic polynomials (cyclotomic()) * The Meijer G-function (meijerg()) * Clausen functions (clsin(), clcos()) * The Appell F1 hypergeometric function of two variables (appellf1()) * The Hurwitz zeta function, with nth order derivatives (hurwitz()) * Dirichlet L-series (dirichlet()) * Coulomb wave functions (coulombf(), coulombg(), coulombc()) * Associated Legendre functions of 1st and 2nd kind (legenp(), legenq()) * Hermite polynomials (hermite()) * Gegenbauer polynomials (gegenbauer()) * Associated Laguerre polynomials (laguerre()) * Hypergeometric functions hyp1f2(), hyp2f2(), hyp2f3(), hyp2f0(), hyperu() Evaluation of hypergeometric functions: * Added the function hypercomb() for evaluating expressions containing hypergeometric series, with automatic handling of limits * The available hypergeometric series (of orders up to and including 2F3) implement asymptotic expansions with respect to the last argument z, allowing fast and accurate evaluation anywhere in the complex plane. A massive number of functions, including Bessel functions, error functions, etc., have been updated to take advantage of this to support fast and accurate evaluation anywhere in the complex plane. * Fixed hyp2f1 to handle z close to and on the unit circle (supporting evaluation anywhere in the complex plane) * hyper() handles the 0F0 and 1F0 cases exactly * hyper() eventually raises NoConvergence instead of getting stuck in an infinite loop if given a divergent or extremely slowly convergent series Other improvements and bug fixes to special functions: * gammainc is much faster for large arguments and avoids catastrophic cancellation * Implemented specialized code for ei(x), e1(x), expint(n,x) and gammainc(n,x) for small integers n, making evaluation much faster * Extended the domain of polylog * Fixed accuracy for asin(x) near x = 1 * Fast evaluation of Bernoulli polynomials for large z * Fixed Jacobi polynomials to handle some poles * Some Bessel functions support computing nth order derivatives * A set of "torture tests" for special functions is available as tests/torture.py Other: * Implemented the differint() function for fractional differentiaton / iterated integration * Added functions fadd, fsub, fneg, fmul, fdiv for high-level arithmetic with controllable precision and rounding * Added the function mag() for quick order-of-magnitude estimates of numbers * Implemented powm1() for accurate calculation of x^y-1 * Improved speed and accuracy for raising a pure imaginary number to an integer power * nthroot() renamed to root(); root() optionally computes any of the non-principal roots of a number * Implemented unitroots() for generating all (primitive) roots of unity * Added the mp.pretty option for nicer repr output --0.12-- Released June 9, 2009 General * It is now possible to create multiple context objects and use context-local methods instead of global state/functions (e.g. mp2=mp.clone(); mp2.dps=50; mp2.cos(3)). Not all functions have been converted to context methods, and there are some bugs, so this feature is currently experimental. * If mpmath is installed in Sage 4.0 or later, mpmath will now use sage.Integer instead of Python long internally. * Removed instances of old-style integer division from the codebase. * runtests.py can be run with -coverage to generate coverage statistics. Types and basic arithmetic * Fixed comparison with -inf. * Changed repr format of the mpi interval type to make eval(repr(x)) == x. * Improved printing of intervals, with configurable output format (contributed by Vinzent Steinberg based on code by Don Peterson). * Intervals supported by mpmathify() and nstr() (contributed by Vinzent Steinberg). * mpc is now hashable. * Added more formatting options to the internal function to_str. * Faster pure-Python square root. * Fix trailing whitespace giving wrong values in str->mpf conversion. Calculus * Fixed nsum() with Euler-Maclaurin summation which would previously ignore the starting index and sum from n=1. * Implemented Newton's method for findroot() (contributed by Vinzent Steinberg). Linear algebra * Fixed LU_decomp() to recognize singular matrices (contributed by Jorn Baayen). * The various norm functions were replaced by the generic vector norm function norm(x,p) and the generic matrix norm function mnorm(x,p). Special functions: * Some internal caches were changed to always slightly overallocate precision. This fixes worst-case behavior where previously the cached value had to be recomputed on every function call. * Fixed log(tiny number) returning nonsense at high precision. * Fixed gamma() and derivative functions such as binomial() returning wrong results at integer inputs being divisible by a large power of 2. * Fixed asin() not to raise an exception at high precision (contributed by Vinzent Steinberg). * Optimized the AGM code for the natural logarithm, making the previously used Newton method at intermediate precisions obsolete. * The arithmetic-geometric mean function agm() is now an order of magnitude faster at low precision. * Faster implementations of ellipk() and ellipe(). * Analytic continuation of ellipe() to |x| >= 1 implemented. * Implemented the log gamma function (loggamma()) with correct branch cuts (slow, placeholder implementation). * Fixed branch cuts of hyperfac(). * Implemented the Riemann-Siegel Z-function (siegelz()). * Implemented the Riemann-Siegel theta function (siegeltheta()). * Implemented calculation of Gram points (grampoint()). * Implemented calculation of Riemann zeta function zeros (zetazero()). * Implemented the prime counting function: a slow, exact version (primepi()). and a fast approximate version (primepi2()) that gives a bounding interval. * Implemented the Riemann R prime counting function (riemannr()). * Implemented Bell numbers and polynomials (bell()). * Implemented the expm1() function. * Implemented the 'polyexponential function' (polyexp()). * Implemented the twin prime constant (twinprime) and Mertens' constant (mertens). * Implemented the prime zeta function (primezeta()). --0.11-- Released January 26, 2009 General: * Most of the documentation is now generated from docstrings using Sphinx' autodoc feature, and proper LaTeX is used for mathematical formulas. A large amount of new documentation has been written. * Improved gmpy backend. Using gmpy-1.04 gives a ~30% unit tests speedup over 1.03, with speedups in the range of 2-3x for specific operations (contributed by Case van Horsen and Mario Pernici). * Mpmath imports slightly faster due to not trying to load the 'random' library Numerical calculus, etc: * Implemented a fast high-precision ODE solver (to replace the slow and low-accuracy RK4 algorithm) (odefun()) * Created an intelligent function nsum() to replace sumrich/sumsh * Implemented nprod() for computing infinite products * Rewrote limit() to use the same adaptive extrapolation algorithm as nsum() * Multidimensional nonlinear solving with Newton's method implemented in findroot() (contributed by Vinzent Steinberg) * Simplified the implementation and interface of sumem() * Reimplemented Shanks transformation for nsum using Wynn's epsilon algorithm (shanks()) * Reimplemented Richardson extrapolation slightly more simply and efficiently (richardson()) * Prevent shanks() from exiting prematurely by adding random noise to zeros * Removed the obsolete secant() function (see findroot()) * Implemented high-order derivatives (diff(), diffs()) * Implemented calculation of Taylor series (taylor()) * Implemented calculation of Fourier series (fourier(), fourierval()) * Implemented Pade approximation (pade()) (contributed by Mario Pernici) * Better cancel condition for findroot() (contributed by Vinzent Steinberg) * Some refactoring of numerical integration code * Fix erroneous nodes for 0-th order Gauss-Legendre quadrature, which was causing unnecessary slowness * Quadrature nodes are cached for arbitrary intervals, giving a 30% speedup for repeated integrations * Unified interface and added more options for identify(), pslq(), findpoly() New special functions: * Implemented polylogarithms (polylog()) * Implemented Bernoulli polynomials (bernpoly()) * Implemented the Barnes G-function (barnesg()) * Implemented double factorials (fac2()) * Implemented superfactorials (superfac()) * Implemented hyperfactorials (hyperfac()) * Replaced lower_gamma and upper_gamma with a more versatile function gammainc() for computing the generalized (and optionally regularized) incomplete gamma function * Implemented sinc() and sincpi() * Implemented Fibonacci numbers (fib()) * Implemented the Dirichlet eta function (altzeta()) * Implemented the inverse error function (erfinv()) * Jacobi theta functions and elliptic functions were essentially rewritten from scratch, making them much faster and more general. Renamed Jacobi theta functions: jacobi_theta -> jtheta, etc. (contributed by Mario Pernici) * Implemented derivatives of jtheta (djtheta) (contributed by Mario Pernici) * Implemented Bessel Y, I, K functions (bessely, besseli, besselk; Bessel J functions were also renamed to besselj) also renamed) * Generalized Stieltjes constants can now be computed, with stieltjes(n,a) * Implemented Hankel functions (hankel1, hankel2) Speed improvements and bugfixes to special functions: * Fast logarithm at very high precision using the formula by Sasaki and Kanada (contributed by Mario Pernici) * Slightly faster logarithm at low precision (contributed by Mario Pernici) * Faster exponential function at high precision, using Newton's method (contributed by Mario Pernici) * Faster computation of ln2 and ln10 by means of binary splitting (contributed by Mario Pernici) * Fixed accuracy problems in sinpi() and cospi() * Correct evaluation of beta() at limits * Much faster evaluation of stieltjes(n), using an improved integral formula * Fixed bernoulli() being inaccurate for large n and low precision, and being needlessly slow for small n and huge precision * Fixed accuracy of zeta(s) for large negative re(s) * Fixed accuracy problems for asinh, atanh and tanh * Fixed accuracy of airyai() for large x.real * Fixed bug in nthroot() for very large arguments (contributed by Mario Pernici) * Fixed accuracy of log(x) for complex |x| ~= 1 * Fixed accuracy of exp(n), n a huge integer and prec >= 600 * Slightly faster hypergeometric functions with rational parameters (contributed by Mario Pernici) * Faster and more accurate calculation of ci(x), si(x) * Faster and more accurate calculation of ei(x) for large x, using an asymptotic expansion (contributed by Mario Pernici) * Fixed accuracy bugs in theta functions (contributed by Mario Pernici) * The Lambert W function returns more appropriate values at infinities Arithmetic and basic interface: * Square roots are now rounded correctly * Made float(huge) -> inf and float(1/huge) -> 0 instead of raising OverflowError * Renamed convert_lossless -> mpmathify * mpmathify() accepts strings representing fractions or complex numbers (contributed by Vinzent Steinberg) * Fixed a bug in interval multiplication giving wrong signs * Added monitor() to monitor function evaluation * Implemented a chop() utility function for deletion of numerical noise * Added re(), im(), conj(), fabs(), mpf.conjugate() * Fixed the != operator for intervals * Added functions fsum, fprod, fdot for efficient computation of sums, products and dot products of lists of mpf:s or mpc:s Matrices: * Generation of Hilbert matrices (hilbert()) (contributed by Vinzent Steinberg) * Added lu_solve_mat() to solve a*x=b where a and b are matrices (contributed by Mario Pernici) * Implemented computation of matrix exponentials (exp_pade()) (contributed by Mario Pernici) * Prettier repr of complex matrices (contributed by Vinzent Steinberg) * Speedups by using fdot and fsum (contributed by Vinzent Steinberg) --0.10-- Released October 15, 2008 Interface / general: * Mpmath now works with Python 2.6 * Implemented function plotting via 'plot' and 'cplot' (requires matplotlib) * Removed global rounding mode (always rounding to nearest by default) * Instead added 'prec', 'dps', 'rounding' keyword arguments to standard functions, for optional fine-grained control over precision and rounding * Implemented isinf, isnan, isint, utility functions * A large number of internal functions were moved and/or renamed to improve consistency. This particularly affects low-level mpf functions (lib.fadd -> libmpf.mpf_add, etc). * Syntax for some operations was changed (see details below) * The test runner (runtests.py) was updated to support running isolated tests and to allow a local import of mpmath * Unit tests can now be run with import mpmath; mpmath.runtests() * Implicit imports are no longer used internally in the main codebase. (This will hopefully make the source easier to read, and can catch installation problems more cleanly.) Added linear algebra functions (contributed by Vinzent Steinberg): * Provided a matrix class * Computation of powers, inverses, determinants * Linear system solving using LU, QR and Cholesky * Vector and matrix norms * Calculation of condition numbers Improvements to interval arithmetic: * Fixed rounding direction for negative numbers and related spurious bugs * Fix interval exponentiation (all cases should work now) * Basic interval arithmetic is up to 10x faster * sqrt, exp, log, sin, cos and a few other functions accept interval arguments * Intervals supported in matrices Changes to root-finding code: * secant renamed to findroot * findroot was made more general; many useful alternative root-finding algorithms were implemented (contributed by Vinzent Steinberg) Improvements to special functions: * Implemented polygamma functions * Implemented harmonic numbers * Implemented Stieltjes constants * Made gamma more accurate for huge arguments and/or precision * Made zeta more accurate in various cases * Made zeta typically 2-5x faster * Much more efficient computation of zeta for huge s (zeta(s) ~= 1) * Optimized numerical calculation of Bernoulli numbers * Fast exact calculation of huge Bernoulli numbers via zeta and the von Staudt-Clausen theorem * Using AGM to compute ellipk, which is much faster and works in the entire complex plane * Allow single-argument form agm(x) = agm(1,x) * Faster and more accurate computation of erf * Added fast and accurate implementation of erfc * Normal probability functions npdf, ncdf * Fixed directed rounding in corner cases for various functions Improvements to numerical integration: * Changed syntax for integration (quad(f, [a, b], options)) * Implemented Gauss-Legendre quadrature * Direct support for triple integrals (quad(f, X, Y, Z)) * Interval can be a list of several points, to split integration into subintervals * Oscillatory quadrature uses Gauss-Legendre instead of tanh-sinh, since this is typically faster * Fixed minor rounding bug in tanh-sinh quadrature not giving complete symmetry in the nodes * Implemented quadrature rules in classes for improved extensibility Various speed improvements: * Up to 3x faster computation of log(x) at low precision, due to using Taylor series with argument reduction and partial caching * About 2x faster log(x) at very high precision due to more efficient computation of exp in the Newton iteration * Up to 10x faster computation of atan(x) at low to medium precision, due to using Taylor series with argument reduction and partial caching * Faster pickling due to using hex() instead of long() * Optimized code for Khinchin's constant (2.5x faster at 1000 digits) * Optimized code for Glaisher's constant (1.5x faster at 1000 digits) * Faster algorithm for Euler's constant (10x faster at 10000 digits) * Rewrote PSLQ to use fixed-point arithmetic, giving a ~7x speedup in pslq, findpoly and identify Miscellaneous bugfixes: * Fixed nthroot for n = -1, 0, 1 * Fixed inf/2**n and nan/2**n returning zero --0.9-- Released August 23, 2008 * gmpy mpzs are used instead of python ints when available, for huge speedups at high precision (contributed by Case Van Horsen) * using binary splitting to compute pi and e near-optimally * mpmath includes __version__ information * arange behaves more like range (contributed by Vinzent Steinberg) * asymptotically faster trigonometric functions via Brent's trick (contributed by Mario Pernici) * asymptotically faster inverse trigonometric functions via Newton's method (contributed by Mario Pernici) * added Jacobi elliptic functions 1-4, sn, cn, dn (contributed by Mike Taschuk) * polyval, polyroots and related functions now use the same order for coefficients as scipy and matlab (i.e. the reverse order of what was used previously in mpmath) * fixed polyroots for degree-0 polynomials (contributed by Nimish Telang) * added convenience functions (log10, degrees, radians, frexp, modf, ln, arg, sign) * added fast cbrt and nthroot functions for computing nth roots (contributed by (Mario Pernici) * added various exponential integrals (ei, li, si, ci, shi, chi, erfi) * added airy functions (airyai, airybi) * more __op__ and __rop__ methods return NotImplemented where appropriate * external classes can define a special method _mpmath_ to interact with mpmath numbers and functions * fixed some corner cases in atan2 * faster rand() --0.8-- Released April 20, 2008 New features: * the full set of reciprocal trigonometric and hyperbolic functions and their inverses (cotangent, secant, etc) is available * oscillatory quadrature algorithm * the PSLQ algorithm and constant recognition functions * Richardson and Shanks transformations for computing limits and series * Euler-Maclaurin summation of series * basic ODE solvers (contributed by Ondrej Certik) * the Lambert W function * arithmetic-geometric mean function * generic hypergeometric series and some special hypergeometric functions (elliptic integrals, orthogonal polynomials) * several more mathematical constants * fast sequential computation of integer logarithms and Bernoulli numbers * Bessel function jv works for complex arguments and noninteger v * support for trapping complex results * using Sphinx to generate HTML documentation Bugfixes, speed enhancements, and other improvements: * compatibility tests should now pass on systems where Python is compiled to use 80-bit registers for floating point operations * fixed mpmath to work with some versions of Python 2.4 where a list indexing bug is present in the Python core * better algorithms for various complex elementary functions (tan and tanh by Fredrik; sqrt, acos, asin, acosh and asinh improved by Mario Pernici) * multiplication and integer powers for complex numbers is faster and more accurate * miscellaneous speed improvements to complex arithmetic (contributed by Mario Pernici) * faster computation of cos and sin when only one of them is needed (contributed by Mario Pernici) * slightly faster square roots at low precision (contributed by Mario Pernici) * fixed computation of exp(n) for negative integers and x**y for negative half integers y * mpf ** complex now works * faster generation of quadrature nodes (contributed by Mario Pernici) * faster change of variables for quadrature * comparisons and conversions have been optimized slightly. comparisons with float(nan) also work as intended. * str() is several times faster at very high precision * implementations of most elementary functions moved to the lib and libmpc modules for cleaner separation of functionality * the rounding argument for lib and libmpc functions, and for some functions also the the prec argument, are now optional, resulting in cleaner and slightly faster lib code * gamma and factorial are about 2x faster * polyroots returns nicer results * pickling now works for mpf and mpc instances --0.7-- Released March 12, 2008 * the interface for switching precision and rounding modes has been changed. instead of changing mpf.prec, there is a new object mp which holds the precision as mp.prec. this change improves flexibility in the implementation. it will unfortunately break any existing code written for mpmath, but the broken code should be trivial to update. * the functions workprec, workdps, extraprec, extradps have been introduced for switching precision in a more safe manner, ensuring that the precision gets reset when finished. they can be used with the 'with' statement available in python 2.5 * improved documentation (manual.html) * the round-half-down and round-half-up modes have been deprecated, since they added complexity without being particularly useful. round-half-even has been renamed to round-nearest. * implemented the functions nstr, nprint for printing numbers with a small or custom number of digits * accuracy of cos and sin near roots has been fixed. computing sin(x) or cos(x) where x is huge is also much faster * implemented a magical constant eps that gives the "machine" epsilon * additional mathematical functions: implemented Catalan's constant and Bessel functions J_n(x) for integer n and real x * new functions diff and diffc for numerical differentiation * implemented the ldexp function for fast multiplication by 2**n * mpf uses rich comparison methods (contributed by Pearu Peterson) * epydoc-friendly docstrings (contributed by Pearu Peterson) * support creating mpf from float nan or inf * fixed printing of complex numbers with negative imaginary part * flattened package structure to simplify inclusion of mpmath in other packages * external classes can interoperate with mpf and mpc instances by defining _mpf_ or _mpc_ properties * renamed lib.fpow -> lib.fpowi and implemented lib.fpow for general real powers. ** should now be slightly faster and more robust * the internal number representation has been changed to include an explicit sign bit. as a result of this change and other small tweaks, arithmetic is up to 20% faster and the total running time for mpmath's unit tests has dropped 10%. * miscellaneous speed improvements: * ** is 2-3 times faster (contributed by Mario Pernici) * * and * is roughly twice as fast * / is roughly twice as fast (contributed by Mario Pernici) * exp and log are about 10% faster * fast computation of e and exp(n) when precision is extremely high --0.6-- Released January 13, 2008 * added the mpi type for interval arithmetic * powers with integer exponents are computed with directed rounding all the way through to preserve interval bounds more robustly (however, the code is not fully tested and may have some bugs) * string input to mpf.__new__() can now be unicode * mpf.__eq__ now works in pypy * infs and nans are now implemented in mpmath.lib, resulting in considerable simplification of the mpf class implementation * partial support for infs and nans in functions, e.g. exp(inf) -> inf and exp(-inf) -> 0 now work. * renamed several files. created mpmath.apps and moved tests into the main mpmath directory * wrote script to permit running unit tests without py.test available * improved bit counting code in fadd, fmul and fdiv, plus other small performance tweaks, resulting in a 20-30% speedup for arithmetic --0.5-- Released November 24, 2007 * added the quad module for arbitrary-precision numerical integration * floor and ceil functions available * implemented __mod__ and __rmod__ for the mpf class * partial support for the special numbers +inf, -inf and nan * faster multiplication and division (up to 40% faster with psyco) * simplified syntax for conversion function (from_int instead of from_int_exact, etc) * renamed cgamma to euler * more documentation strings --0.4-- Released November 3, 2007 * new string conversion code (much faster; unlimited exponents) * fixed bug in factorial (it gave the wrong value, though gamma worked) * division now uses a rigorous algorithm for directed rounding (mpmath previously used a heuristic that got the last bit wrong in 1/10000 of cases) * misc. performance improvements (arithmetic is 15% faster) * refactored parts of the code; added many more docstrings and tests * added a function rand() for generating full-precision random numbers * rewrote the benchmark script to compare against Decimal and to automatically generate timings with psyco both disabled and enabled * rewrote unit tests to use py.test --0.3-- Released October 5, 2007 * fixed high-precision accuracy problem in complex sqrt * fixed high-precision accuracy problem in atan and complex log * fixed directed rounding for sqrt (always rounded to nearest) * implemented all hyperbolic and inverse functions (there are some accuracy issues left to sort out) * included gamma, factorial, erf, zeta incomplete gamma functions * made sin and tan more accurate for complex input very close to 0 * more docstrings * many more tests * including a benchmark script -- 0.2 -- Released October 2, 2007 * 50% faster exponential function * faster mpf <-> int ops * fixed import error in pidigits.py; added demos to source distribution * __rmul__ was missing on mpf * fixed bitcount bug also for -(2**n-1) * more docstrings * more tests; tests included in source distribution * approximate equality testing (.ae method) supported * implemented atan and atan2 functions * tan works for both mpfs and mpcs * complex logarithms and complex powers supported * more details in README -- 0.1 -- Released September 27, 2007 * imported code from SymPy's numerics module * renamed functions and restructured various parts of the code * fixed erroneous bitcount for 2**n-1 mantissa with directed rounding * various small speed improvements and bug fixes mpmath-1.1.0/LICENSE000066400000000000000000000027641340375245600140260ustar00rootroot00000000000000Copyright (c) 2005-2018 Fredrik Johansson and mpmath contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c. Neither the name of mpmath nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mpmath-1.1.0/MANIFEST.in000066400000000000000000000001161340375245600145440ustar00rootroot00000000000000include mpmath/*.py include mpmath/tests/*.py include LICENSE include CHANGES mpmath-1.1.0/README.rst000066400000000000000000000147721340375245600145120ustar00rootroot00000000000000mpmath ====== |pypi version| |Build status| |Zenodo Badge| .. |pypi version| image:: https://img.shields.io/pypi/v/mpmath.svg :target: https://pypi.python.org/pypi/mpmath .. |Build status| image:: https://secure.travis-ci.org/fredrik-johansson/mpmath.svg?branch=master :target: https://travis-ci.org/fredrik-johansson/mpmath .. |Zenodo Badge| image:: https://zenodo.org/badge/2934512.svg :target: https://zenodo.org/badge/latestdoi/2934512 A Python library for arbitrary-precision floating-point arithmetic. Website: http://mpmath.org/ Main author: Fredrik Johansson Mpmath is free software released under the New BSD License (see the LICENSE file for details) 0. History and credits ---------------------- The following people (among others) have contributed major patches or new features to mpmath: * Pearu Peterson * Mario Pernici * Ondrej Certik * Vinzent Steinberg * Nimish Telang * Mike Taschuk * Case Van Horsen * Jorn Baayen * Chris Smith * Juan Arias de Reyna * Ioannis Tziakos * Aaron Meurer * Stefan Krastanov * Ken Allen * Timo Hartmann * Sergey B Kirpichev * Kris Kuhlman * Paul Masson * Michael Kagalenko * Jonathan Warner Numerous other people have contributed by reporting bugs, requesting new features, or suggesting improvements to the documentation. Mpmath includes a copy of Benjamin Peterson's six.py for Python 2/3 compatibility. six.py is provided under the MIT license (see the source file for details). For a detailed changelog, including individual contributions, see the CHANGES file. Fredrik's work on mpmath during summer 2008 was sponsored by Google as part of the Google Summer of Code program. Fredrik's work on mpmath during summer 2009 was sponsored by the American Institute of Mathematics under the support of the National Science Foundation Grant No. 0757627 (FRG: L-functions and Modular Forms). Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the sponsors. Credit also goes to: * The authors of the GMP library and the Python wrapper gmpy, enabling mpmath to become much faster at high precision * The authors of MPFR, pari/gp, MPFUN, and other arbitrary- precision libraries, whose documentation has been helpful for implementing many of the algorithms in mpmath * Wikipedia contributors; Abramowitz & Stegun; Gradshteyn & Ryzhik; Wolfram Research for MathWorld and the Wolfram Functions site. These are the main references used for special functions implementations. * George Brandl for developing the Sphinx documentation tool used to build mpmath's documentation Release history: * Version 1.1.0 released on December 11, 2018 * Version 1.0.0 released on September 27, 2017 * Version 0.19 released on June 10, 2014 * Version 0.18 released on December 31, 2013 * Version 0.17 released on February 1, 2011 * Version 0.16 released on September 24, 2010 * Version 0.15 released on June 6, 2010 * Version 0.14 released on February 5, 2010 * Version 0.13 released on August 13, 2009 * Version 0.12 released on June 9, 2009 * Version 0.11 released on January 26, 2009 * Version 0.10 released on October 15, 2008 * Version 0.9 released on August 23, 2008 * Version 0.8 released on April 20, 2008 * Version 0.7 released on March 12, 2008 * Version 0.6 released on January 13, 2008 * Version 0.5 released on November 24, 2007 * Version 0.4 released on November 3, 2007 * Version 0.3 released on October 5, 2007 * Version 0.2 released on October 2, 2007 * Version 0.1 released on September 27, 2007 1. Download & installation -------------------------- Mpmath requires Python 2.5 or later. It has been tested with CPython 2.7, 3.3 through 3.7 and for PyPy. The latest release of mpmath can be downloaded from the mpmath website and from https://github.com/fredrik-johansson/mpmath/releases It should also be available in the Python Package Index at https://pypi.python.org/pypi/mpmath To install latest release of Mpmath with pip, simply run ``pip install mpmath`` Or unpack the mpmath archive and run ``python setup.py install`` Mpmath can also be installed using ``python -m easy_install mpmath`` The latest development code is available from https://github.com/fredrik-johansson/mpmath See the main documentation for more detailed instructions. 2. Running tests ---------------- The unit tests in mpmath/tests/ can be run via the script runtests.py, but it is recommended to run them with py.test (http://codespeak.net/py/dist/index.html), especially to generate more useful reports in case there are failures. You may also want to check out the demo scripts in the demo directory. The master branch is automatically tested by Travis CI. 3. Documentation ---------------- Documentation in reStructuredText format is available in the doc directory included with the source package. These files are human-readable, but can be compiled to prettier HTML using the build.py script (requires Sphinx, http://sphinx.pocoo.org/). See setup.txt in the documentation for more information. The most recent documentation is also available in HTML format: http://mpmath.org/doc/current/ 4. Known problems ----------------- Mpmath is a work in progress. Major issues include: * Some functions may return incorrect values when given extremely large arguments or arguments very close to singularities. * Directed rounding works for arithmetic operations. It is implemented heuristically for other operations, and their results may be off by one or two units in the last place (even if otherwise accurate). * Some IEEE 754 features are not available. Inifinities and NaN are partially supported; denormal rounding is currently not available at all. * The interface for switching precision and rounding is not finalized. The current method is not threadsafe. 5. Help and bug reports ----------------------- General questions and comments can be sent to the mpmath mailinglist, mpmath@googlegroups.com You can also report bugs and send patches to the mpmath issue tracker, https://github.com/fredrik-johansson/mpmath/issues mpmath-1.1.0/TODO000066400000000000000000000000701340375245600134750ustar00rootroot00000000000000See README and the mpmath website for more information. mpmath-1.1.0/demo/000077500000000000000000000000001340375245600137345ustar00rootroot00000000000000mpmath-1.1.0/demo/mandelbrot.py000066400000000000000000000013111340375245600164310ustar00rootroot00000000000000""" This script uses the cplot function in mpmath to plot the Mandelbrot set. By default, the fp context is used for speed. The mp context could be used to improve accuracy at extremely high zoom levels. """ import mpmath import cmath ctx = mpmath.fp # ctx = mpmath.mp ITERATIONS = 50 POINTS = 100000 ESCAPE_RADIUS = 8 # Full plot RE = [-2.5, 1.5] IM = [-1.5, 1.5] # A pretty subplot #RE = [-0.96, -0.80] #IM = [-0.35, -0.2] def mandelbrot(z): c = z for i in xrange(ITERATIONS): zprev = z z = z*z + c if abs(z) > ESCAPE_RADIUS: return ctx.exp(1j*(i + 1 - ctx.log(ctx.log(abs(z)))/ctx.log(2))) return 0 ctx.cplot(mandelbrot, RE, IM, points=POINTS, verbose=1) mpmath-1.1.0/demo/manydigits.py000066400000000000000000000043131340375245600164570ustar00rootroot00000000000000""" This script calculates solutions to some of the problems from the "Many Digits" competition: http://www.cs.ru.nl/~milad/manydigits/problems.php Run with: python manydigits.py """ from mpmath import * from mpmath.libmp import to_fixed, bin_to_radix dps = 100 mp.dps = dps + 10 def pr(x): """Return the first dps digits after the decimal point""" x = x._mpf_ p = int(dps*3.33 + 10) t = to_fixed(x, p) d = bin_to_radix(t, p, 10, dps) s = str(d).zfill(dps)[-dps:] return s[:dps//2] + "\n" + s[dps//2:] print """ This script prints answers to a selection of the "Many Digits" competition problems: http://www.cs.ru.nl/~milad/manydigits/problems.php The output for each problem is the first 100 digits after the decimal point in the result. """ print "C01: sin(tan(cos(1)))" print pr(sin(tan(cos(1)))) print print "C02: sqrt(e/pi)" print pr(sqrt(e/pi)) print print "C03: sin((e+1)^3)" print pr(sin((e+1)**3)) print print "C04: exp(pi*sqrt(2011))" mp.dps += 65 print pr(exp(pi*sqrt(2011))) mp.dps -= 65 print print "C05: exp(exp(exp(1/2)))" print pr(exp(exp(exp(0.5)))) print print "C06: arctanh(1-arctanh(1-arctanh(1-arctanh(1/pi))))" print pr(atanh(1-atanh(1-atanh(1-atanh(1/pi))))) print print "C07: pi^1000" mp.dps += 505 print pr(pi**1000) mp.dps -= 505 print print "C08: sin(6^(6^6))" print pr(sin(6**(6**6))) print print "C09: sin(10*arctan(tanh(pi*(2011^(1/2))/3)))" mp.dps += 150 print pr(sin(10*atan(tanh(pi*sqrt(2011)/3)))) mp.dps -= 150 print print "C10: (7+2^(1/5)-5*(8^(1/5)))^(1/3) + 4^(1/5)-2^(1/5)" a = mpf(1)/5 print pr(((7 + 2**a - 5*(8**a))**(mpf(1)/3) + 4**a - 2**a)) print print "C11: tan(2^(1/2))+arctanh(sin(1))" print pr((tan(sqrt(2)) + atanh(sin(1)))) print print "C12: arcsin(1/e^2) + arcsinh(e^2)" print pr(asin(1/exp(2)) + asinh(exp(2))) print print "C17: S= -4*Zeta(2) - 2*Zeta(3) + 4*Zeta(2)*Zeta(3) + 2*Zeta(5)" print pr(-4*zeta(2) - 2*zeta(3) + 4*zeta(2)*zeta(3) + 2*zeta(5)) print print "C18: Catalan G = Sum{i=0}{\infty}(-1)^i/(2i+1)^2" print pr(catalan) print print "C21: Equation exp(cos(x)) = x" print pr(findroot(lambda x: exp(cos(x))-x, 1)) print print "C22: J = integral(sin(sin(sin(x)))), x=0..1" print pr(quadts(lambda x: sin(sin(sin(x))), [0, 1])) print mpmath-1.1.0/demo/pidigits.py000066400000000000000000000045221340375245600161250ustar00rootroot00000000000000""" Calculate digits of pi. This module can be run interactively with python pidigits.py """ __docformat__ = 'plaintext' import sys import math from time import clock from mpmath.libmp import bin_to_radix, numeral, pi_fixed def display_fraction(digits, skip=0, colwidth=10, columns=5): perline = colwidth * columns printed = 0 for linecount in range((len(digits)-skip) // (colwidth * columns)): line = digits[skip+linecount*perline:skip+(linecount+1)*perline] for i in range(columns): print line[i*colwidth : (i+1)*colwidth], print ":", (linecount+1)*perline if (linecount+1) % 10 == 0: print printed += colwidth*columns rem = (len(digits)-skip) % (colwidth * columns) if rem: buf = digits[-rem:] s = "" for i in range(columns): s += buf[:colwidth].ljust(colwidth+1, " ") buf = buf[colwidth:] print s + ":", printed + colwidth*columns def calculateit(base, n, tofile): intpart = numeral(3, base) skip = 1 if base <= 3: skip = 2 prec = int(n*math.log(base,2))+10 print "Step 1 of 2: calculating binary value..." t = clock() a = pi_fixed(prec, verbose=True, verbose_base=base) step1_time = clock() - t print "Step 2 of 2: converting to specified base..." t = clock() d = bin_to_radix(a, prec, base, n) d = numeral(d, base, n) step2_time = clock() - t print "\nWriting output...\n" if tofile: out_ = sys.stdout sys.stdout = tofile print "%i base-%i digits of pi:\n" % (n, base) print intpart, ".\n" display_fraction(d, skip, colwidth=10, columns=5) if tofile: sys.stdout = out_ print "\nFinished in %f seconds (%f calc, %f convert)" % \ ((step1_time + step2_time), step1_time, step2_time) def interactive(): print "Compute digits of pi with mpmath\n" base = input("Which base? (2-36, 10 for decimal) \n> ") digits = input("How many digits? (enter a big number, say, 10000)\n> ") tofile = raw_input("Output to file? (enter a filename, or just press " \ "enter\nto print directly to the screen) \n> ") if tofile: tofile = open(tofile, "w") calculateit(base, digits, tofile) raw_input("\nPress enter to close this script.") if __name__ == "__main__": interactive() mpmath-1.1.0/demo/plotting.py000066400000000000000000000015741340375245600161550ustar00rootroot00000000000000""" Function plotting demo. """ from mpmath import * def main(): print """ Simple function plotting. You can enter one or several formulas, in ordinary Python syntax and using the mpmath function library. The variable is 'x'. So for example the input "sin(x/2)" (without quotation marks) defines a valid function. """ functions = [] for i in xrange(10): if i == 0: s = raw_input('Enter a function: ') else: s = raw_input('Enter another function (optional): ') if not s: print break f = eval("lambda x: " + s) functions.append(f) print "Added f(x) = " + s print xlim = raw_input('Enter xmin, xmax (optional): ') if xlim: xlim = eval(xlim) else: xlim = [-5, 5] print "Plotting..." plot(functions, xlim=xlim) main() mpmath-1.1.0/demo/taylor.py000066400000000000000000000036431340375245600156260ustar00rootroot00000000000000""" Interval arithmetic demo: estimating error of numerical Taylor series. This module can be run interactively with python taylor.py """ from mpmath import * def taylor(x, n): print "-"*75 t = x = mpi(x) s = 1 print "adding 1" print s, "\n" s += t print "adding x" print s, "\n" for k in range(2, n+1): t = (t * x) / k s += t print "adding x^%i / %i! ~= %s" % (k, k, t.mid) print s, "\n" print "-"*75 return s # Note: this should really be computed using interval arithmetic too! def remainder(x, n): xi = max(0, x) r = exp(xi) / factorial(n+1) r = r * x**(n+1) return abs(r) def exponential(x, n): """ Compute exp(x) using n terms of the Taylor series for exp using intervals, and print detailed error analysis. """ t = taylor(x, n) r = remainder(x, n) expx = exp(x) print "Correct value of exp(x): ", expx print print "Computed interval: " print t print print "Computed value (midpoint): ", t.mid print print "Estimated rounding error: ", t.delta print "Estimated truncation error: ", r print "Estimated total error: ", t.delta + r print "Actual error ", abs(expx - t.mid) print u = t + mpi(-r, r) print "Interval with est. truncation error added:" print u print print "Correct value contained in computed interval:", t.a <= expx <= t.b print "When accounting for truncation error:", u.a <= expx <= u.b if __name__ == "__main__": print "Interval arithmetic demo" print print "This script sums the Taylor series for exp(x) using interval arithmetic," print "and then compares the numerical errors due to rounding and truncation." print x = mpf(raw_input("Enter the value of x (e.g. 3.5): ")) n = int(raw_input("Enter the number of terms n (e.g. 10): ")) print exponential(x, n) mpmath-1.1.0/doc/000077500000000000000000000000001340375245600135555ustar00rootroot00000000000000mpmath-1.1.0/doc/build.py000066400000000000000000000002011340375245600152170ustar00rootroot00000000000000#!/usr/bin/env python import os if not os.path.exists("build"): os.mkdir("build") os.system("sphinx-build -E source build") mpmath-1.1.0/doc/source/000077500000000000000000000000001340375245600150555ustar00rootroot00000000000000mpmath-1.1.0/doc/source/basics.txt000066400000000000000000000212451340375245600170660ustar00rootroot00000000000000Basic usage =========================== In interactive code examples that follow, it will be assumed that all items in the ``mpmath`` namespace have been imported:: >>> from mpmath import * Importing everything can be convenient, especially when using mpmath interactively, but be careful when mixing mpmath with other libraries! To avoid inadvertently overriding other functions or objects, explicitly import only the needed objects, or use the ``mpmath.`` or ``mp.`` namespaces:: from mpmath import sin, cos sin(1), cos(1) import mpmath mpmath.sin(1), mpmath.cos(1) from mpmath import mp # mp context object -- to be explained mp.sin(1), mp.cos(1) Number types ------------ Mpmath provides the following numerical types: +------------+----------------+ | Class | Description | +============+================+ | ``mpf`` | Real float | +------------+----------------+ | ``mpc`` | Complex float | +------------+----------------+ | ``matrix`` | Matrix | +------------+----------------+ The following section will provide a very short introduction to the types ``mpf`` and ``mpc``. Intervals and matrices are described further in the documentation chapters on interval arithmetic and matrices / linear algebra. The ``mpf`` type is analogous to Python's built-in ``float``. It holds a real number or one of the special values ``inf`` (positive infinity), ``-inf`` (negative infinity) and ``nan`` (not-a-number, indicating an indeterminate result). You can create ``mpf`` instances from strings, integers, floats, and other ``mpf`` instances: >>> mpf(4) mpf('4.0') >>> mpf(2.5) mpf('2.5') >>> mpf("1.25e6") mpf('1250000.0') >>> mpf(mpf(2)) mpf('2.0') >>> mpf("inf") mpf('+inf') The ``mpc`` type represents a complex number in rectangular form as a pair of ``mpf`` instances. It can be constructed from a Python ``complex``, a real number, or a pair of real numbers: >>> mpc(2,3) mpc(real='2.0', imag='3.0') >>> mpc(complex(2,3)).imag mpf('3.0') You can mix ``mpf`` and ``mpc`` instances with each other and with Python numbers: >>> mpf(3) + 2*mpf('2.5') + 1.0 mpf('9.0') >>> mp.dps = 15 # Set precision (see below) >>> mpc(1j)**0.5 mpc(real='0.70710678118654757', imag='0.70710678118654757') Setting the precision --------------------- Mpmath uses a global working precision; it does not keep track of the precision or accuracy of individual numbers. Performing an arithmetic operation or calling ``mpf()`` rounds the result to the current working precision. The working precision is controlled by a context object called ``mp``, which has the following default state: >>> print(mp) Mpmath settings: mp.prec = 53 [default: 53] mp.dps = 15 [default: 15] mp.trap_complex = False [default: False] The term **prec** denotes the binary precision (measured in bits) while **dps** (short for *decimal places*) is the decimal precision. Binary and decimal precision are related roughly according to the formula ``prec = 3.33*dps``. For example, it takes a precision of roughly 333 bits to hold an approximation of pi that is accurate to 100 decimal places (actually slightly more than 333 bits is used). Changing either precision property of the ``mp`` object automatically updates the other; usually you just want to change the ``dps`` value: >>> mp.dps = 100 >>> mp.dps 100 >>> mp.prec 336 When the precision has been set, all ``mpf`` operations are carried out at that precision:: >>> mp.dps = 50 >>> mpf(1) / 6 mpf('0.16666666666666666666666666666666666666666666666666656') >>> mp.dps = 25 >>> mpf(2) ** mpf('0.5') mpf('1.414213562373095048801688713') The precision of complex arithmetic is also controlled by the ``mp`` object: >>> mp.dps = 10 >>> mpc(1,2) / 3 mpc(real='0.3333333333321', imag='0.6666666666642') There is no restriction on the magnitude of numbers. An ``mpf`` can for example hold an approximation of a large Mersenne prime: >>> mp.dps = 15 >>> print(mpf(2)**32582657 - 1) 1.24575026015369e+9808357 Or why not 1 googolplex: >>> print(mpf(10) ** (10**100)) # doctest:+ELLIPSIS 1.0e+100000000000000000000000000000000000000000000000000... The (binary) exponent is stored exactly and is independent of the precision. Temporarily changing the precision .................................. It is often useful to change the precision during only part of a calculation. A way to temporarily increase the precision and then restore it is as follows: >>> mp.prec += 2 >>> # do_something() >>> mp.prec -= 2 Since Python 2.5, the ``with`` statement along with the mpmath functions ``workprec``, ``workdps``, ``extraprec`` and ``extradps`` can be used to temporarily change precision in a more safe manner: >>> from __future__ import with_statement # only need this in Python 2.5 >>> with workdps(20): # doctest: +SKIP ... print(mpf(1)/7) ... with extradps(10): ... print(mpf(1)/7) ... 0.14285714285714285714 0.142857142857142857142857142857 >>> mp.dps 15 The ``with`` statement ensures that the precision gets reset when exiting the block, even in the case that an exception is raised. (The effect of the ``with`` statement can be emulated in Python 2.4 by using a ``try/finally`` block.) The ``workprec`` family of functions can also be used as function decorators: >>> @workdps(6) ... def f(): ... return mpf(1)/3 ... >>> f() mpf('0.33333331346511841') Some functions accept the ``prec`` and ``dps`` keyword arguments and this will override the global working precision. Note that this will not affect the precision at which the result is printed, so to get all digits, you must either use increase precision afterward when printing or use ``nstr``/``nprint``: >>> mp.dps = 15 >>> print(exp(1)) 2.71828182845905 >>> print(exp(1, dps=50)) # Extra digits won't be printed 2.71828182845905 >>> nprint(exp(1, dps=50), 50) 2.7182818284590452353602874713526624977572470937 Finally, instead of using the global context object ``mp``, you can create custom contexts and work with methods of those instances instead of global functions. The working precision will be local to each context object: >>> mp2 = mp.clone() >>> mp.dps = 10 >>> mp2.dps = 20 >>> print(mp.mpf(1) / 3) 0.3333333333 >>> print(mp2.mpf(1) / 3) 0.33333333333333333333 **Note**: the ability to create multiple contexts is a new feature that is only partially implemented. Not all mpmath functions are yet available as context-local methods. In the present version, you are likely to encounter bugs if you try mixing different contexts. Providing correct input ----------------------- Note that when creating a new ``mpf``, the value will at most be as accurate as the input. *Be careful when mixing mpmath numbers with Python floats*. When working at high precision, fractional ``mpf`` values should be created from strings or integers: >>> mp.dps = 30 >>> mpf(10.9) # bad mpf('10.9000000000000003552713678800501') >>> mpf('10.9') # good mpf('10.8999999999999999999999999999997') >>> mpf(109) / mpf(10) # also good mpf('10.8999999999999999999999999999997') >>> mp.dps = 15 (Binary fractions such as 0.5, 1.5, 0.75, 0.125, etc, are generally safe as input, however, since those can be represented exactly by Python floats.) Printing -------- By default, the ``repr()`` of a number includes its type signature. This way ``eval`` can be used to recreate a number from its string representation: >>> eval(repr(mpf(2.5))) mpf('2.5') Prettier output can be obtained by using ``str()`` or ``print``, which hide the ``mpf`` and ``mpc`` signatures and also suppress rounding artifacts in the last few digits: >>> mpf("3.14159") mpf('3.1415899999999999') >>> print(mpf("3.14159")) 3.14159 >>> print(mpc(1j)**0.5) (0.707106781186548 + 0.707106781186548j) Setting the ``mp.pretty`` option will use the ``str()``-style output for ``repr()`` as well: >>> mp.pretty = True >>> mpf(0.6) 0.6 >>> mp.pretty = False >>> mpf(0.6) mpf('0.59999999999999998') The number of digits with which numbers are printed by default is determined by the working precision. To specify the number of digits to show without changing the working precision, use :func:`mpmath.nstr` and :func:`mpmath.nprint`: >>> a = mpf(1) / 6 >>> a mpf('0.16666666666666666') >>> nstr(a, 8) '0.16666667' >>> nprint(a, 8) 0.16666667 >>> nstr(a, 50) '0.16666666666666665741480812812369549646973609924316' mpmath-1.1.0/doc/source/calculus/000077500000000000000000000000001340375245600166705ustar00rootroot00000000000000mpmath-1.1.0/doc/source/calculus/approximation.txt000066400000000000000000000007651340375245600223330ustar00rootroot00000000000000Function approximation ---------------------- Taylor series (``taylor``) .......................... .. autofunction:: mpmath.taylor Pade approximation (``pade``) ............................. .. autofunction:: mpmath.pade Chebyshev approximation (``chebyfit``) ...................................... .. autofunction:: mpmath.chebyfit Fourier series (``fourier``, ``fourierval``) ............................................ .. autofunction:: mpmath.fourier .. autofunction:: mpmath.fourierval mpmath-1.1.0/doc/source/calculus/differentiation.txt000066400000000000000000000010231340375245600225770ustar00rootroot00000000000000Differentiation --------------- Numerical derivatives (``diff``, ``diffs``) ........................................... .. autofunction:: mpmath.diff .. autofunction:: mpmath.diffs Composition of derivatives (``diffs_prod``, ``diffs_exp``) .......................................................... .. autofunction:: mpmath.diffs_prod .. autofunction:: mpmath.diffs_exp Fractional derivatives / differintegration (``differint``) ............................................................ .. autofunction:: mpmath.differint mpmath-1.1.0/doc/source/calculus/index.txt000066400000000000000000000003401340375245600205350ustar00rootroot00000000000000Numerical calculus ================== .. toctree:: :maxdepth: 2 polynomials.txt optimization.txt sums_limits.txt differentiation.txt integration.txt odes.txt approximation.txt inverselaplace.txt mpmath-1.1.0/doc/source/calculus/integration.txt000066400000000000000000000011131340375245600217500ustar00rootroot00000000000000Numerical integration (quadrature) ---------------------------------- Standard quadrature (``quad``) .............................. .. autofunction:: mpmath.quad Oscillatory quadrature (``quadosc``) .................................... .. autofunction:: mpmath.quadosc Quadrature rules ................ .. autoclass:: mpmath.calculus.quadrature.QuadratureRule :members: Tanh-sinh rule ~~~~~~~~~~~~~~ .. autoclass:: mpmath.calculus.quadrature.TanhSinh :members: Gauss-Legendre rule ~~~~~~~~~~~~~~~~~~~ .. autoclass:: mpmath.calculus.quadrature.GaussLegendre :members: mpmath-1.1.0/doc/source/calculus/inverselaplace.txt000066400000000000000000000034321340375245600224300ustar00rootroot00000000000000Numerical inverse Laplace transform ----------------------------------- One-step algorithm (``invertlaplace``) ...................................... .. autofunction:: mpmath.invertlaplace Specific algorithms ................... Fixed Talbot algorithm ~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: mpmath.calculus.inverselaplace.FixedTalbot :members: Gaver-Stehfest algorithm ~~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: mpmath.calculus.inverselaplace.Stehfest :members: de Hoog, Knight & Stokes algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: mpmath.calculus.inverselaplace.deHoog :members: Manual approach ............... It is possible and sometimes beneficial to re-create some of the functionality in ``invertlaplace``. This could be used to compute the Laplace-space function evaluations in a different way. For example, the Laplace-space function evaluations could be the result of a quadrature or sum, solution to a system of ordinary differential equations, or possibly computed in parallel from some external library or function call. A trivial example showing the process (which could be implemented using the existing interface): >>> from mpmath import * >>> myTalbot = calculus.inverselaplace.FixedTalbot(mp) >>> t = convert(0.25) >>> myTalbot.calc_laplace_parameter(t) >>> fp = lambda p: 1/(p + 1) - 1/(p + 1000) >>> ft = lambda t: exp(-t) - exp(-1000*t) >>> fpvec = [fp(p) for p in myTalbot.p] >>> ft(t)-myTalbot.calc_time_domain_solution(fpvec,t,manual_prec=True) mpf('1.928300179528890061756872185e-21') This manual approach is also useful to look at the Laplace parameter, order, or working precision which were computed. >>> myTalbot.degree 34 Credit ...... The numerical inverse Laplace transform functionality was contributed to mpmath by Kristopher L. Kuhlman in 2017. mpmath-1.1.0/doc/source/calculus/odes.txt000066400000000000000000000003101340375245600203550ustar00rootroot00000000000000Ordinary differential equations ------------------------------- Solving the ODE initial value problem (``odefun``) .................................................. .. autofunction:: mpmath.odefun mpmath-1.1.0/doc/source/calculus/optimization.txt000066400000000000000000000017551340375245600221670ustar00rootroot00000000000000Root-finding and optimization ----------------------------- Root-finding (``findroot``) ........................... .. autofunction:: mpmath.findroot(f, x0, solver=Secant, tol=None, verbose=False, verify=True, **kwargs) Solvers ^^^^^^^ .. autoclass:: mpmath.calculus.optimization.Secant .. autoclass:: mpmath.calculus.optimization.Newton .. autoclass:: mpmath.calculus.optimization.MNewton .. autoclass:: mpmath.calculus.optimization.Halley .. autoclass:: mpmath.calculus.optimization.Muller .. autoclass:: mpmath.calculus.optimization.Bisection .. autoclass:: mpmath.calculus.optimization.Illinois .. autoclass:: mpmath.calculus.optimization.Pegasus .. autoclass:: mpmath.calculus.optimization.Anderson .. autoclass:: mpmath.calculus.optimization.Ridder .. autoclass:: mpmath.calculus.optimization.ANewton .. autoclass:: mpmath.calculus.optimization.MDNewton .. Minimization and maximization (``findmin``, ``findmax``) .. ........................................................ .. (To be added.) mpmath-1.1.0/doc/source/calculus/polynomials.txt000066400000000000000000000005071340375245600220010ustar00rootroot00000000000000Polynomials ----------- See also :func:`taylor` and :func:`chebyfit` for approximation of functions by polynomials. Polynomial evaluation (``polyval``) ................................... .. autofunction:: mpmath.polyval Polynomial roots (``polyroots``) ................................ .. autofunction:: mpmath.polyroots mpmath-1.1.0/doc/source/calculus/sums_limits.txt000066400000000000000000000030071340375245600220010ustar00rootroot00000000000000Sums, products, limits and extrapolation ---------------------------------------- The functions listed here permit approximation of infinite sums, products, and other sequence limits. Use :func:`mpmath.fsum` and :func:`mpmath.fprod` for summation and multiplication of finite sequences. Summation .......................................... :func:`nsum` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nsum :func:`sumem` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sumem :func:`sumap` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sumap Products ............................... :func:`nprod` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nprod Limits (``limit``) .................. :func:`limit` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.limit Extrapolation .......................................... The following functions provide a direct interface to extrapolation algorithms. :func:`nsum` and :func:`limit` essentially work by calling the following functions with an increasing number of terms until the extrapolated limit is accurate enough. The following functions may be useful to call directly if the precise number of terms needed to achieve a desired accuracy is known in advance, or if one wishes to study the convergence properties of the algorithms. :func:`richardson` ^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.richardson :func:`shanks` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.shanks :func:`levin` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.levin :func:`cohen_alt` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.cohen_alt mpmath-1.1.0/doc/source/conf.py000066400000000000000000000103771340375245600163640ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # mpmath documentation build configuration file, created by # sphinx-quickstart on Sun Apr 13 00:14:30 2008. # # This file is execfile()d with the current directory set to its containing dir. # # The contents of this file are pickled, so don't put values in the namespace # that aren't pickleable (module imports are okay, they're removed automatically). # # All configuration values have a default value; values that are commented out # serve to show the default value. import sys # If your extensions are in another directory, add it here. sys.path.insert(0, '../..') # General configuration # --------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.mathjax'] # MathJax file, which is free to use. See http://www.mathjax.org/docs/2.0/start.html # mathjax_path = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full' # Add any paths that contain templates here, relative to this directory. templates_path = [] # The suffix of source filenames. source_suffix = '.txt' # The master toctree document. master_doc = 'index' # General substitutions. project = 'mpmath' copyright = '2007-2018, Fredrik Johansson and mpmath developers' # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. # # The short X.Y version. import mpmath version = mpmath.__version__ # The full version, including alpha/beta/rc tags. release = mpmath.__version__ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # Options for HTML output # ----------------------- # The "theme" that the HTML output should use. html_theme = 'classic' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Content template for the index page. #html_index = '' # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If true, the reST sources are included in the HTML build as _sources/. #html_copy_source = True # Output file base name for HTML help builder. htmlhelp_basename = 'mpmathdoc' # Options for LaTeX output # ------------------------ # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). latex_documents = [(master_doc, 'main.tex', 'mpmath documentation', r'Fredrik Johansson \and mpmath contributors', 'manual')] # Additional stuff for the LaTeX preamble. latex_preamble = r'\usepackage{amsfonts}' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True default_role = 'math' pngmath_dvipng_args = ['-gamma 1.5', '-D 110'] mpmath-1.1.0/doc/source/contexts.txt000066400000000000000000000271251340375245600174740ustar00rootroot00000000000000Contexts ======== High-level code in mpmath is implemented as methods on a "context object". The context implements arithmetic, type conversions and other fundamental operations. The context also holds settings such as precision, and stores cache data. A few different contexts (with a mostly compatible interface) are provided so that the high-level algorithms can be used with different implementations of the underlying arithmetic, allowing different features and speed-accuracy tradeoffs. Currently, mpmath provides the following contexts: * Arbitrary-precision arithmetic (``mp``) * A faster Cython-based version of ``mp`` (used by default in Sage, and currently only available there) * Arbitrary-precision interval arithmetic (``iv``) * Double-precision arithmetic using Python's builtin ``float`` and ``complex`` types (``fp``) Most global functions in the global mpmath namespace are actually methods of the ``mp`` context. This fact is usually transparent to the user, but sometimes shows up in the form of an initial parameter called "ctx" visible in the help for the function:: >>> import mpmath >>> help(mpmath.fsum) # doctest:+SKIP Help on method fsum in module mpmath.ctx_mp_python: fsum(ctx, terms, absolute=False, squared=False) method of mpmath.ctx_mp.MPContext instance Calculates a sum containing a finite number of terms (for infinite series, see :func:`~mpmath.nsum`). The terms will be converted to ... The following operations are equivalent:: >>> mpmath.mp.dps = 15; mpmath.mp.pretty = False >>> mpmath.fsum([1,2,3]) mpf('6.0') >>> mpmath.mp.fsum([1,2,3]) mpf('6.0') The corresponding operation using the ``fp`` context:: >>> mpmath.fp.fsum([1,2,3]) 6.0 Common interface ---------------- ``ctx.mpf`` creates a real number:: >>> from mpmath import mp, fp >>> mp.mpf(3) mpf('3.0') >>> fp.mpf(3) 3.0 ``ctx.mpc`` creates a complex number:: >>> mp.mpc(2,3) mpc(real='2.0', imag='3.0') >>> fp.mpc(2,3) (2+3j) ``ctx.matrix`` creates a matrix:: >>> mp.matrix([[1,0],[0,1]]) matrix( [['1.0', '0.0'], ['0.0', '1.0']]) >>> _[0,0] mpf('1.0') >>> fp.matrix([[1,0],[0,1]]) matrix( [['1.0', '0.0'], ['0.0', '1.0']]) >>> _[0,0] 1.0 ``ctx.prec`` holds the current precision (in bits):: >>> mp.prec 53 >>> fp.prec 53 ``ctx.dps`` holds the current precision (in digits):: >>> mp.dps 15 >>> fp.dps 15 ``ctx.pretty`` controls whether objects should be pretty-printed automatically by :func:`repr`. Pretty-printing for ``mp`` numbers is disabled by default so that they can clearly be distinguished from Python numbers and so that ``eval(repr(x)) == x`` works:: >>> mp.mpf(3) mpf('3.0') >>> mpf = mp.mpf >>> eval(repr(mp.mpf(3))) mpf('3.0') >>> mp.pretty = True >>> mp.mpf(3) 3.0 >>> fp.matrix([[1,0],[0,1]]) matrix( [['1.0', '0.0'], ['0.0', '1.0']]) >>> fp.pretty = True >>> fp.matrix([[1,0],[0,1]]) [1.0 0.0] [0.0 1.0] >>> fp.pretty = False >>> mp.pretty = False Arbitrary-precision floating-point (``mp``) --------------------------------------------- The ``mp`` context is what most users probably want to use most of the time, as it supports the most functions, is most well-tested, and is implemented with a high level of optimization. Nearly all examples in this documentation use ``mp`` functions. See :doc:`basics` for a description of basic usage. Arbitrary-precision interval arithmetic (``iv``) ------------------------------------------------ The ``iv.mpf`` type represents a closed interval `[a,b]`; that is, the set `\{x : a \le x \le b\}`, where `a` and `b` are arbitrary-precision floating-point values, possibly `\pm \infty`. The ``iv.mpc`` type represents a rectangular complex interval `[a,b] + [c,d]i`; that is, the set `\{z = x+iy : a \le x \le b \land c \le y \le d\}`. Interval arithmetic provides rigorous error tracking. If `f` is a mathematical function and `\hat f` is its interval arithmetic version, then the basic guarantee of interval arithmetic is that `f(v) \subseteq \hat f(v)` for any input interval `v`. Put differently, if an interval represents the known uncertainty for a fixed number, any sequence of interval operations will produce an interval that contains what would be the result of applying the same sequence of operations to the exact number. The principal drawbacks of interval arithmetic are speed (``iv`` arithmetic is typically at least two times slower than ``mp`` arithmetic) and that it sometimes provides far too pessimistic bounds. .. note :: The support for interval arithmetic in mpmath is still experimental, and many functions do not yet properly support intervals. Please use this feature with caution. Intervals can be created from single numbers (treated as zero-width intervals) or pairs of endpoint numbers. Strings are treated as exact decimal numbers. Note that a Python float like ``0.1`` generally does not represent the same number as its literal; use ``'0.1'`` instead:: >>> from mpmath import iv >>> iv.dps = 15; iv.pretty = False >>> iv.mpf(3) mpi('3.0', '3.0') >>> print(iv.mpf(3)) [3.0, 3.0] >>> iv.pretty = True >>> iv.mpf([2,3]) [2.0, 3.0] >>> iv.mpf(0.1) # probably not intended [0.10000000000000000555, 0.10000000000000000555] >>> iv.mpf('0.1') # good, gives a containing interval [0.099999999999999991673, 0.10000000000000000555] >>> iv.mpf(['0.1', '0.2']) [0.099999999999999991673, 0.2000000000000000111] The fact that ``'0.1'`` results in an interval of nonzero width indicates that 1/10 cannot be represented using binary floating-point numbers at this precision level (in fact, it cannot be represented exactly at any precision). Intervals may be infinite or half-infinite:: >>> print(1 / iv.mpf([2, 'inf'])) [0.0, 0.5] The equality testing operators ``==`` and ``!=`` check whether their operands are identical as intervals; that is, have the same endpoints. The ordering operators ``< <= > >=`` permit inequality testing using triple-valued logic: a guaranteed inequality returns ``True`` or ``False`` while an indeterminate inequality returns ``None``:: >>> iv.mpf([1,2]) == iv.mpf([1,2]) True >>> iv.mpf([1,2]) != iv.mpf([1,2]) False >>> iv.mpf([1,2]) <= 2 True >>> iv.mpf([1,2]) > 0 True >>> iv.mpf([1,2]) < 1 False >>> iv.mpf([1,2]) < 2 # returns None >>> iv.mpf([2,2]) < 2 False >>> iv.mpf([1,2]) <= iv.mpf([2,3]) True >>> iv.mpf([1,2]) < iv.mpf([2,3]) # returns None >>> iv.mpf([1,2]) < iv.mpf([-1,0]) False The ``in`` operator tests whether a number or interval is contained in another interval:: >>> iv.mpf([0,2]) in iv.mpf([0,10]) True >>> 3 in iv.mpf(['-inf', 0]) False Intervals have the properties ``.a``, ``.b`` (endpoints), ``.mid``, and ``.delta`` (width):: >>> x = iv.mpf([2, 5]) >>> x.a [2.0, 2.0] >>> x.b [5.0, 5.0] >>> x.mid [3.5, 3.5] >>> x.delta [3.0, 3.0] Some transcendental functions are supported:: >>> iv.dps = 15 >>> mp.dps = 15 >>> iv.mpf([0.5,1.5]) ** iv.mpf([0.5, 1.5]) [0.35355339059327373086, 1.837117307087383633] >>> iv.exp(0) [1.0, 1.0] >>> iv.exp(['-inf','inf']) [0.0, +inf] >>> >>> iv.exp(['-inf',0]) [0.0, 1.0] >>> iv.exp([0,'inf']) [1.0, +inf] >>> iv.exp([0,1]) [1.0, 2.7182818284590455349] >>> >>> iv.log(1) [0.0, 0.0] >>> iv.log([0,1]) [-inf, 0.0] >>> iv.log([0,'inf']) [-inf, +inf] >>> iv.log(2) [0.69314718055994528623, 0.69314718055994539725] >>> >>> iv.sin([100,'inf']) [-1.0, 1.0] >>> iv.cos(['-0.1','0.1']) [0.99500416527802570954, 1.0] Interval arithmetic is useful for proving inequalities involving irrational numbers. Naive use of ``mp`` arithmetic may result in wrong conclusions, such as the following:: >>> mp.dps = 25 >>> x = mp.exp(mp.pi*mp.sqrt(163)) >>> y = mp.mpf(640320**3+744) >>> print(x) 262537412640768744.0000001 >>> print(y) 262537412640768744.0 >>> x > y True But the correct result is `e^{\pi \sqrt{163}} < 262537412640768744`, as can be seen by increasing the precision:: >>> mp.dps = 50 >>> print(mp.exp(mp.pi*mp.sqrt(163))) 262537412640768743.99999999999925007259719818568888 With interval arithmetic, the comparison returns ``None`` until the precision is large enough for `x-y` to have a definite sign:: >>> iv.dps = 15 >>> iv.exp(iv.pi*iv.sqrt(163)) > (640320**3+744) >>> iv.dps = 30 >>> iv.exp(iv.pi*iv.sqrt(163)) > (640320**3+744) >>> iv.dps = 60 >>> iv.exp(iv.pi*iv.sqrt(163)) > (640320**3+744) False >>> iv.dps = 15 Fast low-precision arithmetic (``fp``) --------------------------------------------- Although mpmath is generally designed for arbitrary-precision arithmetic, many of the high-level algorithms work perfectly well with ordinary Python ``float`` and ``complex`` numbers, which use hardware double precision (on most systems, this corresponds to 53 bits of precision). Whereas the global functions (which are methods of the ``mp`` object) always convert inputs to mpmath numbers, the ``fp`` object instead converts them to ``float`` or ``complex``, and in some cases employs basic functions optimized for double precision. When large amounts of function evaluations (numerical integration, plotting, etc) are required, and when ``fp`` arithmetic provides sufficient accuracy, this can give a significant speedup over ``mp`` arithmetic. To take advantage of this feature, simply use the ``fp`` prefix, i.e. write ``fp.func`` instead of ``func`` or ``mp.func``:: >>> u = fp.erfc(2.5) >>> print(u) # doctest:+SKIP 0.000406952017445 >>> type(u) # doctest:+SKIP >>> mp.dps = 15 >>> print(mp.erfc(2.5)) 0.000406952017444959 >>> fp.matrix([[1,2],[3,4]]) ** 2 matrix( [['7.0', '10.0'], ['15.0', '22.0']]) >>> >>> type(_[0,0]) # doctest:+SKIP >>> print(fp.quad(fp.sin, [0, fp.pi])) # numerical integration 2.0 The ``fp`` context wraps Python's ``math`` and ``cmath`` modules for elementary functions. It supports both real and complex numbers and automatically generates complex results for real inputs (``math`` raises an exception):: >>> fp.sqrt(5) # doctest:+SKIP 2.23606797749979 >>> fp.sqrt(-5) # doctest:+SKIP 2.23606797749979j >>> fp.sin(10) # doctest:+SKIP -0.5440211108893698 >>> fp.power(-1, 0.25) # doctest:+SKIP (0.7071067811865476+0.7071067811865475j) >>> (-1) ** 0.25 # doctest:+SKIP Traceback (most recent call last): ... ValueError: negative number cannot be raised to a fractional power The ``prec`` and ``dps`` attributes can be changed (for interface compatibility with the ``mp`` context) but this has no effect:: >>> fp.prec 53 >>> fp.dps 15 >>> fp.prec = 80 >>> fp.prec 53 >>> fp.dps 15 Due to intermediate rounding and cancellation errors, results computed with ``fp`` arithmetic may be much less accurate than those computed with ``mp`` using an equivalent precision (``mp.prec = 53``), since the latter often uses increased internal precision. The accuracy is highly problem-dependent: for some functions, ``fp`` almost always gives 14-15 correct digits; for others, results can be accurate to only 2-3 digits or even completely wrong. The recommended use for ``fp`` is therefore to speed up large-scale computations where accuracy can be verified in advance on a subset of the input set, or where results can be verified afterwards. mpmath-1.1.0/doc/source/cplot.png000066400000000000000000001230571340375245600167140ustar00rootroot00000000000000PNG  IHDRh7( IDATx^A@ aV3[m$I:X)o"~SQ$p.dе0``  00``  00``  00``u;cV[B T Zp 8\Ef} 2Hv/`P,vH:1(qL ^8w@wP3Uoy*x>ܙszVok|Ȱx=mcyeջY+=gw'T֦M]tN= f 2pekj 0mX'>w_aNmZ|0 dh5Zu[50\Za>\ۚ/k?z31Q7hoOAz}kZ@W`l+V6G 5``/ߥu5mjϗGß &k;b09œf4U͝<=C?>mfOk5Fޟp'=͵aݷ e-h2am-b._ Vfy4iA!d՛V[ @wBHz=(h4ρՁOMw}opY×k^r̃I3*xvxW1&;k*_WmಲX2 aأLP%P*n5)_êꊶuה/㎶,,jFCN"Y ^ ys5t 6f 6M|=yC~V.+1v\SrvU\ \Tv, (\| ɱ<c sz[vY|)K5zosoj84`lߟ#pŌg:\V/@8Ge۱ ]Za2fe'><^+aBPWu><+d16LoNƜli@7ߡ uE/T} !ܡ@I/h[,_ 4ZsOk¯ eeJ@Ј$Gan fT91/m*{ZG- [.Fer~pwjJXlq{ _ o6IٯP j؅N< 6XLAߢ _;Ϋ`uA$-le+zQ:֨h<o_P9~)ƕ8'٠ P5!c"]!٫ۘkL_ &z.7רT!hNC2_;WaiegKabHTb/ %%fJji}ef[m_֎OmF;X SR7Uxp e|CW ~[+Ʈ;/s!dY(&fqKvg|0٢$g/a4ޡuG [s,Z|71vZ_l"fZ,ؒ^圏q+5cl& L$hYhA2#h6H23$)ihfN?n@9tS{WI!}̘γ9IVz'8JKH?9*XhC(Có]V.+^7cHTqn>|f;[X]DE:F aP`E3,ڦ_+uG%X; ~~Q݋c>ױn?bUJykcElK@@o=#jsO//ņϨӡ2i^wʗh3|1Kw47E|b*T&q_ئd5ت%_1 .k  ׯzsoE+ݜ3Uܣ;Uv/J\[䵭ncrУZ>{[Kabބ;s)=oXٹeL$`*_=x 6n\wۮ~aT@mk9뭷P.Q[nCI]ШCuG0 ѝ32! &ꗦBe{?Z[S_+!~9ڼ\&|H|MկbpN+_K3bj0Z%,J˄+dGbJϛj8a–BEmV9Wp[}xPnV4pp?XY }_ς\AgʗAB{s5|#xa q I b!̌;y$Rüb]zmOw_bO0uŠȩ\~:a7p;;SbӧR6`q"2(%^AyyMOP퀪P7ǽ|Uuf2p?A + [Y ՝C9/4siPהp)6!y\dj^A<n*Zd.$]:wM{$NP' L 6C Cb_Nkhe2$7}4Β+¹5KZ/@7V: ^"ą H' 8V4{ fCavW#Z aQE~,λ뙉XL1pwws >vi++9펔n6fj6{?=oqz f,x  ,*XoPRPj8˪^qxkNhW>JUđUn9=Wۖ[.}OGQ>$ OO^C:QNJˤa@4x ->e".,J\޳tЁsHKn(i;Y.馑ۙ 9Ͷ.3/},)Im7i6GC T [oಟܾ+a}ەh6{9^}̠K1 e9=m.,AH la+&C#BQH9H|xϸξaoSI\zJbSToU:cR36_SDo~߿m_3a񛫍˱`\%F?'k6^Lg58GlIR&g J1#&,ug LOTg#> sgpL^g&gv;g<Ş)nӶ@ \Omj}J}@m 7'0[ĺ[i<'xssoE|2JFfs g™Pη3 cs؏5+> fg!S~P.{VG# k13s~ 0 !LH_%g|[ʄ 8ѰTȆ֏cxݳgxqPnx RUg*Nul*GS*@~Z!T7 eg}_zk_~e_~%a:Y21Wl,0b2:07~~DžYaĚH[;кOїbvyƺîzą9,ҰkVxqKn\#͙g]{>mmL+}ן>?}7 xCưyxCT9s E7"a+>Y*aB*5_x& E70Lhg2~zʆ7@3Ը&2;τ#ew>fdƎ>j|oZY, ALQ:y~*X}EWt]/n3S3xp{iIYU,޷Ԉ l}6 3۸뭬\v.9s5rK@_/~rcuG\eĥq:3r3^ă5 kvM _5Y} @ZEؑSz^|wYL.ޱN)_04z9|ucU==`J`iK$`1v vD.2nj_|c7+;ƒ׽>Njo"( Elϸ9AbyNP?-#r9XUܼX0"| +ЇuNVtv>Jf0FКb%g`r\﹓ߩh>ت(۞׫rsGGx k`e2y W:cZJaJҢY &x!^ҌeYf>v|6XC 3ws r,~$*_n~/Reߍ Tnd>t#l/pu!ĪYTo޼Jlc ykljv;ۚB_\λSgV5yGr~^W4lY$`eG (a{ ^z&)*s=7$gAÃY(P2J TrNIpgʹ1CZ9-vqŇ*5+R ǐ/Zj|*63PV.cl{/lOuLPKK7wE]YKo݉_qGk yq{QI rff3.$P3%h u񱯲M[o T.XYLb5CX5}w:<`WTϴSsX/5 pY1_7Ibs/,$:6s<5I"0_W(L1?yVVOS2+7jᛯH&%QLX^+Jb2͟ X^ntWƂc|1Q<,a&8)~üC'z=ztnh_] %I `i[OpZ ">ܨp} OVd-f eP!YLzhюy2w4X8>Qm;!MK/85z^';︯5![lZ `i~vS~4*=%i8a qîaLZ82Ab\t=5$x7sbse5};0ysq`P>ꘘ44w3 nxƃFQep;@Xj+Icf4AݴI++mCC ¡ :0ccʾ5xˆ~pxxpg hjRAc[eܞ0qď@nfnS#㳧1]6S ojpSR&ё(.+,MB¢9zK63xnؙ~ơ?.Ud,czu~.ҍ]ΌU.e,U3273A<[%\!g6[ӠP.+A8g|9wG^4mЇ5us`P~G$z#5/=8|:anV5k9(A1GUhEd݁ ll?p◦^* 2ulcG"t1:7E35M^?*Q[Y,vsR9|U/>oԴk @?k1Gl؁{)&f#|s!/^= %b|HrqPjW}@ù78b4ik++]ה H8!;}3n9B^HfuǜgTS@ϛe–:Zf]^G%*&; XGasvĀp-e2'\OI'iRV:{&HzC;т"݌*hgnpLaeh%!\q o7}my'l]ۚv3+;z/n~c7pe0Y;.^q-Hݛ`M\6cwWs^MQٶԨeT cnH>A@\u%o2OpAZ؟`ApVyW:IMBY:^T~+BZ':x{s'̣nO^6^aSɢ 0uBfkv@ F;~zIww}? }_[ 冦KUpcrF!b܂S~C( qɈ:cI mvC7t &pŃf,xvl&qu;,j%SǦ8I|خ smJ\fT~@.+Wv4㜩:Jv\nCBXۚ*^Bf&e۔/ЭqnfF4޹T:VVL,خ^\k YЌ fTbΣ Z EǬ]Lsor>A'Lp1YPs;6'`#%nR<N%µx?\Gwc3ٮ蒄,|,x?~,3053Q-kiG\J w\\cw\骬\g:rqF{5-A= oGbN$n=2pSR8tJW8/\ѲRъǨ0w_c4b{:hs=ܐ۞]~VnȾJc4k5G8cw1!-6**0S իGX{6,HPPѳV>#x銶gX/`l1>dO <;X$}) KYBw?XPqD,yJWv4Hʜxo;hdu&S^m۰ō R7F+2ձ]o+qb|w.Lh{tI뒦kVU"h-Tx@v epFFhDZ4q\{6NkBdnf?UMئp0'kjh%^Q{%`U)_bh/VQ#ݍg1XjsI3ε'u((B|F2oYL9 Q.eڵ: F2VdV{<|YJk:SIފ(]vmufenCZ[wγV4xG@"*hMงg88kG- js/UrYz}uc̊^1@@0&|#"l$~ GME߻8K w`fX<#c=?Cngt3+z ?@e{&D&GqƤ a`w*akB/x7k@ vtx ]vg B.X~A lϔhTyޣ/PtI/QtܵhЧ874-ٮeDVV.>h.x1+"4fJiPp=Ye1\OchxrSbٶЏ>8CŋmkEtI/s9n.w5qx&4ՇubM9++sfMW mކp3뻡TokԆPƧQ! g@-'qvfhecb,֛ly! 3?8&^ ^ Ͷpw*W28qpL( X'7~h1)0X+@ 콿:pu{kfiv~7<ի{/|;37nKxm?zb{)" x͎r|T4_S bbqׂvT`_8>]~jTr^:,;͔گX^!'˻w~&NPW¬ .9a.TvwH75 kyJTl\+Q0.]"\C\a-ۚ[{bj7 LIG!xB3x s}/=ߕz o#&v,mHF< ]^L KPcob_{h%ow wnuԠZ4ic8V:S'/ԍ*,G A\Ԓ[ +^e_w P0DUA\6vn,^cqUt{#v9pAҷ.E|jLmL?aNIPF)xC4h_7\w븼ΥysەRϕU v(lԯLb>M?*7x~M~OU nMEoMLNf ;3L 29= B7BWftyWV)KTTQ)0d $4ZY K<̻R ӨT?Wz?7>O?,~^7:W<ճr]y繁%}ZF *:az0uʐibqT/CsS'tXYwn+٩}-woWd\<.#BY*n*w/δ-[-hY^v#2μ5⫿|U>צ/^w\;hhq]0{pN["׌BQn"@-x9Fyj7x݇理Q抩 }QI*q =ʣj'* =1ǂ~Lq܆B cڹ6>)m,UX@8PMfF,;+]0frN|35mdF j(I)>NMP\X^AXn#U"A1mל.RSYcJ [O^&.Z 'y:m5H[Xm k\#tnhTOՉ "k: Eo?Y99HG%_2v\vDbxf*_A8*[ ᫱D:ɠjkF(I5CNIgնL{b:f4 mˁB``w vk iq< A&C ~^'5&A&Aљ +b T.+`K9뗰 oc F.P;%.thp=l|=jHiZ.R&H%55iu/((A:1bxEF RQx ku:U:c` F4T[7DdMX9t-˵X۶h~Vmj?̟v)PefG!c7|;o5Hxq&DV?&\{h Q m e*8`h^dS@a}bm %j݉U6XLCSa(CeY-xtۗu:#WkǠLl%X kZJ}8Ӡjk0xoXXku[bU"KI %ßnj;ҬQ)Γ{s~Ճ*ⳅ^eIMjo*ĝ)7kc !8`Lø5HS֝@i S(D`]NemC]GM!2YI8*XEjU 2kf+o8L`=ϩBzLZKT9s\J9+~ H=dj3u`]}^7nrQU~.%醞; t Z>Vފs6 ˨AW,**ad5vo' dҞP7oR5u&%j=T'蠆1$Fu a𡚟F_nWM•cG (I>~)^^Azzm L)5Iw?!m.QupсB;WH t\rkU0;e+Vĕf,Y'h,I2uDP&t ymր<>c5(OY9ScIl aU.*ظ[ \Hi)ƃR6oq(̰ =-֜ 5eY d,:EBVV5EYpR[ k&Dv0QFw3 !ŽVi0F ݐ.vqlsL(1x\KblcKp;>|uZ0^ Y0O]_;;EL '5X{.A W/r[\Su3rPJKr*W6NPE9B-\ P܆rİ] g` Ȳ]'fa]{UO::f:*e];{n9+ |IbUہ1$d)lP6 Nnh݉Y*q?.CsO0+Rdr %FѢ˳6 69YmW@7pw*tw4:l1F< gtS 2gJЅS"-V#k3 .@[h^ngN߸qWqy*:{%,$0JP.P/>a ;T0c  IMNF :T&4nh\ť+ ׿*u^*e>[}`HG  kj~÷tk%$+:]tc9pd}#:>]GPW #ƌ#f0i"b7g21^HHc| )%-+]CmxK'!m]nZpwϞN=}|KςBo[R*xxZaPY0cN!,A{N**`Eƚ1Ec {qP-&Xgm!߂&Es[zcDmRyڀgqie-n_oƷqr~׾I姧O@ϢT-ҁhI6jUfC~ |`!D6ytqF؇퐔{Vp/.*sLX*Y.h &:0ULf06)OJvGr1_~_ܚH  ҝnawmi [pt֛oџɟ/_1IȰ4O*hjT/MT*SxŽ^l\KR 5U!Bx7fdCVeMHvXߞşǶ* zYޜƾ_yc72I@wc]Ax$`+ +d-Qj1`'HʩdZ3cݾ/Co<~~:@x3a"[G79ba{b'$Y 16teQaB9vψ|r{{4dJ*-E9!ngo$I&1["WSr<<ݨ.gD^. ݪ n^2_ V=痧{NooǑ5Mz%PS#&.Bc>Ѓ-U~ZMafc{vPKSNt#!S1@H! TARu9a_rpo"vsa;^YgB,}9ǹ4tV&x*ڵv<=s*y2>uwHī1}> x矿Cws*)ly$ ؆m:Sꍙn È 4fGUUT0dC\(rSSǐDاu+ K|61d7f/pBQ$KrMvPFA%fB܎ωS"T1f!H}u& Q 8+&F<-7wE W^1O]j>[_ 6,N_~Mn7ѣGŸ~>z_ lTϿ{ɷ?0EDQA)m3=%5y"k'[I“a96c4#%"5&5.yKpI/}JCNg5/IJ߰}iZa] 67z.:us~B|(E}w ծ~~E_C6c|Ec9':{HjitU8^Ct;{jvAɟ]~rIOvi%b]ş**ߡ]Q, b“_:&lK׏hߤ\o<5lu7>[9[r^r(=mжָ;z8:qj/{?"z./ޔ!v2/ÐQJ'IߦԀ"0W$XK~]CD_O`~ />gb;tMׯ_om>G8 p3uJpA쒮cF$_lۉM2{tEo#'z"Q'ݳ7ىQxs{Zw+Q~O/^s꯯곫ۏvKg?˛D. @ zBYH ^#+R\N1S'%QQ"&\s?|-τ).}@̺G*lPJ!OG77҆y[x I!LLr.!yܳFg9KOQ ktkp^6=3@؂X0|%߁-̝+[[/cӏW~W;V:8ZacsO僇D2}nA#XMp ktC燺LD_!;|JU>+Wmt#<햮E|H0|p\ƸWQPBYױWHo(hR*o @ͩ% ";@$DJܟH>C WmS(BV|qtb\> I|)\#Z2Vv=pWn3Puwy5$혀k(HҘr>IŘl LWz "*DRV8&d|PhGL>]oD'N?>)@Q i/Iiq*kT=o.y6~z-51%b:Bzۇr^Eh)wo*;!tϾǐ^r>=;B~o<&̓wTOzu{wD%ŋ9z&͈syMfN⊋>6ؒ% cx5y$賤x9_u|f^s]j6 a|[ɊJg{[DqN;@G8SS.]R !Ef!~ j(wdm% 2 :~xz^ y@N SGhTM_BoW1FtR sے94!DopңcL;(ag/y}&mގL(6w$)3rKH( sZ-mB&w!K&f9B|nF&oPB=D(7J:O~D?>As"I1K(S (+d´o-;*A9M5.—ERQT u=3xTA4 .0{.*m쨴1`k3v$1Z'c>Dq!s c끻?~Lݎӫ7i$t4QPSYVI50m!QC*.,/p={ :vU̓mpQӛ(5⠀/!eb:+VR^(A lB zB'tOzMpImjb ~cn5$7?#91HlǜIvg@BsEo9 :wnι?,.Q9 eLOT *`DU D'l89@r R,ÁzܛSǞ@jx\>Ƹ5a\:|D#W:>Qe0u*vyQ;L@,?㪫A[C Vmor 2`{O'5@8X7ݞ7DLBZK8u؆ݼ~<1;xɩJA M<0 T{]QBkdH| $Ico$pY{+o6<)^ 5lA, ⵅ#bILw ܲQҷyCUDS)ñr~D*_9Ym'V f:;UF"ދ=WuZF'+%ʠg OCq@'m9.}fJ—k+@Qn^ mE ԰=gi1uNK(* +ǓgX_s"ZVJnh#!_: X#KR^5Ty)^yg0k: ͅo֫2lZ^^B^߂[p!7`yX4(X݋ծY#/Ϊ8>B :V' 1 б_bOU` 1K][7W`IZ_d{RxjIVJCx h;B|+R^Ejaz&^UQA:̧ ɋFN%aQZh@!ϪƖ~) ^_H{ė.bM*=!,N j^z n+Y u*y[[|=pv}gn6p>6> b 0@%_N-_w}aV:,w&IzIkHxAP;)aW~<TH#ŁݬbR_(d a{x|lJAߡzU6 @> uVWU9:<VP`\锂-,I *Y!^p=[+,0u;-Qw|q9ᶚn^uw [VYPh:ՠ~r-$"`IThyuVMNƓcVE3CBX70 pq=Ly(j Fiz/9SfĈ[i[-\mR2+YymКڀ{:ޭ[l# Vp撐* q_OTj(Qj\AUل,kc*, /H@],IwŘ H կ./~u܆}mEA tr!im gyu 48+ nG@2CL c[ Ǐ$jxcd"ͭʪ_+U~-"-agl)/xʆqm+<+eolmH FLU,H%cc<eB]'܍T b wqaa IWB[> ۄ&WTg_jA,o.o]W_ㆶg}hJK4 }uּya.1Zc-=rTW5 ê1ar[[t t[ kr'*/0y[p7)L V&"[us$^M[p4_ 3Tm u sW] u~e9/V{~p++s >opAK[֒tcЀr$>^x6qWRBܸ3/nѐ:̻uw1J2 [VT+tbiO'k kدWeJtfW '=JjtrFrbQ'.6\ RJa٪WFq1`7 ]g5U-yTM&{SVh(PdEo=6G+@Z YX9ܪ*fiHV NĺRV8K@$c#f\OTNJuwùWVE&^5 mh[ R@% PLn ࣋d]v@€*F*J77d C0Q`^1ebpMAmQegsQ2=}eUj[p71_f@8pVBԈ5d:F; j "9AK{f! 8{&JԚޯ(c]s 6w(5 8;I57p-Ƅ뀅 vn;Y+wE0]rX0:Af>!CUH* suOOl=I66fXpP7edҊЀ"ad;k4W;ԍ'lHZA+ ~xǘۓ-h_ #~vL8 XS>=z}lʭ xU1 7mpnDZ{|1 n+^ewMrj^.ԩU`+u.W2q߭_uچzI_BҨv6aR s:=qoPWFBiH"F`ugP%lR ]X EȖ ֠9\l!l}'W) cpqCg+ rn `Ub@lbpȨ'(b.7 k`Ɣ:ט31NrHN~iujKQzRX[̺n aa0<@g>7U1+jG3ۊv-tłں+dCXH X5hm׵V vLfs;is ?MƂ5|[ 9N=P(?hSW}Y۶zU1_}dMmV׳Sv|U" |t#Ka|պQ|6fj GnC7nhXf\6U#g^n,ʥaI\Zb?\ q|EbLi{0ݟr(=ƅ{y@~#JIngI+% π8pY;RT~ѽ޸֐|uwE WXm9n!Y׳UWq_2=Y+omEڠ406'68+ֹv{0^ursci,9s.YAH{'oYDE$!/KB2;)<AQ !L{!h0*W>` .GrФV뫓LE^X0!L0w8[#WFxE]e&}ޛ D(ROA †UV4~"6n = i԰ٍaK:1β:YzRh;!W[% @AY w|K*R1\Y NuJu\g&Ŋx 䖵ZKxt帞~P1E±Xӟzf!M:>钮\-wUDL,J<ܾ=EěE]ʌxp\taT'eMg|T_Lq& KK  ZPҚ be6J"b\@L4(r qB\q ]uЀ ^u Px+z2@+ lMBV,vtU,7vz I 8q!ZDk# Vͳ׆ #R%Y4yۃlkbpTuj](ChÒn ,c_gY We>s{}Jj\pN7vC\ ]6<7QdD|]AnKin":&6*[jO'] ry@b|U1;k,_JhM**F+?KK ܫRMShe&P7ITq }r9s o.\R x5G}rX+O}ngĂAlu= ,@lXvSOvZ&D݅mϳY-WWg7 JWͨ^G2eg}$tdŮh. |kzN4ЙPƊWPBݏՏo?~/+D;*_ nÍx@lFVat*LtJR~sbAldY纶W 4 gzf(`'˵Uk45WFl=j]fd4°qH7rU7+ oTdb= m6<o?dI)*S[Wqb7h`+ZֵA'L3YgO]YQϨKh #IkgIبa~VttY$XZpnVRm?F |=p^t _}vK.MO?%|߽JgA ZTDFլT0ZfWt0y#8j7FͱTmPS kwܠ^ Ob m@MtxK $[+br6Y/Zv#\_X7q9cq; *U5LPr MO|z TBk_h@@]xKf3WWZR.IЫ-5jld+{{YJ:l -aiIFwv.yQjlr} i WQ*þg|0qr{[S *I`mO,fr7>H1`k@V/B*a3߀b݅"A-%=[k- 8vZ0e6`FڪM%^lhߦMO̮ATsV LP2v{ݑq=4{fTı5֘%{xt_iwt?˹48t9wsk8ԍ+ K?~8 _1VN𠏄-&ڴ;kWcE&8y3Lt|E+@ Rĺfqyxm~wPt}yN|utFwtQ+$+l1DRł3F‡nxE iA4 _&- X/ALupLb7>L5=:u=(<7Z8 Ąp \ʹqM/ut7w:ˏecw4 oV<Ǚ Y 6 t/zzPpMO'Nj r@+bߌJkReUIh6/"-ƸF_k$Cgl+XZJ N7ډeڠYn$YʝX,txN@)Ot[ p; fƺ@@8.i/ ^ v*b~`ă v끥K0ŇMkO6jjtul2Lkyfh'qjT)^jБRjo./{VfBvE YgiV)Ge53E+L&xbֳpzcơ KAn_ϑl~g6Lo4j'hx}NY\uV7q:BZ$uTFT\̀ZE$@9o&'Q: pg'QliUw\uU%<jXT¸9/fsM_|IpSL}kb[W5g}sGs/vGIVu`fF~gb**gO;*i|B/d@1–"k,1M^bu۟HH Л\XL+N[ pagQ&Py JT|W%5a{0GJ /k]k&i(ZS^B$DƇ$5,߀8)Vl!5lp`k98s~RN qsjN umZ Y^Ѭ #, iZƳJx x_K1'C p9 ZMGoNrq QmقA/X!4f%|qVk {6t?δqѾ&Sw; *Ov{?/|^cЄ!,18:jUcTq/a;`\a6cYjY`zȈky[PmJa iA46Z_L |eC;ކr$5H γ$f=KJ{>\V/EIZWkmyLL&;Yk\ ; @5._[UHi` v&*gA ,Y:Tc.CMa`׋mqt<k>r՝ ?8^p#RLgfHh7z\!^/v o@)5ixiB7iJw,BD,p ƃ3eҩg!˒$ b}.Y ʾK:߷eב .Ŋ9fK']%cl&4:Xy!6hk&WdiWҨW ]o 6%bw5TCiEI|Rì]PKQ C*y,*zn 5K,R}V3^^fHgU xF6U61|yutVg.Sݬ`%U59>#^-"|WˑWվ>6AaT-Amc-0T2PI_xʸyIn}Zk~.xXΰ$)i!biLȻ˒(?檗 Z3oi Jœn*D/[nej;A vTT1a:~7V`yt>x= j1]FGիdm igz> x}p)kXMPGwACH 5Anj(#|qubfTF3 oBLX3 sR.xU,7Kn|ՋuVtǮMO+N VTö9GcSv>ە. Řob#5U7 }ىpIC26cc2cˍ.q‘  k RpOpu˧Rn蚇i݃gY6<= XkPh&| pKёm| /hbR+_{Zi [LBVNM/teHWjڐ <׋ME8/bWt 2׃}^M*X0͚MO{T+dH#|?NE+=sn0$ײT̮CM7l$, B^pxF ^5̬gYFm9g>gt݄&9ppƝ\9PeL7 rQR+ Λs,VWr^\T8tؿM]~ q­?6Δ`oLY@U=4뤷fTlD餔mi *xE7[f2R‚c7TgY۴[Q%uG@1ߪ7`٩-]BS: (6ܨnX;*hN}Av3˞M8 EUn>p>mh-rR)2 Vx4oL_HiqNW&* TUcl`k*dN܋ATɀoRd3y<_=sJY)8F4 heo=fz{ 01+>mxv,gND7p_A\6{ kn3/mY\bՒ+|7'Jjgl aZAh33yjTRߍ "Vѭ큶iΑ@ae|&\& =TÏWT`>|W=V)=Қ j8_v!R1PGp3yN*`Zkc)wvs*A|PZMR3 kڟ?_{˗m?ns^k 7yMp,<+]0' ū3mlԯ:1`jxҼ#3eGʢ7m*i,x#5ti[M=u1K]I a<[^_>5#:Si#yHTUrJRQ\J>Wɭ-g Ҟ]O<췟-__yC&io0G\{U1PfM⍻^ A\vU\7(5b}4B8ª F gSK%L^{IVI^b}xMx ˺]jHGZVJ5}7ynN7O׾nk?w&Ο~,QqY('%]NYJ ;:c5$4T`3^sL 0@ !;%e ݌$w)``/AˆMC\ U0\\[τ̨w |@T^/#Y4~I҅\|5p=${W/坷 i?-74g"M^01}K}d Ӝ*IBg܄j #FRձFMn1]PTܻJܨ]L UI6ːoKGl9 ]Za~џ> m;hy@f߁9(p+sO͂d < a5B ٹh?_&ncZFR<|+d֓]^km!\N7q|sY!܀GQEpQ[O:m l@t —zƅpYk/m=9!K5 |Y[g!|Ī]~&baM}:[QN;PtfQǃx]z6d2×YĽ}작+N32MAtj|3=ptik09hncq~,X>tbŠniSOB=;ܻ _TҰނIG>7Ozi7ޛuf)]uYS6puکUE,LsEZZ}TP^tN [%ToUOyrKJ:aM xBz)V\Lˍb!\F) 39KJva ߂f=RF2F}c&lv{eEJF %u.-7*VU𫿓-o iToY:ٰ=ЕjxC\ˡ ŀQe4uK#̄C x3+ld07Wj*")TH6}J@kJxu6<?|q ePwXK'C8n/9vGv,W ¥BPA<*sogX98:J=/G⠅ mA[ol%7*ĕjͮJ(UeAP䬧N268Y}8|H%oѩ|\5qϬY90%dei7頛n Pp-?uhAI/㹺j_r`Ӧ zT|^K|o3]ҫ7bJ}lqˇa%^Y5p7&e)_/*Mpo=_C3lf]l1 g *(5hCJTU,j=H~zoզ6˝UI SF.īzD {Nγ/` %:Yϛ;Z VSYdJ+(z,KH(^f>?xnf'\ۥf?]O,};sS{>\cӦǨKwo~Ϡh}}UIOFUcArU IQUB\Y6C/~rV}.TeqѦ6{=Nހq n+S E,1*ծ ^&f,׬n/UC: W3wzYd\4'Ι* kRTi2㵂!J Zg ?'u,g 7;:*V\ 5`G,\}$P7w}#tE^V\j%PVd,V B<Jݥ,ʷMd$Z V$l2ۙ|򽐟l_j0R,+%U*d X`ʀF s {<,:`T1EꕠݏmVwvz̴[9co\m|dcO;/@ WSle+{l8.>#KUUYќddE+Vevd_knVa{O xۂo~`s:P_^|cw×xwG_7ςlFV:U勧}nA[ac-(eI DGТsa;=vb774n6m*੆7ո-'S| :G_Lg6rAs"QrpsU-출sZ325:!{\F/Tʄ.f;*X!Zkf%k9GE' E[S6mxB~}sJo1TS KLYWZjû@C! pE;9Wc| >h&h`PCk٠V%ʆ\5h!oRńnմi&=Z7?vƅ|5,(â×İN+ ӭJpRn k@xk p,gzlskEP`  5!+*!6<-Rl9bUL}"X VL%'.!DŽfs:*6^,?r5d5hoVw,JŃ@9v9kT ī|=>%7lo{wVpT*0! f8ݠ` }0e kك RcZՇv0Up$>-{PaB+LvPHA| dkt?4ip)ɹ|;_ 5`h244$nW\4wjN~Z\ީXKzmR(.jnب^C:] 2+/ 6Z&{$kRϥL1.Vfb͚g6ZqMY}D:I=.*|^0SoOܛ9ce`U~5SșXl,^48:a*Պ7ïe0PZkE_oJ2ytR\nb3`%$5RQXV\3sjFl,{#1b,^i ,Yo[w2ylRJ_9w3ܟp 5k!b梋]4#^g%EM*?>YL$<3Δqkk^vs7K&,H眧7VcX0'͠$2:2*:/9T,qG"=%L4~nȥ W$b3}ٿ PtA$, @gsg>v;/KRk3 ۺgG{ÁnGL(V n P"១gd+Yc=ު#묻vsٴ(d$I{0@}i^n2 y(}'? ǚ`Ft[S!Ǻwimܭ4tPGQXٔ0Z.c%W ;[_߆ߛՊN̊eP(AۀͲLZ|զ#Є@;d\|Eڄg&TB܈qkSgG 2`q2`OKBY@t̝2`Ȁ`4 @`  {КkIENDB`mpmath-1.1.0/doc/source/functions/000077500000000000000000000000001340375245600170655ustar00rootroot00000000000000mpmath-1.1.0/doc/source/functions/bessel.txt000066400000000000000000000104601340375245600211040ustar00rootroot00000000000000Bessel functions and related functions -------------------------------------- The functions in this section arise as solutions to various differential equations in physics, typically describing wavelike oscillatory behavior or a combination of oscillation and exponential decay or growth. Mathematically, they are special cases of the confluent hypergeometric functions `\,_0F_1`, `\,_1F_1` and `\,_1F_2` (see :doc:`hypergeometric`). Bessel functions ................................................... :func:`besselj` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.besselj(n,x,derivative=0) .. autofunction:: mpmath.j0(x) .. autofunction:: mpmath.j1(x) :func:`bessely` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bessely(n,x,derivative=0) :func:`besseli` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.besseli(n,x,derivative=0) :func:`besselk` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.besselk(n,x) Bessel function zeros ............................... :func:`besseljzero` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.besseljzero(v,m,derivative=0) :func:`besselyzero` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.besselyzero(v,m,derivative=0) Hankel functions ................ :func:`hankel1` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.hankel1(n,x) :func:`hankel2` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.hankel2(n,x) Kelvin functions ................ :func:`ber` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ber :func:`bei` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bei :func:`ker` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ker :func:`kei` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.kei Struve functions ................................................... :func:`struveh` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.struveh :func:`struvel` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.struvel Anger-Weber functions ................................................... :func:`angerj` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.angerj :func:`webere` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.webere Lommel functions ................................................... :func:`lommels1` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.lommels1 :func:`lommels2` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.lommels2 Airy and Scorer functions ............................................... :func:`airyai` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.airyai(z, derivative=0, **kwargs) :func:`airybi` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.airybi(z, derivative=0, **kwargs) :func:`airyaizero` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.airyaizero(k, derivative=0) :func:`airybizero` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.airybizero(k, derivative=0, complex=0) :func:`scorergi` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.scorergi(z, **kwargs) :func:`scorerhi` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.scorerhi(z, **kwargs) Coulomb wave functions ............................................... :func:`coulombf` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.coulombf(l,eta,z) :func:`coulombg` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.coulombg(l,eta,z) :func:`coulombc` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.coulombc(l,eta) Confluent U and Whittaker functions ................................... :func:`hyperu` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyperu(a, b, z) :func:`whitm` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.whitm(k,m,z) :func:`whitw` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.whitw(k,m,z) Parabolic cylinder functions ................................. :func:`pcfd` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.pcfd(n,z,**kwargs) :func:`pcfu` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.pcfu(a,z,**kwargs) :func:`pcfv` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.pcfv(a,z,**kwargs) :func:`pcfw` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.pcfw(a,z,**kwargs) mpmath-1.1.0/doc/source/functions/constants.txt000066400000000000000000000044031340375245600216430ustar00rootroot00000000000000Mathematical constants ---------------------- Mpmath supports arbitrary-precision computation of various common (and less common) mathematical constants. These constants are implemented as lazy objects that can evaluate to any precision. Whenever the objects are used as function arguments or as operands in arithmetic operations, they automagically evaluate to the current working precision. A lazy number can be converted to a regular ``mpf`` using the unary ``+`` operator, or by calling it as a function:: >>> from mpmath import * >>> mp.dps = 15 >>> pi >>> 2*pi mpf('6.2831853071795862') >>> +pi mpf('3.1415926535897931') >>> pi() mpf('3.1415926535897931') >>> mp.dps = 40 >>> pi >>> 2*pi mpf('6.283185307179586476925286766559005768394338') >>> +pi mpf('3.141592653589793238462643383279502884197169') >>> pi() mpf('3.141592653589793238462643383279502884197169') Exact constants ............... The predefined objects :data:`j` (imaginary unit), :data:`inf` (positive infinity) and :data:`nan` (not-a-number) are shortcuts to :class:`mpc` and :class:`mpf` instances with these fixed values. Pi (``pi``) .................................... .. autoattribute:: mpmath.mp.pi Degree (``degree``) .................................... .. autoattribute:: mpmath.mp.degree Base of the natural logarithm (``e``) ..................................... .. autoattribute:: mpmath.mp.e Golden ratio (``phi``) ...................... .. autoattribute:: mpmath.mp.phi Euler's constant (``euler``) ............................ .. autoattribute:: mpmath.mp.euler Catalan's constant (``catalan``) ................................ .. autoattribute:: mpmath.mp.catalan Apery's constant (``apery``) ............................ .. autoattribute:: mpmath.mp.apery Khinchin's constant (``khinchin``) .................................. .. autoattribute:: mpmath.mp.khinchin Glaisher's constant (``glaisher``) .................................. .. autoattribute:: mpmath.mp.glaisher Mertens constant (``mertens``) .................................. .. autoattribute:: mpmath.mp.mertens Twin prime constant (``twinprime``) ................................... .. autoattribute:: mpmath.mp.twinprime mpmath-1.1.0/doc/source/functions/elliptic.txt000066400000000000000000000034511340375245600214360ustar00rootroot00000000000000Elliptic functions ------------------ .. automodule :: mpmath.functions.elliptic Elliptic arguments ................................................... :func:`qfrom` ^^^^^^^^^^^^^ .. autofunction:: mpmath.qfrom(**kwargs) :func:`qbarfrom` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.qbarfrom(**kwargs) :func:`mfrom` ^^^^^^^^^^^^^ .. autofunction:: mpmath.mfrom(**kwargs) :func:`kfrom` ^^^^^^^^^^^^^ .. autofunction:: mpmath.kfrom(**kwargs) :func:`taufrom` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.taufrom(**kwargs) Legendre elliptic integrals ................................................... :func:`ellipk` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.ellipk(m, **kwargs) :func:`ellipf` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.ellipf(phi, m) :func:`ellipe` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.ellipe(*args) :func:`ellippi` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ellippi(*args) Carlson symmetric elliptic integrals ................................................... :func:`elliprf` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.elliprf(x, y, z) :func:`elliprc` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.elliprc(x, y, pv=True) :func:`elliprj` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.elliprj(x, y, z, p) :func:`elliprd` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.elliprd(x, y, z) :func:`elliprg` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.elliprg(x, y, z) Jacobi theta functions ...................... :func:`jtheta` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.jtheta(n,z,q,derivative=0) Jacobi elliptic functions ................................................................. :func:`ellipfun` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ellipfun(kind,u=None,m=None,q=None,k=None,tau=None) Modular functions ...................... :func:`kleinj` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.kleinj(tau=None, **kwargs) mpmath-1.1.0/doc/source/functions/expintegrals.txt000066400000000000000000000044131340375245600223350ustar00rootroot00000000000000Exponential integrals and error functions ----------------------------------------- Exponential integrals give closed-form solutions to a large class of commonly occurring transcendental integrals that cannot be evaluated using elementary functions. Integrals of this type include those with an integrand of the form `t^a e^{t}` or `e^{-x^2}`, the latter giving rise to the Gaussian (or normal) probability distribution. The most general function in this section is the incomplete gamma function, to which all others can be reduced. The incomplete gamma function, in turn, can be expressed using hypergeometric functions (see :doc:`hypergeometric`). Incomplete gamma functions .......................... :func:`gammainc` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.gammainc(z, a=0, b=inf, regularized=False) Exponential integrals ..................... :func:`ei` ^^^^^^^^^^ .. autofunction:: mpmath.ei(x, **kwargs) :func:`e1` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.e1(x, **kwargs) :func:`expint` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.expint(*args) Logarithmic integral .................... :func:`li` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.li(x, **kwargs) Trigonometric integrals ....................... :func:`ci` ^^^^^^^^^^ .. autofunction:: mpmath.ci(x, **kwargs) :func:`si` ^^^^^^^^^^ .. autofunction:: mpmath.si(x, **kwargs) Hyperbolic integrals .................... :func:`chi` ^^^^^^^^^^^ .. autofunction:: mpmath.chi(x, **kwargs) :func:`shi` ^^^^^^^^^^^ .. autofunction:: mpmath.shi(x, **kwargs) Error functions ............... :func:`erf` ^^^^^^^^^^^ .. autofunction:: mpmath.erf(x, **kwargs) :func:`erfc` ^^^^^^^^^^^^ .. autofunction:: mpmath.erfc(x, **kwargs) :func:`erfi` ^^^^^^^^^^^^ .. autofunction:: mpmath.erfi(x) :func:`erfinv` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.erfinv(x) The normal distribution .................................................... :func:`npdf` ^^^^^^^^^^^^ .. autofunction:: mpmath.npdf(x, mu=0, sigma=1) :func:`ncdf` ^^^^^^^^^^^^ .. autofunction:: mpmath.ncdf(x, mu=0, sigma=1) Fresnel integrals ...................................................... :func:`fresnels` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.fresnels(x) :func:`fresnelc` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.fresnelc(x) mpmath-1.1.0/doc/source/functions/gamma.txt000066400000000000000000000057421340375245600207200ustar00rootroot00000000000000Factorials and gamma functions ------------------------------ Factorials and factorial-like sums and products are basic tools of combinatorics and number theory. Much like the exponential function is fundamental to differential equations and analysis in general, the factorial function (and its extension to complex numbers, the gamma function) is fundamental to difference equations and functional equations. A large selection of factorial-like functions is implemented in mpmath. All functions support complex arguments, and arguments may be arbitrarily large. Results are numerical approximations, so to compute *exact* values a high enough precision must be set manually:: >>> from mpmath import mp, fac >>> mp.dps = 15; mp.pretty = True >>> fac(100) 9.33262154439442e+157 >>> print(int(_)) # most digits are wrong 93326215443944150965646704795953882578400970373184098831012889540582227238570431295066113089288327277825849664006524270554535976289719382852181865895959724032 >>> mp.dps = 160 >>> fac(100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000.0 The gamma and polygamma functions are closely related to :doc:`zeta`. See also :doc:`qfunctions` for q-analogs of factorial-like functions. Factorials .......... :func:`factorial`/:func:`fac` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.factorial(x, **kwargs) :func:`fac2` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.fac2(x) Binomial coefficients .................................................... :func:`binomial` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.binomial(n,k) Gamma function .............. :func:`gamma` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.gamma(x, **kwargs) :func:`rgamma` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.rgamma(x, **kwargs) :func:`gammaprod` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.gammaprod(a, b) :func:`loggamma` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.loggamma(x) Rising and falling factorials ............................. :func:`rf` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.rf(x,n) :func:`ff` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ff(x,n) Beta function ............. :func:`beta` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.beta(x,y) :func:`betainc` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.betainc(a,b,x1=0,x2=1,regularized=False) Super- and hyperfactorials .......................... :func:`superfac` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.superfac(z) :func:`hyperfac` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyperfac(z) :func:`barnesg` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.barnesg(z) Polygamma functions and harmonic numbers ........................................ :func:`psi`/:func:`digamma` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.psi(m, z) .. autofunction:: mpmath.digamma(z) :func:`harmonic` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.harmonic(z) mpmath-1.1.0/doc/source/functions/hyperbolic.txt000066400000000000000000000017301340375245600217670ustar00rootroot00000000000000Hyperbolic functions -------------------- Hyperbolic functions .................... :func:`cosh` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.cosh(x, **kwargs) :func:`sinh` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sinh(x, **kwargs) :func:`tanh` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.tanh(x, **kwargs) :func:`sech` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sech(x) :func:`csch` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.csch(x) :func:`coth` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.coth(x) Inverse hyperbolic functions ............................ :func:`acosh` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.acosh(x, **kwargs) :func:`asinh` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.asinh(x, **kwargs) :func:`atanh` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.atanh(x, **kwargs) :func:`asech` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.asech(x) :func:`acsch` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.acsch(x) :func:`acoth` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.acoth(x) mpmath-1.1.0/doc/source/functions/hypergeometric.txt000066400000000000000000000065511340375245600226630ustar00rootroot00000000000000Hypergeometric functions ------------------------ The functions listed in :doc:`expintegrals`, :doc:`bessel` and :doc:`orthogonal`, and many other functions as well, are merely particular instances of the generalized hypergeometric function `\,_pF_q`. The functions listed in the following section enable efficient direct evaluation of the underlying hypergeometric series, as well as linear combinations, limits with respect to parameters, and analytic continuations thereof. Extensions to twodimensional series are also provided. See also the basic or q-analog of the hypergeometric series in :doc:`qfunctions`. For convenience, most of the hypergeometric series of low order are provided as standalone functions. They can equivalently be evaluated using :func:`~mpmath.hyper`. As will be demonstrated in the respective docstrings, all the ``hyp#f#`` functions implement analytic continuations and/or asymptotic expansions with respect to the argument `z`, thereby permitting evaluation for `z` anywhere in the complex plane. Functions of higher degree can be computed via :func:`~mpmath.hyper`, but generally only in rapidly convergent instances. Most hypergeometric and hypergeometric-derived functions accept optional keyword arguments to specify options for :func:`hypercomb` or :func:`hyper`. Some useful options are *maxprec*, *maxterms*, *zeroprec*, *accurate_small*, *hmag*, *force_series*, *asymp_tol* and *eliminate*. These options give control over what to do in case of slow convergence, extreme loss of accuracy or evaluation at zeros (these two cases cannot generally be distinguished from each other automatically), and singular parameter combinations. Common hypergeometric series ............................ :func:`hyp0f1` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp0f1(a, z) :func:`hyp1f1` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp1f1(a, b, z) :func:`hyp1f2` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp1f2(a1, b1, b2, z) :func:`hyp2f0` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp2f0(a, b, z) :func:`hyp2f1` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp2f1(a, b, c, z) :func:`hyp2f2` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp2f2(a1, a2, b1, b2, z) :func:`hyp2f3` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp2f3(a1, a2, b1, b2, b3, z) :func:`hyp3f2` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyp3f2(a1, a2, a3, b1, b2, z) Generalized hypergeometric functions .................................... :func:`hyper` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyper(a_s, b_s, z) :func:`hypercomb` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.hypercomb Meijer G-function ................................... :func:`meijerg` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.meijerg(a_s,b_s,z,r=1,**kwargs) Bilateral hypergeometric series ............................... :func:`bihyper` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bihyper(a_s,b_s,z,**kwargs) Hypergeometric functions of two variables ............................................... :func:`hyper2d` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.hyper2d(a,b,x,y,**kwargs) :func:`appellf1` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.appellf1(a,b1,b2,c,x,y,**kwargs) :func:`appellf2` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.appellf2(a,b1,b2,c1,c2,x,y,**kwargs) :func:`appellf3` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.appellf3(a1,a2,b1,b2,c,x,y,**kwargs) :func:`appellf4` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.appellf4(a,b,c1,c2,x,y,**kwargs) mpmath-1.1.0/doc/source/functions/index.txt000066400000000000000000000013721340375245600207400ustar00rootroot00000000000000Mathematical functions ====================== Mpmath implements the standard functions from Python's ``math`` and ``cmath`` modules, for both real and complex numbers and with arbitrary precision. Many other functions are also available in mpmath, including commonly-used variants of standard functions (such as the alternative trigonometric functions sec, csc, cot), but also a large number of "special functions" such as the gamma function, the Riemann zeta function, error functions, Bessel functions, etc. .. toctree:: :maxdepth: 2 constants.txt powers.txt trigonometric.txt hyperbolic.txt gamma.txt expintegrals.txt bessel.txt orthogonal.txt hypergeometric.txt elliptic.txt zeta.txt numtheory.txt qfunctions.txt mpmath-1.1.0/doc/source/functions/numtheory.txt000066400000000000000000000034031340375245600216600ustar00rootroot00000000000000Number-theoretical, combinatorial and integer functions ------------------------------------------------------- For factorial-type functions, including binomial coefficients, double factorials, etc., see the separate section :doc:`gamma`. Fibonacci numbers ................. :func:`fibonacci`/:func:`fib` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.fibonacci(n, **kwargs) Bernoulli numbers and polynomials ................................. :func:`bernoulli` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bernoulli(n) :func:`bernfrac` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bernfrac(n) :func:`bernpoly` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bernpoly(n,z) Euler numbers and polynomials ................................. :func:`eulernum` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.eulernum(n) :func:`eulerpoly` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.eulerpoly(n,z) Bell numbers and polynomials ........................................... :func:`bell` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.bell(n,x) Stirling numbers ........................................... :func:`stirling1` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.stirling1(n,k,exact=False) :func:`stirling2` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.stirling2(n,k,exact=False) Prime counting functions ........................ :func:`primepi` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.primepi(x) :func:`primepi2` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.primepi2(x) :func:`riemannr` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.riemannr(x) Cyclotomic polynomials ...................... :func:`cyclotomic` ^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.cyclotomic(n,x) Arithmetic functions ...................... :func:`mangoldt` ^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.mangoldt(n) mpmath-1.1.0/doc/source/functions/orthogonal.txt000066400000000000000000000051151340375245600220040ustar00rootroot00000000000000Orthogonal polynomials ---------------------- An orthogonal polynomial sequence is a sequence of polynomials `P_0(x), P_1(x), \ldots` of degree `0, 1, \ldots`, which are mutually orthogonal in the sense that .. math :: \int_S P_n(x) P_m(x) w(x) dx = \begin{cases} c_n \ne 0 & \text{if $m = n$} \\ 0 & \text{if $m \ne n$} \end{cases} where `S` is some domain (e.g. an interval `[a,b] \in \mathbb{R}`) and `w(x)` is a fixed *weight function*. A sequence of orthogonal polynomials is determined completely by `w`, `S`, and a normalization convention (e.g. `c_n = 1`). Applications of orthogonal polynomials include function approximation and solution of differential equations. Orthogonal polynomials are sometimes defined using the differential equations they satisfy (as functions of `x`) or the recurrence relations they satisfy with respect to the order `n`. Other ways of defining orthogonal polynomials include differentiation formulas and generating functions. The standard orthogonal polynomials can also be represented as hypergeometric series (see :doc:`hypergeometric`), more specifically using the Gauss hypergeometric function `\,_2F_1` in most cases. The following functions are generally implemented using hypergeometric functions since this is computationally efficient and easily generalizes. For more information, see the `Wikipedia article on orthogonal polynomials `_. Legendre functions ....................................... :func:`legendre` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.legendre(n, x) :func:`legenp` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.legenp(n, m, z, type=2) :func:`legenq` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.legenq(n, m, z, type=2) Chebyshev polynomials ..................... :func:`chebyt` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.chebyt(n, x) :func:`chebyu` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.chebyu(n, x) Jacobi polynomials .................. :func:`jacobi` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.jacobi(n, a, b, z) Gegenbauer polynomials ..................................... :func:`gegenbauer` ^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.gegenbauer(n, a, z) Hermite polynomials ..................................... :func:`hermite` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.hermite(n, z) Laguerre polynomials ....................................... :func:`laguerre` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.laguerre(n, a, z) Spherical harmonics ..................................... :func:`spherharm` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.spherharm(l, m, theta, phi) mpmath-1.1.0/doc/source/functions/powers.txt000066400000000000000000000026601340375245600211510ustar00rootroot00000000000000Powers and logarithms --------------------- Nth roots ......... :func:`sqrt` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.sqrt(x, **kwargs) :func:`hypot` ^^^^^^^^^^^^^ .. autofunction:: mpmath.hypot(x, y) :func:`cbrt` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.cbrt(x, **kwargs) :func:`root` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.root(z, n, k=0) :func:`unitroots` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.unitroots(n, primitive=False) Exponentiation .............. :func:`exp` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.exp(x, **kwargs) :func:`power` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.power(x, y) :func:`expj` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.expj(x, **kwargs) :func:`expjpi` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.expjpi(x, **kwargs) :func:`expm1` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.expm1(x) :func:`powm1` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.powm1(x, y) Logarithms .......... :func:`log` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.log(x, b=None) :func:`ln` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.ln(x, **kwargs) :func:`log10` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.log10(x) :func:`log1p` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.log1p(x) Lambert W function ................................................... :func:`lambertw` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.lambertw(z, k=0) Arithmetic-geometric mean ....................................... :func:`agm` ^^^^^^^^^^^^^^ .. autofunction:: mpmath.agm(a, b=1) mpmath-1.1.0/doc/source/functions/qfunctions.txt000066400000000000000000000011531340375245600220170ustar00rootroot00000000000000q-functions ------------------------------------------- q-Pochhammer symbol .................................................. :func:`qp` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.qp(a, q=None, n=None, **kwargs) q-gamma and factorial .................................................. :func:`qgamma` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.qgamma(z, q, **kwargs) :func:`qfac` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.qfac(z, q, **kwargs) Hypergeometric q-series .................................................. :func:`qhyper` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.qhyper(a_s, b_s, q, z, **kwargs) mpmath-1.1.0/doc/source/functions/trigonometric.txt000066400000000000000000000050571340375245600225220ustar00rootroot00000000000000Trigonometric functions ----------------------- Except where otherwise noted, the trigonometric functions take a radian angle as input and the inverse trigonometric functions return radian angles. The ordinary trigonometric functions are single-valued functions defined everywhere in the complex plane (except at the poles of tan, sec, csc, and cot). They are defined generally via the exponential function, e.g. .. math :: \cos(x) = \frac{e^{ix} + e^{-ix}}{2}. The inverse trigonometric functions are multivalued, thus requiring branch cuts, and are generally real-valued only on a part of the real line. Definitions and branch cuts are given in the documentation of each function. The branch cut conventions used by mpmath are essentially the same as those found in most standard mathematical software, such as Mathematica and Python's own ``cmath`` libary (as of Python 2.6; earlier Python versions implement some functions erroneously). Degree-radian conversion ........................................................... :func:`degrees` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.degrees(x) :func:`radians` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.radians(x) Trigonometric functions ....................... :func:`cos` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.cos(x, **kwargs) :func:`sin` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sin(x, **kwargs) :func:`tan` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.tan(x, **kwargs) :func:`sec` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sec(x) :func:`csc` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.csc(x) :func:`cot` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.cot(x) Trigonometric functions with modified argument ........................................................ :func:`cospi` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.cospi(x, **kwargs) :func:`sinpi` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sinpi(x, **kwargs) Inverse trigonometric functions ................................................ :func:`acos` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.acos(x, **kwargs) :func:`asin` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.asin(x, **kwargs) :func:`atan` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.atan(x, **kwargs) :func:`atan2` ^^^^^^^^^^^^^ .. autofunction:: mpmath.atan2(y, x) :func:`asec` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.asec(x) :func:`acsc` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.acsc(x) :func:`acot` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.acot(x) Sinc function ............. :func:`sinc` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sinc(x) :func:`sincpi` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sincpi(x) mpmath-1.1.0/doc/source/functions/zeta.txt000066400000000000000000000040051340375245600205700ustar00rootroot00000000000000Zeta functions, L-series and polylogarithms ------------------------------------------- This section includes the Riemann zeta functions and associated functions pertaining to analytic number theory. Riemann and Hurwitz zeta functions .................................................. :func:`zeta` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.zeta(s,a=1,derivative=0) Dirichlet L-series .................................................. :func:`altzeta` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.altzeta(s) :func:`dirichlet` ^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.dirichlet(s,chi,derivative=0) Stieltjes constants ................... :func:`stieltjes` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.stieltjes(n,a=1) Zeta function zeros ...................................... These functions are used for the study of the Riemann zeta function in the critical strip. :func:`zetazero` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.zetazero(n, verbose=False) :func:`nzeros` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nzeros(t) :func:`siegelz` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.siegelz(t) :func:`siegeltheta` ^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.siegeltheta(t) :func:`grampoint` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.grampoint(n) :func:`backlunds` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.backlunds(t) Lerch transcendent ................................ :func:`lerchphi` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.lerchphi(z,s,a) Polylogarithms and Clausen functions ....................................... :func:`polylog` ^^^^^^^^^^^^^^^ .. autofunction:: mpmath.polylog(s,z) :func:`clsin` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.clsin(s, z) :func:`clcos` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.clcos(s, z) :func:`polyexp` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.polyexp(s,z) Zeta function variants .......................... :func:`primezeta` ^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.primezeta(s) :func:`secondzeta` ^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.secondzeta(s, a=0.015, **kwargs) mpmath-1.1.0/doc/source/general.txt000066400000000000000000000104511340375245600172340ustar00rootroot00000000000000Utility functions =============================================== This page lists functions that perform basic operations on numbers or aid general programming. Conversion and printing ----------------------- :func:`mpmathify` / :func:`convert` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.mpmathify(x, strings=True) :func:`nstr` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nstr(x, n=6, **kwargs) :func:`nprint` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nprint(x, n=6, **kwargs) Arithmetic operations --------------------- See also :func:`mpmath.sqrt`, :func:`mpmath.exp` etc., listed in :doc:`functions/powers` :func:`fadd` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fadd :func:`fsub` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fsub :func:`fneg` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fneg :func:`fmul` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fmul :func:`fdiv` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fdiv :func:`fmod` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fmod(x, y) :func:`fsum` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fsum(terms, absolute=False, squared=False) :func:`fprod` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fprod(factors) :func:`fdot` ^^^^^^^^^^^^^ .. autofunction:: mpmath.fdot(A, B=None, conjugate=False) Complex components ------------------ :func:`fabs` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.fabs(x) :func:`sign` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.sign(x) :func:`re` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.re(x) :func:`im` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.im(x) :func:`arg` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.arg(x) :func:`conj` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.conj(x) :func:`polar` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.polar(x) :func:`rect` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.rect(x) Integer and fractional parts ----------------------------- :func:`floor` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.floor(x) :func:`ceil` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ceil(x) :func:`nint` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nint(x) :func:`frac` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.frac(x) Tolerances and approximate comparisons -------------------------------------- :func:`chop` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.chop(x, tol=None) :func:`almosteq` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.almosteq(s, t, rel_eps=None, abs_eps=None) Properties of numbers ------------------------------------- :func:`isinf` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.isinf(x) :func:`isnan` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.isnan(x) :func:`isnormal` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.isnormal(x) :func:`isfinite` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.isfinite(x) :func:`isint` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.isint(x, gaussian=False) :func:`ldexp` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.ldexp(x, n) :func:`frexp` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.frexp(x, n) :func:`mag` ^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.mag(x) :func:`nint_distance` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.nint_distance(x) .. :func:`absmin` .. ^^^^^^^^^^^^^^^^^^^^ .. .. autofunction:: mpmath.absmin(x) .. .. autofunction:: mpmath.absmax(x) Number generation ----------------- :func:`fraction` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.fraction(p,q) :func:`rand` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.rand() :func:`arange` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.arange(*args) :func:`linspace` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.linspace(*args, **kwargs) Precision management -------------------- :func:`autoprec` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.autoprec :func:`workprec` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.workprec :func:`workdps` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.workdps :func:`extraprec` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.extraprec :func:`extradps` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.extradps Performance and debugging ------------------------------------ :func:`memoize` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.memoize :func:`maxcalls` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.maxcalls :func:`monitor` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.monitor :func:`timing` ^^^^^^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.timing mpmath-1.1.0/doc/source/identification.txt000066400000000000000000000033301340375245600206060ustar00rootroot00000000000000Number identification ===================== Most function in mpmath are concerned with producing approximations from exact mathematical formulas. It is also useful to consider the inverse problem: given only a decimal approximation for a number, such as 0.7320508075688772935274463, is it possible to find an exact formula? Subject to certain restrictions, such "reverse engineering" is indeed possible thanks to the existence of *integer relation algorithms*. Mpmath implements the PSLQ algorithm (developed by H. Ferguson), which is one such algorithm. Automated number recognition based on PSLQ is not a silver bullet. Any occurring transcendental constants (`\pi`, `e`, etc) must be guessed by the user, and the relation between those constants in the formula must be linear (such as `x = 3 \pi + 4 e`). More complex formulas can be found by combining PSLQ with functional transformations; however, this is only feasible to a limited extent since the computation time grows exponentially with the number of operations that need to be combined. The number identification facilities in mpmath are inspired by the `Inverse Symbolic Calculator `_ (ISC). The ISC is more powerful than mpmath, as it uses a lookup table of millions of precomputed constants (thereby mitigating the problem with exponential complexity). Constant recognition ----------------------------------- :func:`identify` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.identify Algebraic identification --------------------------------------- :func:`findpoly` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.findpoly Integer relations (PSLQ) ---------------------------- :func:`pslq` ^^^^^^^^^^^^^^^^ .. autofunction:: mpmath.pslq mpmath-1.1.0/doc/source/index.txt000066400000000000000000000026071340375245600167320ustar00rootroot00000000000000.. mpmath documentation master file, created by sphinx-quickstart on Fri Mar 28 13:50:14 2008. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to mpmath's documentation! ================================== Mpmath is a Python library for arbitrary-precision floating-point arithmetic. For general information about mpmath, see the project website http://mpmath.org/ These documentation pages include general information as well as docstring listing with extensive use of examples that can be run in the interactive Python interpreter. For quick access to the docstrings of individual functions, use the `index listing `_, or type ``help(mpmath.function_name)`` in the Python interactive prompt. Introduction ------------ .. toctree :: :maxdepth: 2 setup.txt basics.txt Basic features ---------------- .. toctree :: :maxdepth: 2 contexts.txt general.txt plotting.txt Advanced mathematics -------------------- On top of its support for arbitrary-precision arithmetic, mpmath provides extensive support for transcendental functions, evaluation of sums, integrals, limits, roots, and so on. .. toctree :: :maxdepth: 2 functions/index.txt calculus/index.txt matrices.txt identification.txt End matter ---------- .. toctree :: :maxdepth: 2 technical.txt references.txt mpmath-1.1.0/doc/source/matrices.txt000066400000000000000000000335401340375245600174320ustar00rootroot00000000000000Matrices ======== Creating matrices ----------------- Basic methods ............. Matrices in mpmath are implemented using dictionaries. Only non-zero values are stored, so it is cheap to represent sparse matrices. The most basic way to create one is to use the ``matrix`` class directly. You can create an empty matrix specifying the dimensions:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> matrix(2) matrix( [['0.0', '0.0'], ['0.0', '0.0']]) >>> matrix(2, 3) matrix( [['0.0', '0.0', '0.0'], ['0.0', '0.0', '0.0']]) Calling ``matrix`` with one dimension will create a square matrix. To access the dimensions of a matrix, use the ``rows`` or ``cols`` keyword:: >>> A = matrix(3, 2) >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0'], ['0.0', '0.0']]) >>> A.rows 3 >>> A.cols 2 You can also change the dimension of an existing matrix. This will set the new elements to 0. If the new dimension is smaller than before, the concerning elements are discarded:: >>> A.rows = 2 >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0']]) Internally ``convert`` is applied every time an element is set. This is done using the syntax A[row,column], counting from 0:: >>> A = matrix(2) >>> A[1,1] = 1 + 1j >>> print(A) [0.0 0.0] [0.0 (1.0 + 1.0j)] A more comfortable way to create a matrix lets you use nested lists:: >>> matrix([[1, 2], [3, 4]]) matrix( [['1.0', '2.0'], ['3.0', '4.0']]) Advanced methods ................ Convenient functions are available for creating various standard matrices:: >>> zeros(2) matrix( [['0.0', '0.0'], ['0.0', '0.0']]) >>> ones(2) matrix( [['1.0', '1.0'], ['1.0', '1.0']]) >>> diag([1, 2, 3]) # diagonal matrix matrix( [['1.0', '0.0', '0.0'], ['0.0', '2.0', '0.0'], ['0.0', '0.0', '3.0']]) >>> eye(2) # identity matrix matrix( [['1.0', '0.0'], ['0.0', '1.0']]) You can even create random matrices:: >>> randmatrix(2) # doctest:+SKIP matrix( [['0.53491598236191806', '0.57195669543302752'], ['0.85589992269513615', '0.82444367501382143']]) Vectors ....... Vectors may also be represented by the ``matrix`` class (with rows = 1 or cols = 1). For vectors there are some things which make life easier. A column vector can be created using a flat list, a row vectors using an almost flat nested list:: >>> matrix([1, 2, 3]) matrix( [['1.0'], ['2.0'], ['3.0']]) >>> matrix([[1, 2, 3]]) matrix( [['1.0', '2.0', '3.0']]) Optionally vectors can be accessed like lists, using only a single index:: >>> x = matrix([1, 2, 3]) >>> x[1] mpf('2.0') >>> x[1,0] mpf('2.0') Other ..... Like you probably expected, matrices can be printed:: >>> print(randmatrix(3)) # doctest:+SKIP [ 0.782963853573023 0.802057689719883 0.427895717335467] [0.0541876859348597 0.708243266653103 0.615134039977379] [ 0.856151514955773 0.544759264818486 0.686210904770947] Use ``nstr`` or ``nprint`` to specify the number of digits to print:: >>> nprint(randmatrix(5), 3) # doctest:+SKIP [2.07e-1 1.66e-1 5.06e-1 1.89e-1 8.29e-1] [6.62e-1 6.55e-1 4.47e-1 4.82e-1 2.06e-2] [4.33e-1 7.75e-1 6.93e-2 2.86e-1 5.71e-1] [1.01e-1 2.53e-1 6.13e-1 3.32e-1 2.59e-1] [1.56e-1 7.27e-2 6.05e-1 6.67e-2 2.79e-1] As matrices are mutable, you will need to copy them sometimes:: >>> A = matrix(2) >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0']]) >>> B = A.copy() >>> B[0,0] = 1 >>> B matrix( [['1.0', '0.0'], ['0.0', '0.0']]) >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0']]) Finally, it is possible to convert a matrix to a nested list. This is very useful, as most Python libraries involving matrices or arrays (namely NumPy or SymPy) support this format:: >>> B.tolist() [[mpf('1.0'), mpf('0.0')], [mpf('0.0'), mpf('0.0')]] Matrix operations ----------------- You can add and subtract matrices of compatible dimensions:: >>> A = matrix([[1, 2], [3, 4]]) >>> B = matrix([[-2, 4], [5, 9]]) >>> A + B matrix( [['-1.0', '6.0'], ['8.0', '13.0']]) >>> A - B matrix( [['3.0', '-2.0'], ['-2.0', '-5.0']]) >>> A + ones(3) # doctest:+ELLIPSIS Traceback (most recent call last): File "", line 1, in File "...", line 238, in __add__ raise ValueError('incompatible dimensions for addition') ValueError: incompatible dimensions for addition It is possible to multiply or add matrices and scalars. In the latter case the operation will be done element-wise:: >>> A * 2 matrix( [['2.0', '4.0'], ['6.0', '8.0']]) >>> A / 4 matrix( [['0.25', '0.5'], ['0.75', '1.0']]) >>> A - 1 matrix( [['0.0', '1.0'], ['2.0', '3.0']]) Of course you can perform matrix multiplication, if the dimensions are compatible:: >>> A * B matrix( [['8.0', '22.0'], ['14.0', '48.0']]) >>> matrix([[1, 2, 3]]) * matrix([[-6], [7], [-2]]) matrix( [['2.0']]) You can raise powers of square matrices:: >>> A**2 matrix( [['7.0', '10.0'], ['15.0', '22.0']]) Negative powers will calculate the inverse:: >>> A**-1 matrix( [['-2.0', '1.0'], ['1.5', '-0.5']]) >>> nprint(A * A**-1, 3) [ 1.0 1.08e-19] [-2.17e-19 1.0] Matrix transposition is straightforward:: >>> A = ones(2, 3) >>> A matrix( [['1.0', '1.0', '1.0'], ['1.0', '1.0', '1.0']]) >>> A.T matrix( [['1.0', '1.0'], ['1.0', '1.0'], ['1.0', '1.0']]) Norms ..... Sometimes you need to know how "large" a matrix or vector is. Due to their multidimensional nature it's not possible to compare them, but there are several functions to map a matrix or a vector to a positive real number, the so called norms. .. autofunction :: mpmath.norm .. autofunction :: mpmath.mnorm Linear algebra -------------- Decompositions .............. .. autofunction :: mpmath.cholesky Linear equations ................ Basic linear algebra is implemented; you can for example solve the linear equation system:: x + 2*y = -10 3*x + 4*y = 10 using ``lu_solve``:: >>> A = matrix([[1, 2], [3, 4]]) >>> b = matrix([-10, 10]) >>> x = lu_solve(A, b) >>> x matrix( [['30.0'], ['-20.0']]) If you don't trust the result, use ``residual`` to calculate the residual ||A*x-b||:: >>> residual(A, x, b) matrix( [['3.46944695195361e-18'], ['3.46944695195361e-18']]) >>> str(eps) '2.22044604925031e-16' As you can see, the solution is quite accurate. The error is caused by the inaccuracy of the internal floating point arithmetic. Though, it's even smaller than the current machine epsilon, which basically means you can trust the result. If you need more speed, use NumPy, or use ``fp`` instead ``mp`` matrices and methods:: >>> A = fp.matrix([[1, 2], [3, 4]]) >>> b = fp.matrix([-10, 10]) >>> fp.lu_solve(A, b) # doctest:+SKIP matrix( [['30.0'], ['-20.0']]) ``lu_solve`` accepts overdetermined systems. It is usually not possible to solve such systems, so the residual is minimized instead. Internally this is done using Cholesky decomposition to compute a least squares approximation. This means that that ``lu_solve`` will square the errors. If you can't afford this, use ``qr_solve`` instead. It is twice as slow but more accurate, and it calculates the residual automatically. Matrix factorization .................... The function ``lu`` computes an explicit LU factorization of a matrix:: >>> P, L, U = lu(matrix([[0,2,3],[4,5,6],[7,8,9]])) >>> print(P) [0.0 0.0 1.0] [1.0 0.0 0.0] [0.0 1.0 0.0] >>> print(L) [ 1.0 0.0 0.0] [ 0.0 1.0 0.0] [0.571428571428571 0.214285714285714 1.0] >>> print(U) [7.0 8.0 9.0] [0.0 2.0 3.0] [0.0 0.0 0.214285714285714] >>> print(P.T*L*U) [0.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0] The function ``qr`` computes a QR factorization of a matrix:: >>> A = matrix([[1, 2], [3, 4], [1, 1]]) >>> Q, R = qr(A) >>> print(Q) [-0.301511344577764 0.861640436855329 0.408248290463863] [-0.904534033733291 -0.123091490979333 -0.408248290463863] [-0.301511344577764 -0.492365963917331 0.816496580927726] >>> print(R) [-3.3166247903554 -4.52267016866645] [ 0.0 0.738548945875996] [ 0.0 0.0] >>> print(Q * R) [1.0 2.0] [3.0 4.0] [1.0 1.0] >>> print(chop(Q.T * Q)) [1.0 0.0 0.0] [0.0 1.0 0.0] [0.0 0.0 1.0] The singular value decomposition ................................ The routines ``svd_r`` and ``svd_c`` compute the singular value decomposition of a real or complex matrix A. ``svd`` is an unified interface calling either ``svd_r`` or ``svd_c`` depending on whether *A* is real or complex. Given *A*, two orthogonal (*A* real) or unitary (*A* complex) matrices *U* and *V* are calculated such that .. math :: A = U S V, \quad U' U = 1, \quad V V' = 1 where *S* is a suitable shaped matrix whose off-diagonal elements are zero. Here ' denotes the hermitian transpose (i.e. transposition and complex conjugation). The diagonal elements of *S* are the singular values of *A*, i.e. the square roots of the eigenvalues of `A' A` or `A A'`. Examples:: >>> from mpmath import mp >>> A = mp.matrix([[2, -2, -1], [3, 4, -2], [-2, -2, 0]]) >>> S = mp.svd_r(A, compute_uv = False) >>> print(S) [6.0] [3.0] [1.0] >>> U, S, V = mp.svd_r(A) >>> print(mp.chop(A - U * mp.diag(S) * V)) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] The Schur decomposition ....................... This routine computes the Schur decomposition of a square matrix *A*. Given *A*, a unitary matrix *Q* is determined such that .. math :: Q' A Q = R, \quad Q' Q = Q Q' = 1 where *R* is an upper right triangular matrix. Here ' denotes the hermitian transpose (i.e. transposition and conjugation). Examples:: >>> from mpmath import mp >>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]]) >>> Q, R = mp.schur(A) >>> mp.nprint(R, 3) # doctest:+SKIP [2.0 0.417 -2.53] [0.0 4.0 -4.74] [0.0 0.0 9.0] >>> print(mp.chop(A - Q * R * Q.transpose_conj())) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] The eigenvalue problem ...................... The routine ``eig`` solves the (ordinary) eigenvalue problem for a real or complex square matrix *A*. Given *A*, a vector *E* and matrices *ER* and *EL* are calculated such that .. code :: A ER[:,i] = E[i] ER[:,i] EL[i,:] A = EL[i,:] E[i] *E* contains the eigenvalues of *A*. The columns of *ER* contain the right eigenvectors of *A* whereas the rows of *EL* contain the left eigenvectors. Examples:: >>> from mpmath import mp >>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]]) >>> E, ER = mp.eig(A) >>> print(mp.chop(A * ER[:,0] - E[0] * ER[:,0])) [0.0] [0.0] [0.0] >>> E, EL, ER = mp.eig(A,left = True, right = True) >>> E, EL, ER = mp.eig_sort(E, EL, ER) >>> mp.nprint(E) [2.0, 4.0, 9.0] >>> print(mp.chop(A * ER[:,0] - E[0] * ER[:,0])) [0.0] [0.0] [0.0] >>> print(mp.chop( EL[0,:] * A - EL[0,:] * E[0])) [0.0 0.0 0.0] The symmetric eigenvalue problem ................................ The routines ``eigsy`` and ``eighe`` solve the (ordinary) eigenvalue problem for a real symmetric or complex hermitian square matrix *A*. ``eigh`` is an unified interface for this two functions calling either ``eigsy`` or ``eighe`` depending on whether *A* is real or complex. Given *A*, an orthogonal (*A* real) or unitary matrix *Q* (*A* complex) is calculated which diagonalizes A: .. math :: Q' A Q = \operatorname{diag}(E), \quad Q Q' = Q' Q = 1 Here diag(*E*) a is diagonal matrix whose diagonal is *E*. ' denotes the hermitian transpose (i.e. ordinary transposition and complex conjugation). The columns of *Q* are the eigenvectors of *A* and *E* contains the eigenvalues: .. code :: A Q[:,i] = E[i] Q[:,i] Examples:: >>> from mpmath import mp >>> A = mp.matrix([[3, 2], [2, 0]]) >>> E = mp.eigsy(A, eigvals_only = True) >>> print(E) [-1.0] [ 4.0] >>> A = mp.matrix([[1, 2], [2, 3]]) >>> E, Q = mp.eigsy(A) # alternative: E, Q = mp.eigh(A) >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0])) [0.0] [0.0] >>> A = mp.matrix([[1, 2 + 5j], [2 - 5j, 3]]) >>> E, Q = mp.eighe(A) # alternative: E, Q = mp.eigh(A) >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0])) [0.0] [0.0] Interval and double-precision matrices -------------------------------------- The ``iv.matrix`` and ``fp.matrix`` classes convert inputs to intervals and Python floating-point numbers respectively. Interval matrices can be used to perform linear algebra operations with rigorous error tracking:: >>> a = iv.matrix([['0.1','0.3','1.0'], ... ['7.1','5.5','4.8'], ... ['3.2','4.4','5.6']]) >>> >>> b = iv.matrix(['4','0.6','0.5']) >>> c = iv.lu_solve(a, b) >>> print(c) [ [5.2582327113062393041, 5.2582327113062749951]] [[-13.155049396267856583, -13.155049396267821167]] [ [7.4206915477497212555, 7.4206915477497310922]] >>> print(a*c) [ [3.9999999999999866773, 4.0000000000000133227]] [[0.59999999999972430942, 0.60000000000027142733]] [[0.49999999999982236432, 0.50000000000018474111]] Matrix functions ---------------- .. autofunction :: mpmath.expm .. autofunction :: mpmath.cosm .. autofunction :: mpmath.sinm .. autofunction :: mpmath.sqrtm .. autofunction :: mpmath.logm .. autofunction :: mpmath.powm mpmath-1.1.0/doc/source/plot.png000066400000000000000000000502061340375245600165440ustar00rootroot00000000000000PNG  IHDRh7( PMIDATx^A@ aV3[m$I:Fu(mN .$t[;‘cK3ѓYɿ|G8@@@``@@@`}``@@MtwaRJ1pq˲4Mq\/1sZk^.亮Gp?b۶۶}~g6 @} ȷh/^χꦻDLƻmf1>b,ϲlTUR(B4MRk-RJBycZӶ6yw3P3xH=9 L1qe)8#U8}^ɽG8G~\+KN'u幉%.0 {x׉s=zRk1k㺟wQU? $"EH轈 EiR{*~"`EX~N$@P@EԐ~.8+ˌ)3ޛ[+KĘ9}rwxO?e.YHa5y4ә6}D:uWRg;Ld3 N-R͚1K2ϚG̣G3h*RbS0'%a[ŋqXvڕ۷o5k:M81@F1sOC_|񢧺 3rG2kZr~i>cn H߷m8xۀzK(!!!);/4nSOqժUN:C،Ȧlݺ5F1'σ L7>>uBy? s<"w0ϙ#΢gR68 y(S ە]#cc3_wlYkFsnjI-.pvW}-"=,sb"ƹER ,h;v… R7jcM\B,/f.XP^Gf\5!RZƃdk>|9qqCq?g>vuk(2;뽲 owkHx~ \И12TʻRFX 5`N1TF sΜz{*/3y,ŖITk3 3`$aYn>|8ѱc0f+[*UdƮji/kkD'N D5kZO?%gv(1d+F̙dD}4)m` uTKoLAfDÆg/q}"Q p:sٲr)JZ!jwEeŋi`A{l`:z ~[.DɒF#=e!:l62PUS?&&z94|a{dPWCj׾W"_&r^}վce vo ܣ/ us 9kWDdssHIq $x"RNM>HFGgHmiRۓnɯV,~:ٕ+Wn/y ǏfD=&$Pƈ)")cE /jqF@>Md9ѼdIkuVVv3V  ; p&>y%p8v+2z4EZq3WEʗ}T}Sw }b>ga&'kҏ^N-w۷31 Һɛre20AcLj""ࡇ*T `Ct xn]!F{9DH;N}2oRL 4a45W^)w=^tӒ%=) W2ϯQfls% ~ W$ kW=gg>y,h'"MLG"? Z Ӧ],3=`j!PӤx?9 2"$&J `A_~ #ʗOۀ+W /'%I~4'[7g+IIKnF'/$sxxdqW IX4/29R;As'ҭۏ M 's=b=K4o @7St*sgм61_f"W24kт]zowhcNNf5`G/ǎJ eˈAGs'Ѻudd4wa~%Rn_V`My 2ؾ6^n_>\֫&MBG5a|ihnGIIi5 s)!!d駎/и}6 ȪEH.zYYQ1a쩴Sj-Mˑ'?/F&0q"QBۣGo94 0rIRN ˅=%EZ H7B֍{ $iN_}EU5mJ֬aC釢48wْ%)ԲXl# -ɷ3"҄ l٢l5KD6 ,h AAi΂kRfInd4I "3wW&=) ٌL ˔e:v$Ѡ%$JiKi2<(4pj,= "Wv?L?D&"Νdy3VL H&O{ 2u2G ܔCՃX\9ݣkT^wTV @@QHqRwʗ"U.41@߾Z0 ` IXK>}Fҍx1х |e4_T)ܡK`dv$a gAF!ٽ;4w*gN>e3ƹ OT<Lb`A{d`md|8.A9 2r$NTG8=!xCDھ ,hSuT LL:<I+DL3h r傂&@91vdʷt#-qo%8U]HJX3M[>M1](]m[9"yㆭQ 3,ϺuxEdLfE/0ex1fdg ڂI||z&w *wn~(}HfG޼ sg"EfC$a$c͛GtZljJTHR"GٽbrY1M$$/ߣIX7?(C{H7Bꤗ ODL5֚كqL,XL|}(+OkN$ceǚI|Q;ʕ'NpBBׯ_ws~鬷,ӶOٲ:tޱӧgח{6\̜#o_*$N_f`A[-[PjըTR={vӧE;0f6G!G@$&Iol,HsЉ8Ɔm,蔙/V0;TZ[-\xPwܙ=jnzHrNt#, *{[hQ6m(ЉcJ`.4iBTޭ5k?|Æ cA˼hӊɓ's&MvJ,ɯ:O8W^QQQ^&[n… u}əgM<|۹f,~߉AA  LDY}dzn&cm@^|Es|lgl^~=wЁo2~x~뭷yɺ5H?/6/"mQyflYkv ɓ2˥yQvH :wdٲeTbE$ %|nC# w=f"Mʖ̜I WIa\$sswk9e}טž۬xxҥ=z4ScJ  2ER6Oіw@kȥ4 k^V87ebilޣ# +=+W)10/ !&_d.P@ԩ,h{$ S*QÆr^%)I;[ n=#*_ޫ(@ԩ)sˆz..Xvf 3'N$HAݑxt&]vIUȖ.8O#>L/X`1d´ӯЭy2İ;;rt)Y2@ uJC`әCGUڻxuʁnd˦Kk`AKV_>-m֮]|\Vh^ه KsbE$`Agܙ Юsi:h c߇$%(D 9Yt|kX@=d 70֭['qͻ p{Cřزd. YDIV$#. ; lXn&M},%%H>ui0Me`[vp9(KhтX123gquˇyDu@sѓ5n}ݺR3ƹ DK~'kX<Çu`5{xLU)"*>R~~("m݊s˂$%J $aYu+Y\$Tj2 6O,`exe1\:w]`Yٓ*v݈U+0](UJ-HII^@ѣ [Z.g`O L.%-_&TmٹbCk#̖Md]%ņ"6eH#GUڅ#b.^<``-RW`M@]n׮h_{Q-ZH*VRpњ5dнi}mEvrR+V (H\͛"+}i둄e,\zӍ\/_$ jKle0=6ꏈW99{vm k/GѢiGH̗/`{6tZ `A;܂ \SY{c"3HHjG}lhSs 68۶=J wє/ʧ?&:|:5VE$nIX5]$ay^G# ODD1Ѽ94w+RHU-[@IX&ԬItrY;OSþ\4 1Qb y]~XXॗ$q|$aΆvM;H9ڒwB~R1a"mj7-CGzBڵ( G@nEʖM-بvsz|$aRU;3zЖO|̱+rʑClHJR`2)*J$w$;XsD1y !nUi;@$ 刏$Y$, eĆFyZnE \G'caCҥv ڧtmBtN/t\sZ~N- %6E foXAʡ"q. $aC''K _S:u  ˇsܒ ]Dn0^NB$IX&{&c׵$a0ժKJBOǎD9s@sfy7mJT#KH.'/# ˅`q~ysZRh֭c,#" u$V6}:֮&Of5`$a&:8Xl$ay~ΕKgE$"Qņ?IXwQb2|Y;@)ZE 2e!qqr}{F[qcR2^Ć=S6Jl"Rt*wX~aD}6oDFs`飏X(DGH| 4лCbX9r0pc?9!6tnwCE$_~$aIIbF*S˱ X$,f0*HeXL^%$a={*fOB4, پ%ΜfݻEɬZ%oo٢ঁ8g54TuDrzDв4̓K  ['װ xf2eܥM$a^=:^aʆFWߥ=2U6IXȆ>pߐʔit n'vHw%"9~H„4[b@ H'ػGYlB*aXtL@etxiF_/ k*T ][HII*D>KԒ$,V->^aUlh+aaorc%:$,>ڂ޷IX`g:Hڿhn)@Ƌ- 1VĆ6*ѽ< lh{eӑրMXϞv݇}1VTyH4\jUA %)B@Ujz9󍾴b61+}˗ݸA :6D! +lLtgIXzl!"x:.d/Ɗ;5 ,|` Zvyo߾d+n7y˖lr`>ns ԨAtEu{S7~TI[Ёl%Ӎ@hw@Kj$aY l!:qIX`6%[gIXG*D/bC+0VLj'K$aΆF$,/~[K1VLko^}@zוd˖H6ee+WΣl{H*h~s3_fnݴH 0ݐ.]D+V/K˗/# +-GIo$aE69~FO7i2V+RdtG 'ܹ35k֌̙Cǎ#G[6mj 6 +-Y:# ˳,@֢EHN{AܹņXq] gsZ۷O},IJb.YR>-['`?kGH;^ϠO-K<7nS'-R րSm^!˷˽{6qƜ2>\l٘Ϲ`N%C6:Ezy2~,a3ߊHW57Q6*5ѓO>i)޽"""hΝ$}gTD ڳg 4b%ag$ayE63nhflo۷1VLjׇCBhCct+˗IbŊtR,֭:M}~7Y`Ny/M"Eprr-DEӮ p-SHKϠgO-O|5cW"ҟK26lMm""D%K8-8XK9r$꫰nA]8ZQz܉'$JdP_bnCח#аe~FB*̞9Fbn~F֍D˖IbNKe }і-HrkCGw/9Xа,N 8zDy?f D 9ӧ>fe܍ 4%lxٰ!d,#g3M7r$NLb$a҆^lDG'=Kn$rv9s:1ɯ6cD۶! ˍ -?te;z&E˗֯wh%'5FN~]Kezqj.7 5`q4[nSU+6K`NJb3Cia4i-_995jhjyAl֭4.udD?(sp%j${cлv8@ nhȪ9wNIldt2~Fmhh.c/"XжEG>w0'&߀ 52}w64ZUT.,h[Р`A 1Ct@e#!3 c!te?f)C$6Rv.=ʔIX^xBs톆 6tǎm)œ~3h@nbC%H :,h 8ƆVǛW"nt`?wC (HDR%G'VӻY);/*R2o. i5::$D>!-Z )He"wETT,h^ʇ"۞`z sX~;C+@έD>4ٻGHǏ-H²sZ>bC:e'2(.N,?2y':"#: i5myPG9~-ʔL>bE岺uXyzDe;,hk594- g'{N |$,hZԆ#3 #fE IXN -uyfOHeJT&R2QnVhް!QҞElYߟ- gbC8fQ@ 4HʱvYx~<^)9١64,h$a 吺ܹڶE*SԮ He5ժUVKTsmh<dTZZXKl=T&No':|Lԣ)#(FVf;t<>,ԟصK.`:y5`$aƆ6[Cr"jL鴟'j Mh҄;kCÂF ݦ mպcb/&CL鴟e{[J=h.PlDݻ5D/  =gx1 `4}f5kDSaA;ڂjQ8kL%W][)t{f͈q IXnFX!~aaHeJ$,Вy3щ܅ņ^Z$X~6W_I?3ضM.' :ZDR7`A`l#RKe/`?W[hAT̜I4mhh'Z zHmD* 11g$aYp7ƍDNAs¸#0l -uϝ(E~He2e~Ӈ\@R47ݗkCB㏳SGUsr2:t",V1\\-ZpZ@*UHժX/H2eEkTAڹSfAAHer9%t>r"$,Ⱎ9ME0 %ڽVӷ/:e}ERHerLJCK@ŻED@s䆗]vMe ꮻt9 rZFHe0'%2-L/_"*2aA; ;d.]Jt2-[r;Eϲq%%}F8@Iu i5ba)oѓ)88͍HekN>$aYՂ^%aA;DE3!X1]F õHk147ΝH1߸,hg]C?@t[lNXu H ce&@FF@j!xqBBVRnH2Abd$,ˣ/Nv[I3f@sS:v$ʛW<@jj"VƧLl@#!:ge#j֨܈a.X=! k;HG;̛ؗ'/p!D)SؾY22! kIXX}덉fHrч@@͚}Pn5GkIҥ :ˤPSL L6#GߩxH²rU]*C))SY}_K*,/f֬KlرCDRKd )hX>KЮp`A4͛}tno5P6Qժr0ÂvHٹ3) 5&'OxLVΡHB;di`fH6 … ܪU+QiӆS+،`]եKX7YTl3؛|ԶmlD9={ҎfÇE^h Ç X9b6#OR\{9":As=p\-[l9:$a ܹsTpaR)RΪabcc~Tn]7o^ &aybMNK^`Y<LfHV7єr;$ܺukJYuZti:6_~,X@G}\vƎK9EGGFm۶ xOjH}C˗bcNպjI} {,I޿$tP?eb^ӥPBYxњ_?U!͘P/?[K]tm]}IA]w2Sf\BСCyʇK6)^]~kQ|s|=)"M^[3R/Y=ժ?c تoߞf2Oo˔@]Ӵn:VZ&ay:+Z)LL,IjM @skݭ$ӡy  &cH)VcH)v3?cظq#W^k֬ɕ*U'" ݠHβ%Q p4sZ!CA a>sO?-VC88Q@T ^yE~=lx]i&v>`zfݻE?XIXxc -mjUT&~V1|T[d ר!ôiD 1v8>+Ͼ}/]+"}`kְ`Ti"̀x1A|;wh*) 4HzLD/6cѾXӦ0xg-[F}͋T&b)B^[Btb"" !h;ҬX>x# ˜C3ϒ%O>T&tOl8^[nBsS Vs,X11 uV8}pf")BfM-RxàJiА0k9!kN$^V!Q}YAΜzJ2)=l@~o߮H^hͭ_wPN[֮n'`A;$a>܌%.QH"2I~iRH뫯 :.wJƂ 7ֶw0%9֣^U H;2xL?E f>qsbȖfn7nWWn9 x܌^IN4rϟoLҥUI2D M4Qݒ%34w~}ڵJJ"G  kּ~MDzeNX`Di X^ ĉG iDְG* Y^|͝Q$cE}P!&1_fΝv+_db7z4~]D>Hg^yEDڴ 3`gqy<,}EolDO=E&m FtNHLp*3lIWHmԬQz}$VEOtүdz>o|VŊH6BGkWi 4$~`GeKd ,hQx[l[ϒ_k6do`:m5-w^ v(@T|$;IQ)RyclL7&HgA:|_@ƒV|Lr@ZK&S>ls6 3`QL3F&,kײmb1~- > u;A9sd0M^;n9cM摑Dz>#m$GSf !{bswo2=zTUyhܺu#*_^4>HW&HF O$nHC?dJ|L#D$)5`fW9'2-G0?Dr uZq $īu(>λ}ɑbY8 Aղ/9cJq$^{UIv/-k2 %vuyʩt X6.c8`ؽ;˚:C8`ػ9(H4`{~,\17jv_Fx9?!Hv{\֔YpbNeY%>" uk'*gNteUyΚ" mkIa$>ի-@'˚uxŷߪ;L۷͙C=cԼ PESdODlؐ];r&}fG\~y0:8W&Z}Wp,sz5lKlY ݻKFc~[od>YRR_7=bD0$,s)Iݧ11<)I~PGg si=(}V߼y1^yEDKv4e &Nn;1eYcL!a߯G!EϞ^ķ.SF|<9#G$^=CO0l\I +UJRfeʔ˴i2z;QQQtSPt).MݶB#( b+DsvH{V9޺ʱwG4s& ;9 34ܵI;(ҥrHM2E׮Q9ylȲokA,Ck_҅Q#i0` sJTlzwII>vT~/s˱L4ɮ_91"լEʕK:?`"E,U5ݺe 28 B ^^78᭷}Y4iKݶ|NiQԩ2D{ξ/^l'`4<3fPΟ_ݒ"Y*ѳR!$C%<}+ʕS?,W;P˪Y~;i~ HtFd̵kڳeӛ9‚"C)GKlUW`=T~>}ȭ6}:3`н5:U62HկK/^@gDw( R*%.|ѦMdD-[UV-ذhx :j\2҅h TDI'c4-QkaN"Ҕ):5JR~ў=t5<\02YvԭJk?[3g| &4Il3ܹb4onm~}^DjH{V%.V-U~;vr/]bOt옡AXx1DcZOϞR믳o1BDRVePWn0a >}bXSu=0\~2<\Y7_O>aʕhj-۴yy^[ye+VKϻhnq\74$#GJs:ej_ɠbE X9%nX3>/_Ú5M[y{0T!yT~Hŋ3~1bTMzm&;['ꁷw/WV9"XH,/,K#WҎ~;^xAjؐu\KRP;;e˪~sVRK/0(oڤ8$'2iGeZ6e*j@~C֭Zx9.;ԣ"1~ѣD:]tvBt4k'u$ae)H@-Et%]-B~)];΄/]RogO(!2Ǘ@mեtÂXիˠkFxs紫+$oFRlf̗/ۣݾ *U|+66&M<@*U/ 0=YƬY\-l]B[ [vel)Eׯ/"y?`VMD]"عnhөo{ {?g2xÂ65 T{6nf9u*3:wKd^-˓GD s6| 2ϙr@N׆ aA8PcP)5 f"IO|}42IFr$qIʕk’B%Yg;r^}=t ̛7VM+zEywٌ2e(T?d`VnIÆEq Jau:_DRϗezE8Qk?22kuGDHFΟG̬gf._^~^X71haɐPjQMB ѭ\$ұbf(%,! oЩS Bo+_wy!RWo!x}rhDt! !h OrvƳ`_wvX,ak&C%[ 0 d0po,U!e؃00KwCٳDhm͘iiyulyuUiZXqg$|\^Oݗݑj j4aqŴe]c=-JLlulIlnO{'Ig灏?h'aa|wg~sVWEn:&x9a6fSj>2Q'T .dnwo<C5(J,eWW,-m*h89(l۞-I*۬&qqMciU'EN؃00H *#l&4q`}TX IH?쒡 !E%'fJ@"q4-  =}7^^pΡu!{T/{R fjcM)kNCDҦ7ob\kў{stc`Zɼ?MHmU]H4 * ,)#ɯ 䊂#' MAf 6tǴAA+T-+Z-܇`.8=s!Ih$ܫQӯoAq&ӡ"# cКhXҤ\hJ[XX,kMԵQѴG{zzdwwW<谿^(ӵDo#p(---ݓCuvx@u -^UUEƖ<`_K܇ښ,|k(F7ntO#px,//Z`[il}}]v۽:.DD{Ɲ쑾[0fnnN.x[2q\\\z#%%% gggaKS#MCL$P]]p+xہtlnuu5:]ӸAK{8h%xeAKCtA%H` 7c`C855e666;ax~S5c~c-i<- l~~>h@͵҄jCSvHzz7)^LOOKAA5~(R ^OAH,#sERD_P$uww[Sm'Tijj쌻&,e+I;r֒(5lAAkz [5kF8??7cY7]'LO\SSccH:bbW'''AFF&$\9ECCu% }ONN+++6Θ|^]eEy tA ؊0 M &\^^(hGq 9`)uNo:-@ n`g1 hmm X,D"FC @OȺ=l.--} P  0`@ 0hJNPIENDB`mpmath-1.1.0/doc/source/plots/000077500000000000000000000000001340375245600162165ustar00rootroot00000000000000mpmath-1.1.0/doc/source/plots/ai.png000066400000000000000000000637441340375245600173330ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx}wx4H(!t "("׫\++lA" x 5RHۦd6[fwgfgfgy<̞L6g9~^0 4hP|@D4hРA%M@ 4pCh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)4֠ABh 4hP)|xp$''FF֭ڵիWH [-{hӦ :-oӡС0Eii)6m "<<\}eee`FuO[\k%|_MM Twǫ /33Z}zTTT =n0 sq*++zefϞ,_ٱcc43g2>,3k, g ȉaKtNӦM\R#@,[+W?FN:yiA,TA; ZP__n 6P#'@4NqR:aNn"B0]÷mAOo4Lt]h(丛 u &Ovt7 )pB4NqR)Еͱc%bjd<l ++8F^'~8) 萈&=ݽDXlڄyؽ݌ 58IYx@2 }OKv_}*9z)pB4NqR)-[7jM> qE~ 58IYx@5iBߨc^;0` /8uʽD4NqR)Е@&A;xy!+(~ڪZ58IYx@m;?=ˁl > =JɻwmZx5@yiA,@Ϟ4FPSƉ4N#?O.]&M8X^>np̞ 7qHTL- pAyNf;G;v~=^^nƉ4N#8pjj˗֭`ˠ}øه O5k'6K[f@18IYx@CA{HF#Ͱ *3<9{wE[p/7C'e]WWҴBvNh{¤,=Jہu@_'O^nƉ4N#9,0 *??/ OX0r?;yIAƉ4N#:$$ 3i6- |'3<'CVhA,cl4ZAƉI*x@Biaqp11ulB N|GЬ@_")(r^ÆkҪ멩si@j$/p@[pzKr|['@+ {Qi\I+$'~P#'m FH9#hΠmT]M6P$XH|9]t|,"C$'~P#'m B#-L8 7 SNmlG#hCSWÔl\ʠIj$kGxh RsʠIj$eee uwrѢ l'&j 4N#3$Tڃn謬,0B@M,d u 6'5_'em Fv¶ g2в:@!ЄoTC18) Bk1*%ʤ=NazZZPGr*)w18) p+qDDsI/^\ NRa!cP(KsMR64a `0=&O<u5u5oTcqR)u)C@hC ŎYȐ S07N= `f`*O{zIbo~i[`0`ʔ)={6,X`ڟnݺ駟ҥKm ]#,!ՆBg`/j0:.@ر)v -7ѣ}:E O8 'eV޸q#Əe˖tu:BBBPQQv(3XrŴh!ڥRCP,́nshI,ӧ))a4~1k-``N*IYUѺA8bccqa%X:t}/_n3b f=nC!NgS!!@@,#hCI?[p6\Z+Z,<8y:p$ԣGM~N*IYU۴ĭaEffIYxyy!$$7† uVlٲG*Ch)I:#cj{:{/-4#:iiHjh;s&5~pZJ,^ t ,\K9Ih!\T( 7HfqW) :\URP[ \n )@𤋮ɒD9t j I*x@sӠysExj.w}C 4 __Z{x,z$"]}EΟy^ bciӧ,** >]9WȩTpkQpe!8xyYYEUE(*Db[y_5u5vMM0 i[{>-Hʬzsevb($,R%B{K%΃&U끓'ELN~!c@k/*?Ov-$ԑXYN[Ǜ= *&~~ƍ Ӈu%{JKVԂT! &.)S?q:t:[6eG %x&[K//ы ya4T(¸Iĉ4 ;xֶ{9xqz.ׯJm&y=`iC4".y]+^Xz=q{wG*wK *JP^SBRF<'rrp͚4C\hp6 M'FpS)ӧ$KrV)7K0e ~< ݊ B¼<`wJ8?}xyN/} $C~!52z 鷩QMKwlkNG$ԑX VhIMeVILLDϞm_5~M_X}n$e$X13 FABD:w6m;GtF|X<질TFx@svbN%X&̞M#Ӄ%?!a`` ck yM*L{ѣq9!$ ه#58qtIT t^ v-[ήk `?' ȑtQ?`ӷR;cz%X OFvYiˠn$F>}нuwE$y?YamΜIoÇI] CZHf͢_K }Ocm'OtNBwB65qg~1 p2tOga>xv@uWGP[_Mg7Dxmdecth|q87r_ź0,VJm&`p>; w_/ OΜ4d,AҙMA$0J$l)A;~r:v9$,.H$.\H@}=0n\G>u5 n*\s#?=/mɛ'c] a qeoDvq֞9Ihp.С.Ȳ'In(A-ș !6:(  $AC^L55`SM.Uz<\%W'N{"",=Ȑu:tt,Y@~ϕ=賢ml4ۧlGL5-ąOz8kOG uHjCiDA-ZНi^ih12#UWNSR6zԨ@n FVa0G&"86u>n"Z5}f4N^;ÿ➎ۋ1'5@G yHC}]>ᶓU&Oo%%?۹7q&!0$@7naϖwE[g.3$2`'r;:=(g~UzWćcӤM842'wCG yH~ux /X[K,;!TчG\!ysfUҭ>*čO6sX4.: /@. FٟWF`:}%I/^{7 w6<}t}[v;FNR#<$dGkC zo'!Tܷo֚ӑKղaХC w۶5H-Qty3 }xy%;<94~ɜͰu 6o&i\< Y50\ u$T[G'^`<`ʽ00%xݟK'95r )ЅxvfpխV!"$d-!q @h(la9s6)ЀӥPGBfuHrY^4R㗹q萔sRj$۞cf0;p :}DMDpRj$tH  9 8AԻahQ`͋d4mJ> i%"] u$hח>q7TI uÒ |8-k~<#bCbӃ?^n"; JrRj$bʟDS6oDTrx{SCUH$'OEqهt:,`ոUOB>駁9sȩTHϧe^>YOhYgg  Fh'٠";BfBvTl!3ǡo_'.,ТCIfښ0xz(*3v#xk |j I*x@WTЭǃNBn(NZA]{AAZt#@Ի78H}NϬϩ?#.4~Wgb"YݺX i@N t!)OC|tBvQj@y|T!P'A˾BC ڌ޼IhC?W sN5yoƩamc!%5r )@8wͣĎK'm#-sN{ڂAGDOA7mJk!0P 8qr!C(s8 lFsQyx#F:89EhaTѣ0Nj I*x@סG;9hַmqPPvlB>HDt+^ j I*x@WA7kF}/_K8Nzޫ 樮逑&NΐBNGπ*-*ԑ Թsg* p5XN}0W,^} ܹA95r *!h9xMiq$$$87^ RB3y-"b%ТB x[ˉŸ"۶?pYJYW$=9?&~%>i7ȩTpY322j*,]%Y9 ѡ4/Z@H贂w tT3Mh=Y'*ԑ@6=s4ˁo*pBY45h> Q?30@X؜Ν HHH^ǴipV&mLZyzЉ+8#h:wNjV#h> Q? Hp'Q4IPT#@,fHwwҰRlaodH\ZN+2HNNĬY۲%<,^L֑t?9$ti=w}fwio00sL4k aaaXx1h4⩧b zR@$N, NDӦdI4@~XJ T^աϟFDGu~ {a8!@ Xxy\ lLmΎupؑҖ>2Wpor$ЁXf mxC~gxx_7b) eaRNUU49zY:XGFRXeX@OY9y엗<r%3Ϡ ~c1a8Wm۶F֭ڵիW- qд@ds\JA<޴NŎz &T!"(ڕ._r29#8t48|&}7)\n>> &"@"e1Nktٸ1}f&p}q5D>" A)FX|+xjz Fӗ7OgӸg8yP1/_F~~>Fr{ЦMdff233Ml?##mFjϟdž uVlٲJJh(PRҸAl+=z8||aa}}:97AA@a}:~iŋ0VzkG~N8s<}'O1hP]Ç &n|@z:Rbco.ס]+22`v3ߗuik4eg(tVC,p`sB/vk_jka 8a%Z#"h(,PFcZ3XhfӾ7lprӣ$Ϊ!CAL 'Rc0`<֭#}{TsdK# 6`ʕ8qT|x!ڃTͳ.Z@-tt4wg4eV[Am +랟ˋFLyy$@|VvCN_Tբ@PVFk˖'I6m[I'},=-)òyII,rsi4AT VnN2¥tpp0^xƚÐ~⨩m똖  4sB+?'{?M v99d o/XiQv1V>d()S-='!?7ɂ@N k]JڍBB@kGO=u*1lcߤ]f0}h6Y~0bAa˖?ſe3 q吏?oROUKΖTUBzR^~Z-ZDE9Ih!hY]M6A9bB@HhC "Bi IN@K4SպuN~"RGGQ4ڳŋƚ?yb}5rj$4"MIqZEm>}04; a7nI6`1S#';$1ޡ@;A *FU`xg}E] P лwӖ5$tQ_}ƳQ^[I]'!,r [UQ<0u*of͢OI~1S#'-UHЌƵ,ă>u*T?N}hzÅгgyr&ް)vіO,Au" E8;G:׭޽TFdz!95r )RE._zЉa *FN}h YȍpA;S~8}-X2M!!Rχ<|> i;D~NkЛycNI@NG !!pbqA(8hޜj^Ow:̎+%ʁ-@@GEmT<{?h۰ȏS4͛Gh+VP 3白gr|SUcm"j,95r )RJ'#hsTA!!TfgL9QT׮₏ԯ]rԩ%vx |Z)"=OL몱zⱞ%]Z I'"5rj$L[ 4W" C &~؅H:1M7 rn 1D6-gӖ->yJYRR Pc FNR#iHȳ'4]Goz. *l"iUkN,\e.D : 6dCL 5+.s%k5.$Gzpj$Hjodśoҭ֊܇8_(SF}2-YB;hHIfTHvj=N@h-ТBB@ڦÎ@s7:uF.Bza-ͨЀ$+""Lu}9ęi6]Lv'Ow%$9Ih!!zPF-Z4P@`_Ú^Ow*Q^FЉhЁ||[hTE t!x!܃mJ0ti8ݼ "u+)>II@"RB9Ih!!@1 >(dA:D1|x)l!_`9'I %fyhI"ػܩѣ*(4t8m d9]Joď>O_>vzsj I*x@; #ɦ3 6q!!x8;YsR@ Ʀ&C'Ъ-zQy΀t7vČprI*x@ @}"rsQ (42IHXWGw~~.t!!Ǖ"y.dbIN#6 /Y&4~ӛ~<: f1S#'-($)ЀmgaUe0TB ߻gOn$$adhl*V)׊ =m|h};m֜ko]o|`lj^@v6t CL )gΤ)-[T/O=%Ym1S#'-GHPҼ9Mmq-8"12{4ϧV+YYYHKԉ2T]6Vv+W趝WQVI{brMG < }Zӈh`NȺs)Dʢ%#7ȩTq71#$2i8`j | #ks *i]UE)%OŲkp,|:U]YBB><(_}a8Iy7nP9Q⯿U3J(6Br81S#'#hBBd+#kԩ!*[9UY?N6{]a~H hrdol@ɓQ$5퍉]'XhG \!!@ep0Po~=mM=NTP!pXs6mqA ̤HV&v*' #V n$'e-WH!LCӧgOD-PE IDATwDӻ!RՃv/TYs l7xBIYx@ 6ǂ@QT3׿T`qtO/|Cdm}ڶ03 FwE\X{CNN@,u8r !! H[H,%%' Q\/ u~?A]\Laixk%rMG",Cc 7 4N#WH mJx3 ũS@˗۷  @օT{/$c!!I3uFftk :/H{B00g>^BA鐐}IW NoFয়D7@鐐E:eDۀ_f̠_/MDȃ^?$#i+#hb!m :8Z\IYx@ mQ#(0ͻH\DUV](9] >doԶq, .}~i\koL&.TcqRܙmg=B.#$`GdZ{ؙ 'ݾ=C]P[c{P^5GI,,7Drp'e#hA!! " Zqh4NCW$<1vk|Ao<G7J+E*9'Wˮ7$4N#ZpH!*h֌J,\Ar0(iC[rW*> I+,~iG !CTP(HpOedshNBѮm32xWCݍx}6GAAc-{>tR^+a&QS$4N#Z :hޜڰUU ?Nh9 v5FjwInK7zvI ղv0b."'qRZHBB2(b]$". ڡx'ߟ?OcÇSmZ70 4N#Gp-(t2V$< %/==Mcŋ:gЯדs4;(H"8 0{oIJhG ?&$\MD Ot:EWTvd:/q]KYUk, )9I HDŽk Y|XDa+;ZkWzm$RToPcqR)вq)$d_S(./ZѓS̡K,sx$|f5'P f<(.6ؗ ॖUAڣJkeno\سgcCB@xP26mJ"4 ay瘱mt^|?{L:MƆ6`ɠ%yaiؖaC)z`K,踸8ܹGAff&Mbm-[b_yy96l؀[b˖-T')I0A}YKHH<} v0QQv +ڶ**o⹝[>`s1sF7P/s; N,ѵb\&v(m*z cjb=rlݺ}J$79ɸ g̙L:1 ӧ 2̴iӘ9s0=SSScqرc3 0w{,0̉'=a||eKa]B< ZԜ`~K)/`bIsR99Arv27ͭ2RtNӦM\R!{lStv-CB<7" (@jA*пUyMkq;xP4t\s^B`iB* ׊aSyT,~iG !Hv)iِ{o Ō30n0Hy O*k+͟K"qs^-Za"bKxqdf6u֪$'4Nnhap 2PZS>}0!a|*!D KD6_PS_CᯣOč5u+^E|mq`eȾYIg<3ּf{Ƿ9Vwx21ω/7uΐ8) AIXka}; }Sn_vÞ+ |"ڥL1155xwE&q-cԝǧG>ŗ{ +M?>t$me|_t`Q \+aL-sIYx@ *0l0 B靟b̈́5}H/Iǘucp0 t@.11xnBu4|Zs-N84#RsǗF F}oZ5I9Au]5;Hu}v6԰iZq*Rk/yw%̛>L i;mBg*I hG oAn7uz%7.A9e9Xzt)|!f xz;זcq⋕'V""LD ܳ'mOrx6LDؓsKM'̏oyX:~iG 4ߐp_>?u}=ͦŕܝsQ[_˛}oCLVk6@fH|{[=! '>ƻiуNF}^x֗4BWBUn[6Y('qR)|B:c,C}*'#`yvGZa]ʛР" RV!?6r<7thL<6`aB9w'Cny.&$L@=UlNiv`J`ZihѴۂ$'F Ȧܭ^4N#OH/q KįAX|*||7WC0!,;/ġ\u:}+C_|ˋ| X˴@*!ZƔS@IYx@; oTkI[ ІչMnBdl9Ƴi/V}}0h=# 9;ur~ }1>a*8) Hv.س5x3`a6pᰅǪU8{SN| anTxcSY_G1Tt ?DRz`N|0{~yOCxz;ۑG-c:ANy"3_V5¯ =_NJC,>A3qI l=ֿkqϘj/դW0ɑ#؛;9^iFˀRe,LX8Xꗴ_P]W ]̺8) h ,:|~ҙjBY3qn/75f炳I3޽]ht4m40щ8{^UI|x{y;~2C9pBBHMڴ*9]q$fŝ\+% @IYx@s} <g y(-i7y5uӱˏ/y`xO/gQN3_Kz OH3|ylM݊<8z=Y c`E; .DFමd!;qR)!>O/}PP%a>v#0X_q(()߆:,m}ZQvE8YI垎``8uGغ`ѣ.Tr$&&7X<4hM6!G8 6ی:c&u_o_Y8hG yHXQ[< #c;@dKxQRm{GAG?B!|oNZ5.ܵWK? ?OyANF8p~QKm@@J:cHW,hZwf @IYx@x /`lxH ݢaF(*`{AE^y>>1-a`l,ĊƲFwAQgQ"B %H?*i ~`MmTkbBMbMXD$5uHc jcuAX$iE@!x~c=ݽ=YvX<<>O#۬WMXfDE˫9ܹOt옼%4ԪK:99h䮣B;`ވy`p !!T&T˧~iɦ 3욾 /7/J͜ze~o^g3-[7l褎Zug x2LsXrI,Loiڣk9ӌ nޔ)1'鵌 kRD/HZ^lY_O@]v[do8d>'ќmMu| u0;(+!'bORo?ǖ7/wwy]{9Vs<آ˅Ǿ[oqӶON= * H,Ls7dmƻ䷿= ;[N\ !0gK?" Lnhd^7wܮwO#8df&JTW˩NfPAƕxlX8z!^=GD냛=,CG x8&)f>;V׷W_۷!&F9߾͉pߌ ]±օ~Squqe}hdHtJr0f͚eX!I IYYm}$9;Kj7ʞmϽ|ݪ2$R/m R%R$+oKm$ IW/ݿHA(@->g]6(-6!-It{)Wz4+T<||nߧެ;g{ܓVRFU}1a1KQK4O8}֭$?19K]z$|$I"X6~qЌ_I_2@[2 t{)sYE֬PQwO^biQ!=008~ᜪ9f3qDRR-&auy΅4psz걧0 z͝U/> }Z8/]2 ]$lrh Kd[@s߻?Ga}ޡL{r TkK #(,"hOCorͿ//H^CY"8Xވ:@Gs#"NNNNLf]t ΝyYA d|zSMU"\>A^A-F,~ '}qLqw'G_v ZL<KҚ>,#"w\]i=Z$I~H}6W.~ʶNZQ<͛rh5-T[p:˻xsy aﹽ 7_ ӯhgNFC8ChEEB8a.2XI=4-TL(8_ 'Oc!Zzփ$MPN -2M׮uaO8B(*BJj9݉дP1a|,sSZ*oSj{Q'Z{M JTPgkϒU:@ٵ2F=>Ƀˆp Њд~yM9/$T~QPˍ ׭Hoh!Z{999 \\H)JRC;ϰ`q~̟duFs '}qH0t|l>m!CT9i^09!3S~77F+>'bIDAT; 4i=oԕ;wsw%4Ӛ)ňp Њh<+慊3PO Vm?2X_9:9Ҝ/Zc}7m#~~I_2@+.C^{̓Uh aa/%KruqeK; ϶Va'cѾEI͓e_fuaO8ChEB'')M_ &H7Sa ' 7ܻ|0Zv4}c"zG4+͋wR '}qH-$?A)OP }t9#ZG}(65SA^kN!E 7lXf̘ x@uF̛L0fս-:Ν;]K+N!EH~~~[4 hU9iwFtcz 'x멯ux;$I)@:3,_[2j(x $IbǎNyy9uuudffcE@ v 2| )..D\\xyyb ͞=\BFFvͥ={du|4$--Çiի,^ݻc2ذaݺukm6 f0ɓ'ϲh"{hC-39۷3uTrrrkӔ/[nf8v\԰qF\]]qvvCA?[PXXȀ___rssɡo߾Hdz~zrss9xuj*Mfo aȍ*]\tA.\Lbl5kϟ'//]9EDDFff&[ne֭vu9s&'N ==M6ҕWLL 3gɓ4440Լ뾶\XٗVѷo_?1dOee%Gn_YYeee\>\^{5]|:r̙3ܿdcx9{,Lh/}6:^uWӽ{w](((d2w^jjjx 8TuQ1((W^yOOOzom77Ĝ9s󣺺Kb=HJJ/ƍdgg& 0i$舊 É`…pd̖-[XlQQQl-(**ѣ$&&[Es*@ U$'D"d߾}$''sEOnYh-x(1bccV`K "@ Z._L޽1LV!weȑlܸ & N  x"@ -Eh@ 0("@ AZ  @`PD"@ -C]IIENDB`mpmath-1.1.0/doc/source/plots/ai.py000066400000000000000000000003071340375245600171610ustar00rootroot00000000000000# Airy function Ai(x), Ai'(x) and int_0^x Ai(t) dt on the real line f = airyai f_diff = lambda z: airyai(z, derivative=1) f_int = lambda z: airyai(z, derivative=-1) plot([f, f_diff, f_int], [-10,5]) mpmath-1.1.0/doc/source/plots/ai_c.png000066400000000000000000001710011340375245600176170ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxM,v/yΩk@rw[^Al!w -̰@bČ_H׍dK!h&u`y23Zk;2NٴKTRTDfFFyr/kXc5Vŀ"kk,kk+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc5z5X[+Xc51qok_oOWZc5c*Ww~wK/?t:Ç?k|bUЯ//_qwwXcX~%?ݿw_U~7~=_a+mghvC{e]c.=^~@{do4,X?2=0ӷq%|yx,>j 1Y‡t0At4/vD9byeD٠lM"mlx\ l3z2_eDlzzC`Bh,Fz4AR8hG_8[fV^ol޵,=XR j#cL$++)CN|Qp4씜:l0AX,<((𐍇 K~C1 _ kcƘnSL|~ď9pʉ\3o8֎|f'_d_b?6߇?0N/0}0N 'dW3m2ن ƻldd ق@vFރ|8 aC؅Fߠt H]hޔ' qq81 I>uYN@_, f0$_ڪKC}])6Y .8j /inYu1_߫!>s?q8Wdlރm @'kAL}a4:9SWx˧P/&Hf={I?'~70!EI@~2goHN̆l2ܓ+f{> ?gM<@a6? hޡlQ!lۺb#@g; Sڃ-=`LfLSsigpk{JgKր(~ 2 @Q_PT=ú9nſ3Nsy%a e@. ß~ԐHtm3 0"(~gȸjuQ-Q_Z%m:x:fL2˖$=/>?C׾GȏF~wȻ G2c>ȣ.=$Ew?3lfWWc-<3t@ ! CZIֳ]hB]_=F6#!P. DfYlUAXeFƧAz<`3\yoezcov8RkoKNjst ]wĹy0sA“V5EN8xwYծJZ0Q'MzHg'{<҉%e=L 9771^lI;kPhcYx+p'F ̸3ZR7t U<=:!]PY@LCY_.bwf=j{hTQ7?$ *^>/M~N;o2#}i:[ks%_)nrFIeТͪa G p.!HGgi;# X'9klH4A8?M@ސjKdP݃0ٓ5?rO][1WWbtfh[6E1>6.KёԉKPK,3T}ڹM}Pi(Ќ6V@ǫEEIUA_@\N\cgo62u _9ptԙu '=÷5y]Q6c gE1L+Pf% H'쐚ij|Ngӣ1@=17yO/'88M<toȇ??cvCw!oiyɞ {܈qkk Ey_xպ)izGtBY2bVt!Ü`3z߫/7to_"/8`_np~A_\ 0vp*еtF=ùНY@z:;uPjԦ2h'-W]҄\TH!R XrZnȉ.K(j1Gm(wiy` &[;u??K溁NV`xbpPs6a] =)a:EP7!AB㕢Q4J9}x}~/[*+r!yZ砮oԓOr͘.(3yE.(eW݇QNbC뮤 ? !dS6m/;KZu(;b}d'7cj!e覐q؅[_ao7;j{X$9rb/*Z[H3ƽڹuTs44aSt´v i.P=Gob)szT F1u/cF\VԫB"=bv .5,K m;da5 v"MOΠ3ɨc,ֳݡC,nDC-Of/ţf+e LfXuϘ< zȷkảA 'H{//Nwe#dW|(Oj HNa0*c6V=kd,js\.~NH8ݰ}Sk5g-`$z30[ij=_6`q4{%ZQS4=XfmqY꠩rH[-39yf#" }a1:Naz13&-^vy`Ƙ tO8|~&Ye.Û&F<&;oܣ)d$LlUQc:6VOڨ](bLMe4wۣ]mG]#BZ\uyZ< o/ ѐ/|/< "۷z-: c_Pæd\X[iKWOHM(f IV d k«:&S'̫clQ jAcRR*N0=]{J.]tK KnFUQJ^I2!&m[1"ZɲZ&1wH{ȷollzk2W9>co2e6 }-ؕ`?ut(,LĤN jj3t=!eL69'] KMJc7>X e%~3vŰ^QlBzyD|+v˜\Fψd\EϷq2Zb>-5 -] .)琎^zLCi1CZ8,WԆny͵9$(‰9杉S^B(m@~Ğ?B & C~`w }ްc΄y)+~|Op(Eg&Ul1Ovn>3i *ZR(AVbͱ][K6MmzVQhk+Y|e~i?|>E]旛WN ^1^]meamvbj ٖj.]c@do 颤]lP,Mt.0#6qd∲C8M8"L:j'l;dg+6L2*-䏘|=A޲;j[ɮ-Axm2t6$P Ϧ#bĎL9Ї1u:$6ΡȢvO#q %_;O{Ƌwi9?k{yZm:ڥ8 ksH:CZËRBCyVu3[KXp.| pJFw딱VWb`]@ZX2F&%Yx8 GAcDJNFMqygbM(#fGTOdL&tfUI^7*|w.5 (%KhXCڗ,/G'AK{5^#-t-ŢFrUJ r!铑3+ŻZϣQ*K U%=ZJή#+հAzd!ɕ5A,G&Ll&b]}3W7mMp,:qUɽGvX~r;, s 7I)la cgY1sz, ZcdJ$ vuSsn}ZPdR.1> Ke;jFj{8fQ@`Srb¶{̷ 6*\u"W{ Užxyu޲xnJ kXHTΘ6-; ]pzluԺvVj͐|)Iib^<_*k6w6:x ΢~@o]IXv췞> ȍďvbp]&Y e𜄻p̸&& =f36 d;!&Gߐ+zml&fM9r< 2*VAP]8h3T1mMjݱpКF7ܥ/w7V@a@B.s% 2+)׻8Z/e=7ы#S,io7-ڿu]XvFEw]T,kUtC.vFWF- MY{~oݡFVBI7UD@A}`S():3$dA6 IA޾(G;pmsPy;od Ͱlэ1|1G:EF cGo;@s*(Pʓ)ϪU9ԣ5u#FUKP[MxǸdLu{?kUX W{_ԟC.vYk_OQm\ߣc*4h@]r>vLi,dN-rW|%+tJ 27 v:!Ǫ! j:7VG(j(ajlep#>seJՈnCHdf]hWz2d! v›?w ;A72dGÉ1:+a=f[z\1HH(j20Qr CJQ/R|,~QթK9A70Y=kJrv.}c+/ſ?OOݻhl/ >waqw&{1[>gL7px ݢwu%n  9RT-bu\.0[UPwF+i#1S EҰӁֲY` 8kL3+Kb쯐!AݪiPLȽen&&Y/ o#HucQxBPB#z۰gRTkGʨʔܕNCug)u Eo5Ky[HPG)mf*_Я[3??ŽUӯsq))O&rm:/3)N[9r\Eg3B ?l^3R@F>4/gB_;v:4œ,Tg2UaݑMXБͭzBȑen|G2M]ʼ2(cک:vj 3pD$T.8nQ66MQo#2aIt\.0RMxVJt&WUUGx8kkx=>|G#~?? Dxف0]ia ؟uZ[WjVG)Q՞ЖϺ]tɥ˘e]YGH_" IDATlpA5z1v::G< ]i^SǷ[d{G gXgb?ޘ2ȼ'>o nAz>vu&g¬ն` t éBY(ud)6~_;/Jm|V4nmEs*gm%tЯ7&?r?_/7άҠPv>^&۪rVHΊ7 mջh%9%܇~==G[*S&悟ŏwEM;ȱLH :*˦rCK; 'S rU'ȷ#r{G"!օG~6?̭eLx+{7onq!TurQ٢ҡ6mDHGu Pi„q2W" 8^Xk0u ꦱVŗYM~%=V"erTrh&jn$pϗg$EQK';=JEE)cotΣ 5ITG,ѩq%۪Mb4b>ҡO  dkz|΁7dޘNwbQYoԻv> y=݄fS^zFʈPIL;`aY QC[|i+?xiM{E`/T5|wc'RSsX9,nkcШi|\IX2tY+p39^+-C8Wpaln1AojqTҢi|`3HZv~#gPξdc:< rk9oȾGT ū3q'Qwވ& ]qp16[u(1Oz:qH7*ڪ\3Ĭ'] so%=vUUjS3.8S̰.mښ"JEa׀(^-ݪpnA`\}U3 ya{(rTJhۯSyB7~6R>gVr-9w+㠤MQҳf0)6=Q'^YGJ~c ے!SLZ`}0r(f$~ 2# };3cl܉q'&7@sZc4dQς>? V7lPqtݜQfmnʰ[aQKsbxp&چ"V@pPLmV `*q٢I]xփea, 5_UўGhnm-Y\S[)̳:FM5W@IX7VP]U[OZz 0Ms:s$1[r*[Һ#IW Msd hS('焼EmȶbC]{|ΣϮob lO*ZF H3Z>vt:zJ':FRiu2jH)1'ۋIյX̬ o/]𫺌Ǎx>wʖQ(p{W->vYb|p9s\\Mn.~cݤ;SB=wfPѵBhv(P|yrYE{:eCoE^9Tu(N2; ӗjwiO-x\n d"^rs۴dCGȃ(b܈E}< Po#Mz޼ݹtBwmRrURu_Vl3%@]!ߍ5_]Kgs=i+XR%s&x[p[f8-KEҬ[̅dme[a1I]/sSkW?&#?x]!o6X!X9k3Ȟ|`{U4EEkSڹ~UJ`[xiГaSER(yF wRͣCum/l/NW OuB* -3i[%b *U<3i:ĺ]IB;9مա;(-\|jwXɛ^*X2 eH 8TN&Nы\Չaȃqྴ)6FxdZla[.i>mEg} GƘ1y(/smmHrȽ`hႋ(nw!&lbWIΠ;T83'=zgjs40|ҙuF癡\!mcoS ^Y.m 0+XqF^o(϶9mLl/dqksKkjsU8tTDv;0m?ϝ+cizaց&zသg&\q]:4 hWl×3:G9QCpRuC@9oڣ؃VeÐX(X (yCZ+{hlȠH1`z(&=ҫЫ2IRfi$VH<{%A 9ۣ6ֺg8]$Ҙ[E]^ ;9^,7RNȊ=m*}џ㞇 Fq,ddo 4R|7-|fCfDVTWlPUj"o2\+^fxSڋnGz9r- gQ,& ƠhNp| 8*ܨC:T|Ƞ6#6_]2l t#IO,ӫzu:-5 boV u%x p/u~%^}3mJ5c E;o`٥#gb&BEl%l";+*K,V:_:$HEK-?iScuՑ,yJuYqqj(F4m%NF pT_tt"Nu~|/^@>_3FA|]̲)$J~g#]}`3B& ف'4ә~ngZv9)'EGp rab.ǟXl;bޛӈ9Uu˱ØwqlWb_5w4Pnt9F-{ϮUqC*(5J}Y3l>.M] Pѽ$ :Gcur?Z&: }&/TωC:(ZnhQJ]u3vz 5eM|\ w[6g#wڙY>ț-ޔ$VJPW[ H+ j4J蠶uŎNd&}sm3MSKxfvm@X%U&as,-,V@(݊2nvs=7ֻo""ruY"lFx@3j"g>tSs_Xik:.>9ilM-p3jSSPS 1f>&:ka\ENXp5Iy D'\\1j`>f4a/^A|R|U|\ 0`.Qӻ׎BN'EL.g/mX۰us[t4KjEYWH7B#.:/T+?=lc[hpr6W0oo.R@ϖH|wkf"jFOvH}f}2Li_JAy]JK~U#|. nЮ0v('N&Ucg+Rt$VHG ;7 cQ︵kc'1 cΔYI8>𡗣Q"=-76hB :>|P"YLH&VEsk j{a)6Եˑ}X1gsCVEifO:76-\Ec9`ksZ ݦܵ֨HW;~j'\9/Z*/|κP֨)Y VǠPeXG7J@z~uMLLҹHFMuQ1+K~u1/j-[ncCG4 -&aN'azT/Wl+as16 myΜi@h lU46a3- eas=*XeGXnigzyD0 fVꔧy_{ =VA;]ZzN>T$FE/5 S⠨bu4puN“h*8SMKvHj{5]`}I|WӼ!60/=w}DE {;D-Jbn vA7PiX(V qArP+E(Vvz"mn ]>~A /tZrt+?5 jjF-)Eb?"VE۬63g2i+m:h94-SdsV[LuYU5mꌫ]鎤dMdIA$1kG;)I2(is5-8!p..Zd7Pm$Oͣ =G[LQn" ܠ\3-! /퉂u֔,<ץe4;,nIT:N}yaufQp%ih=eN.V*+_Z mB8+mq8:M'X'3BqFaz#j= Ah ++F@GPiND>VP?r4)Sl#X{%ytVGVRiS+ z.ntwZuY>Պ \@5^_QX%sտ//wߙ_"cޯiݑTvl. 5J.*'-I3XCzkt34 U h/ky"R;2jW<6z9f}4,lu'Ħ:Na.لn¶R-X$:e 9{,&2t@r5bWvHlچ[X6r@9/S6bC; eikԉHÈfPQjZ jºn3镸4_E5#7S?S|_xnu]W8LK8U- XP}o?_bWQCϲ]DT"0=arbs:Ѱ9Ϋ !ҭf?g+6ջN0 :6)2pҗ>qhHܱn7 VC?"'c몠](-ʖ n-m>/# ec )%^;m0KpuswžzrsێN1(]:BXJo6OOOo{_ÇW ?Y2Qbo E] ]xyPfN}椺ȉ0bƍڏtrWfT. =tF?^=7LEEPڱdax %Q8A\#KG" vs*ݹ8̠e}J( [/ ZEGkz''Gmi;m06$hq `o8TXGII|\!Oi%na';TڶDgmVцΈǵE͝~l~%?+?s?-o0Ph K6GY;wa]ZCy;gy]X>Qы3@F7iQdt!zU(p.s3uڱuylFfrY5U I#Գ+SZPPG8+e}(7{e)]6(:@ͣU[E<< ψ>袠#.;ldD_^2q =aL"B~z[*v9_n-ݲ̵t? 诌__~闚gN:KH[M] f^CEU.IVrA4.۬+2a˳< ŋ'‹eb ;W}؆т̻w06v5sǡlIڨhȋ8 el嘄7[0nĕ`Qj}'vP?(3h]m\h['.p 듩Cc2_g3Dh eSBƓֳsXV Q IDAT3X:^G9%#WbhŬ+Yq^hF1`V-ϽT}.#ERĞюӨLMGt# ftF^.䦸:2itڳѮQ^~F` eΝ-Л 2^SK$-E_G\־h} ʘ&ٳ}*sHoc3tk }m9J7mU'ѳ d+'KBY6Gia;/@]K“^*b!}e830pn|}Gd*LE PgNaq5u@:k.Qy seP9XJ1t(( AuiV&qs'cUQ[ Z>3'Mxad˵ZyTݝgIoH̞#YtZޑOG*ƦYB/\hĎn<Jvc}"gPe⹲6v\!b歭 KyVÕ EvDi_SzVf2՞$=&qyss)v hX;r'VU_Jhnwd9rSXMyPAkd\}̞PayEMoܛG5._D \1J|m,Ӳ]4/͟kot|{/cuП <>k]))6Ek"=sf‹k3`XTtC ]ESZAm--CϽ8aس-PEEPo8(0@]U@ngX5zV?<Rc:2aX]iaq%;MՋޅj>P+N~' !M5 Ll၏ܨpƓOZZ,fl-tur}v4xNGL?%F*ƌ|T7>cs-!ѹ.-MB dD2dGü:iɸ}//0++![ckUUfcc>"2֪m9bEdddfdVs1 #VBtڞJ(2X7-6#d4eH E%E?q͐y˓DIGgT=_xvji4փE^vhv"mH03cBK D KА)yGXԳ/:+yZѭ}N73!m*zv=7q'EGԢm#&؟rT1i`7.>P^c_Y 6ΔFJxmJ;J<@&Pud[(.L*XI!k_gJz|he,w'{:>zs3_FZYwGRє]lb\߁Huϼe-mLhoceN4:ľX:6@ZI*Ó']ȬO6οiaqh1q%1a*:)4;IEldqTGn-V9sQSU|Cܳ" n&^ WiʡRΝ4G`oGtcN5+HQ]-va)U =W wjYZ⬮u^]JWw;McR6ʃơh*zV+;'6݀QYhQ`:d-:fGFʀ^j^tW Qc1$v3Wq0E޳6ny$jJ5y~RUa @іi-L"L*噖br=c>ݰCV7ymдyڍFT֫uz1PÈ#:J妚/.[J%mpf:r!0撀SK,8=S;-bu!]M :u☇ۥ]lqLx-Z(S@_OMEۙn1%w$I[e(HyF,T/K5[ԋ%C{@hMlXO+6Qfh-C8appM:=2b¦^[;<+ g#\LC zF kfZ+E:j i^+bemD:5#W/V+/:%XcK-e2kX'c?Ev$@8c:y YILfsd/5иf}YOKZC h#R%f-6S;Ťch8T7j#8:죣å.N8 M![o&1z9rnl3@{ *0db z=p9#x[&z`MФPXx ZuͲ ME+0E%+As> z]6/UUDx]b\bW$ԏ1@ځqw6+huRӓeekڳcKga*i(zNIM],E ǫ-RY}Nm3K;M5Gu#ETEqhfhkJ$U4֬'@%TG/3H FzIsjp rgs@6ҩ(k6TtG*zڏіc Vo䐶XJEWJrco })+Y, ^z dn\EsPW';Ƹ={TYieuh:\%8NHg3ߺ,);}XIicn ۬zbݹY;MQ̙zTkH D:N5.H3/:BG;ƃ(i4鬟1_0{; i9 LX=ܮ'KdiJsTv92a%fC,~:~<\;{u5튺/zPGt7MD/6+hBajz q.ְN۞lJ\]8&f᧴` yC͋ HGdaGDW%Q&j\<z^: WiDj7Wu: -|iq3X/M9˃2ȇ-)DCDcJFqUm4zAT~tKg/EO3WK9gKIȬ.E7,g%]2"A55O~3*ClJ$2jW15&sP LbʮCב"F,TuW KEYhѦs2ꗹn^y]ǘGN^kd2x3]UuջLׅ4).#GuL1 185{M]5=zxڟ 1G'SsT)2Gq*Jz[M )ys`f]zf{ʕtA-=PbNSqQ%퀜t֋SȬ2f)sZI)&*Wnig@}c[V~7~hxnIRDc!$Ցv; ?>@SL*2hr Qa/pQV?t.cEU٣=#M=ujCvBGĔny4a7U%\v4N1r}釈CDG+h.36Mr^ب:uO]Isgo[(u0e~T 蝲#֤cn9Uqs*%ع}K{;;Nwe@TH:6!%6Gr N>8h)=Z?@NZlDt5q_VƋUԊͱcm h$*ZkX7 +ږÆ6q~tsTj4@g*^')2e#yҚV5ttqQhPBܗFRu8 |. .kfW}PG.pV׋/ E`Pmw3Q>Bxw;)#??G5:+1og֌nW :'Iɑg#0pm]ϲ1rAt}3=9Vum56Ѕe  zӿ!bs6^֊<5#)2Ĥ7ZYZ;55omu"c"lW*!Vw8 c 2yD` 0W&||ur7Sϵھm'^ ;^_G׽?odPƲ%+ G^PQG9Nq]#A̭kW ;f[+Fے]Yʎw }96;eM : 8s0/t*Qbf ᯒQlqetF1"A#Qi8/~ yyNY!wK8/ɝZmO}kG?ʟɟw__xU)|Zu ChjE4%*20gi(T07סvIM>-vmwm&,V١\5yi9 u+U*S& ^G 6^c(~QͿOe<N#!MMR=hͼ6qHy-є} g;TvKQ"t{g]B<3om}{y{{^3iu``eq.dhb'U1r` '5@٤: ]0D'BBuZ"ǑvuC.tdW)C5Qz)vs0W*vWѕQ\? M.DMJHRd>fZ Ϋ"9D@Ev%ؤ3R:sTGk\T^TlCc*Ke\]x[jwާ* 3"#=6U$T-z')c1$J"9B=lA +9>&EVWiU$ %;cP ȹ킴Lt]?:\ƻ]+hu@hJ#dDQ95c_DpC뭙&!jx>aj[u&o%# Iu9+915}޾gLݗ΀gZ{Ũj}Ufp4KAiVcxU֙ gA'ci-qu=ӕul-o*P]l`6;OJ U҉Yƪ4jwN "HOhm[痍<ԏ/>Hi=י)aMEEu@ZT4L#g{#Q'UlYe:{cEiSDF/jJzOdM!zPTWSH9StJȤ [g)0 U(6%O@yTr߹΀g:1hqȐ;^AM?&WuBhgfѧ'*v#=NRd =+/!ST, MhWlGr$Hm%fD9:U*Zcb4ذv%̃vHz.ϧה;ӝ`=FeKw˝< IDATqPQe: 1؛". T8Ry~ O:oOalgp {6K>PQ@GuZb(?S'lX#MvDꝲє mC%|%8rϘ;scs`nVUa'o"#Q`͚R4)QH:j0c. #ɾ,Ev榋o_\NXe$7AyyH2}Sp}NWI;f/̲ qi%~.WMW Z]byG 9XAڞ%Խc".}=#`J(v e(ϔ\cwjYUdshS2YNyIG"*hW֥͑XPV깂szɇRdV4Y b𬶵Z>Ct4e}b%@Yb)̋8hxaLvZ -&Uaio~Uk5\ <.aQh!# +mh?SQV)TP d=.El,N. ;#ѩ>8~٩ w{9_ {+c؉֠̚A ML zVY;9zYIPL@ߒdMuqQP_,JEpiIT)*:IE{">&stYuZb&|GGr ֑V$@%4{Q *OT.Bs%].qjf`uxנXQ$姳ëDΟ'} Oc>n}rGT20t&4mКNB;0 Hm8x,tBR_\}(RqPd.8ۉ@Ӓg&Vjo1UzwCo뤺ΰMYKiVFvȤk]Eh xuN`Y엾|;(IOF. )]t ZeEʳۿJlQk*?A?)4AMaVIAx *:7?@.H?(sXd9Eȵ$*L?m=Bg4 #ԩ%#[owFЦ.+b;u_ڥ XHM35->*:Х @*&Gѫ*~:*%y jD_6#eĒ_FlZ9[usC"w{uK>ͷyv __\]]}-oy7Qa줚 HDLodD7$HJu!A XbA3>oaX8lXͼ ge0 NLMұmDkՎ^{w)F . {ATAZܗZE ^ k5)HڨQ˧Zc@-UZ,9-)Fg`. zٱG%R=7]Q|ztNSbC͆O|~dRA@Nء\säE/= [@*P6 Qrhv ==:g嚑YI' ^'C S[4JΩ)`+55{=pfu떊xF;)̑Ցw uPl;XJ.2s*_`>YuvtmN9Oc$ iJx i>kҽBZ>ʝ^OX^[ goX@ݎv ;>|'߫cSmpVYڹLAV 8,'jlAW 1htZ v ҩԩƞ WD0hi +.@+HlhIf#x{k }!jsDWAo@w+Pe/5I*}hh* ']ѓQ,yy>Ԫ.mKPx<8xrz\:Vo uT`-}uiX@|w}gƏȏ[[o7qqg> <[dPnj\ #GvmNFj/i fM0+ktVXD/o%0u6X ; bo κ0]0L+n⁃*A1%h;Ho ҹ%M=6;EC-B3vuTׄv<ӚtSPkS݀'>[˽m~w;]?W/S=>M{qRˆ ݲ\3/2`&AƼ(8x %7{h  !|n Լ\L'9IWL0ifv@-z6 j`EtَW7 O=hȨ _櫂|_j4 }웢k%헡y+h ^{"WLĆAL4D]q -\PQ)ԠC>;z ä4_yIp<$FL+*u˜x~ޖʮ$rhB`M]-N> heݳ,G!߶}^>>^xя~O~o~3a|~_?u%܀ytRt_'Ԫ'm-VZq'nѼun}iݶOϲ{wF=^>O}#?𖷼~oFN#hsUD"*{4\aj@ x[5>& :ЯaE׿Mo3 ??g>7?mExk绚 k=fD֊/y.zr/yExy@ـ0طN+Rk7įI_ Dv< 2Q J 6.HY l.`Kh7:9( ( r?XyB="=„էN=)7p&BtuX'ؽǿ?Vg39zh<>ڧ;-ןzSħtn`@ w?ϛfև?Ş | =fe(9_zW`{E'>^{qqȊ6<[Z&A7<N7voJy@dۼMEf  [P 6E/ |گ5h"thh$xˆH  mx < 4_f.khB@B$-;A!K@ip^:@? Q-.JoiL nh@k_F:@6 H `Hc z zGS&Z&BأX0%!&]<*vp\0EiT _ B!@c'@#Z Bx^y`zv !\Yq +EJM;'A'jAEYטFH~=bze%(iY|priiAA]Sj8>|oϚ\,~o\ϗ/)/.~fgCK+[Z`MK!%b#LMoRwXL)Y&EZэ>zF' bny!@\ j}rbYݯh#)jZ.z|nO~=?o=4d㠝h6!F 6V?8AȔ+իQYƎIMI.*+Q$] ..\ӯOn/@\ ] L \ QQ!!{}e-G, 4VddsV-Rנ[0n XQsT$kR6$jL90H/jkVD0J g ZpW:AZE3Az lGG)j- 莓0FeSRqG,UCr-nuH6q׮SgNFgP^-4ByХ0ӟ-4Yy#\WL3*OTV rmWҚK+K o:TD崔P.:%?AխYE$o~6}Y;WvqK~- pfmA&T*U{E{HZI:'tI&XVetorzΆON - b9)#/`{h~y ]i[+B*Ӛ]a ⋢>J56,DMh6CtV)/YI,%~w.B]2 SИO߬m>qwEegZ (Cz 0v}k(s cSVr@xY2 h|Z'W,΀g A8Z*AͪTMD^piJP=6+XO$L1LQ+ ;Sk`HڟV(s*p#hFjщCZ⨿ YSϚ=ee,2e qcvY)IW4Z ][( ڀ{@\M5GXMbR33^FߕJTɰ]Z',܀3B:݈;=)hqjj 'Z-F12RUsVҝ rrygqhy?:NdJlWSnqq\WKMhy\ZYq10[fL^6bSpHY!NC!Fhj} 5OjnYY@ǨR< fy6_9W$gț n}-gWG;i$Yʄqf.k IDATGCW1hd]j%7Cvz_mv0 kAzQ&Eh>˅aEԽZ8*۴xt*ff*45CPQ]U/YmlZ2Z:'-IKZn1~2N% |Ɇ*iXL Y1W4f {̃>??qNNH0(kDY_( ֊&{VH?<m0_{ڷ1>I1'TCĒ>+tltbi$j! y zY*v.KKS]n!nJaR"f=4&I=,r\)hm< Lo?uN|nMj[ K% wjFV;wA){lfo1$k`NJy G˹+:K&J_{c %|SjB)Qm_C{26OnZwnn!xGt8<zºάR0h![BH~%;K- nѦUV-R<5H5STXN sVj @ZКtl&֡".A/./⠶(M h iaa98 TQ ,s,(feh@8yfU1qT$5Ϛr4q]yܫ}܃nQDEԺpmYRQTGbc ֦,*Y%<w$4k)Is=ȩ]<.:]4:Tp Y$VojC,*lb'ݭ KC'66nxQYЋ\zKBa+̸pܨڗw=AкCF& ,I@rEeca'(M5Qُ\=ɗ'WOYodsGB[qealMdR%bޱ<%JJU!NN9Yu٬X1%4ZgUt9ZZ:ZZ<9){iaSgQt̠it`W`nA2…XD…¥+S7(7 pb*zf{쓊v> }THPnB Ic`>8uoUUs7Nу3 Kՙ=zertig@߳8GNcΓT(az' (Iz2\ӺKxȚz\)в^4OݲFd.,e@m{'@7Υ>^ ahq`kpEhj VR+g.y [኉\S`0,Bq0W*E$xR=;ER͊sRS?2 z\-^[]̼s|T.)o@fx*w@WP;D?ϯ^0]ve=;]bsJ,tlGlMKNNL1/ufsb IkBVeߔ8,6s*Z棄!Y:T#.!fo\DWe*(Wno||av+3dy `-z="y t7NqeMmn\pz SۜsKU8:[}x|BG׿i3 RԔ[ieox㰰8(sYP K1TZkgH!vYAw{15 8=)xMB%$]AKpѠj[ 68pF~"nD#zѕTi,y FQ|蘿Rqom~rf=_Lb)y&itLsiwr('[V򕯜|,l$ZJJeq4؛IJ!viKrݺ6ti DЅAVN9Am.󊨝Ep9Eq·'rRQc{{)eC17%麫~1 ]+:z0@p@[MŃPϴA h62F!v Fga⟥/HR1QުgWOms4[v:z]Xd5spautPa-ك^R4!QY[J įHXQ.X^"y5fd6lQx3Èݟ!{6#=&pyJ<񗄼ȇ0&X,hȐ,z޺zmƞ yس_SbʒT$f92,J259d;`s(۟)g9Eel>oOfiLnmboׁ{|>.14=zfM;:PtY 5NgQ]Qyf0]:\@(ItYԼa8=pw9{~:C4X;!{6QleNP:לovCS70^S ?0gΰ܃"SU¾HސxRzU;[-˾L) 9SX7/.oRZRj veЧZY LEYd0 %ԕAHu-&HtCʢKʹ.6 3s,'csJݬ.Jͩzѧ;PGDV xՠ\!틁 أ |gpv'>![#='ڌ+K\Y6O)Fg[f&` ᄲg䅓`J 8'v$(C'kxlt{ _@R.v,@.0M_ވbnQIo5/.o*ܷxLKN񆅜OdzֱU=W{]zפC?.1uOtb9;,~snRs#@bpY{w^Ϛz>vVhX %Yh !ilw` 6UΞrS!msx7=p/؝ns8^AkBAXJba(8IQ{&k@zʹѓNE]Ρ,ꚘҹuF>>r~N%=m.|X:@ti섘;"aY.P]iӒ~H],:Y H2 ];io񵽥xb\' Zme/0yZ,VRڛiAZGgoHgoMt( еk7V3H5\K ocXH=4$X:s\s@qs,Y`kW,9Z;q۞ = 1 n2ܘpcFf̨LvG;crږ,hggҰ'eC=~3s0 p^O+4|`>{ d,6&g&v7p{=Q2Ya]=xmB{-n\3ƟɟOO}{R&Nl&Ed6,JX68 onv*xy_:^`}$9%&u@ lR:hpvuªE_0$dI3 )OJ2 |"')Wp#0yӋ d䪞*o=ɶ`w$#damLE_+EHk5BЅΚ!^v'd$wvj>фY8U"qPBI{ͽ\;'Ax/i*{֐~6.G~z3BEAPJvou~^-dQlUE{# H7d 1m*ԤvBr)+s)Ylj޽gycm{#,23O@hp^tgYby.\v7s /5sPi$zFt ;`RE;{amF:8 Hy;Jzm@ >EW''5ܫgtc:LK2"T($^[Jt,A7b4C~-8b6/& qS6/fwԿ wG39;S4T(pB4o;uk!x6#oRwC *rUL+śaC R>WQ%DaB,Bv ^@^ ^a| 0b {X%a5nk\‘{0Gzv0;}vH=yî ݀m2rQ+!/ ]؋x4O6YxRʹA2yme͡,BJ)B>`%Hz v酢M#+c@wwoT{9[^9?6Kg]3C7.ʊb7zk7W{ js>0OgֆtMk5BLeX]'8rçO[!,]=KDpX(CB^!`d'á&,/H*\ىb^&̾^nŖ:?oA}p]COpJ ֆ$R攒II3sk.W͒|¨4:0]әj 0s|j.w磟+eq"!Rr`\rmI2!5Iri&4*ү(&˧iFhz.:F:y PNjEOjVl.:\9FŮX"pyD@v+Up4b5V2Ó{^)-}gnA]9 _|^+C3771t#@4 G^llUfQdBJ 4>OYnq=K=jXGZ=;42WKٚz/e4uBd )Գ[!w,C5{hK\S3]ɞ0O%s-k'S,$X \5[yG=7X'󭁺B+ @(sNqZ8wr&8E9zSo5u*%z &&PC tP+X@Zs9TɦF桚US6G QA> 1VV*l9G'̫%p@xd3`5C}}`6sWȟV.wkc0 9Y 4<ݦ2Rj}~]oW=ݭ2N[ys}]]:܏U\t;{Ø7V8yВaɐ8xr)UL%%bsgŚLZqgDYf. (k-w&w5#I ԲDt=^g7?zfv *'!: 2fp[ڰGVYG_TU΄{uy_sf?ΰ]#y%6-sײYHaab5/t_A$=3a "#H?m0# lkib.sW+_9 ȐX 5=u*uv:]ًY--޹y~{CJ3)r_$ǥezx3@ʹU=cnbEވe %b 8檖e#٨i-r? sv=Q p#,w5`C6ֆY>(kcRŌϣ:η&ܩqf:g :9/@79O{H3L4C9(Fi47Ƕ瑢cKjcIy|': I'qzحê]B/KĒb_UkI S#ON[bs \r QYf ټ)#ˆ'9l1z94s:3JFyMa`gq./8 L+$rMα4w0 ^N Be0'~k0r~O2C(iSk#\xu+㳋dsΏ|\ͣA|R5=R<+B3AB+;]S=0RU5I B=gX:m 2 [ &dނש j9@dYX :Ce9r T3,;0;yxBxxBamX~وv58~ilqk-/b|/oxu5 gO5,i+5'x<" {JK^W-퐃O`މV03C\Q'm[WPqL1K 2os+-sr.+U~bwI\,tQ=9-u* bQZÀ4`ɢ`|\4 ΓM5K(hEQ\X9ORXi#s{{F3쐶'Da [{~^gֆ1^/sA;3z,gS>)ro.n@o</y%+W8ǎ<)lQ1t4C'fc"kb?C$,(T[īHO56RT)O˔.7٦/+}>.1Q p$l" bgwK̶9WϜ:QU(QOTs]>GRA]s  4s 0[s1%1B=9"6,ao@\/R$kp8`^! mq,{[e(K'img @Q+jnJ_{ (V{E>A6y"MEDZ+ʙ\g6ċY48*PbH0ql6G|-ʹn ļnk,5^0/́TH ^u[ nxLL6>c|FqKY6i|pȰqCJJ ?!=$dDŽ<-s <䵹I׷nʑQ`{TM=]& AD<#(r. s(AJC9s2|\WT;na\"tʹnr6OR^Т$.rj"qV' :@f{!d{# sTF'vXk۹r{CJRQtpL-2JK(:b1/S6..o-tVYL[?<ډq]b;0<+wkۚ)R̙R|,j4MhgmHs';~k>؜Ҽ!'AOF@YN G'yxRJW +i ү;l1"!KW]cI 1ƵYPnE&Wd(5݈}[b{؎ȓGk,Be48y`rb1v$vhk&69"FRH:b%|11(O4 UIi N..8:֥Nm L޹( )zc\7QNdڄ+luԳDζZz.α͠rDw`>G N'Hy2x܇4{#sS }sڎ;,̰Z^:zbtKck:p8c% b0(?A 7 U|ȭbwϙQY5%( Kg91B1[;eO=#fQEF$+ K#e' Gf+; ߝzno&DϏs\X&݄+'6ǔEIw9C IDATMO~3j9Eoy&US!Vi-&:ڢXd!ڠ(s!vf3L3 ku/_ 3n 1BgWΙ#pVsfk [ep6XDž(F$@,x%&+mҰkLnPA#}D'7ؓ|:" 2 _ηE%yT滁*kS(KK,$3GV0(9 sĎ$;$ޔsS;d.YrGlV ZnX߽I2e  TmMZNOgHnozb/v\ճk#~g=7ԳpfbV[\3R.3D50\%B5PsyQ^Z]9 xO\!Ү̴9m {7c+HrE *7pV~^b l +Yϊ^(W:Će Dd60p\|e eIfƑr{L#jd!/d{E)infP:d9t*ܬ];݈cql X a _OL d66pU PqoܓHg27i`^:!KlѾPH;L8'm 4^ KÚUEAGftW$k/.!?xV "ՇMgufoqL|J,Z۷n:J˗ ]\n0HmX[ 酤Rt;ϒGn4 7|Thʍ(768%33(3ܡv =eGOCc4btaCV°.Dh 5dZP35 Ťr]ZMJQ؛iVf% ___[[9;\*=djuzt)}bjOL 8Դwv\z"JDeU%cՒZRC8ySy(pޙ׶{2;Qd[b,! dm\Eּaw/ ga~k:y>a~O >DG/|OQE lD^[hcKйx#!!K>ϧBJ.wRu48pL UTL9W]uR;,W8e~sɿ˿ۿ[o ~76ޝf 3߷RbBM-s,F4樂ߧC b!p-]=KEMLUUݢ@9+fb*I ^f A4qaKl dY)\e ݬ!,bm8K^ µ7&|0 ͸}|B*vrK{4m{tcKq%y9(<'^xIk2eC g6dDr@0 i0.!)ՒK!\L++*ȗ/_>?:ȝcqNp%7Wͭs^i޽Sϒjpl5.m_|akKikT15$G,"ϫacIQ(yO+r 8X,0 Y`k,m\b/l{0^{; dlPF>@LO *ߡ,3-3zm5 Fkc\ yeif"=O5_р%qH0Z&i)ǜZȜҠ|.ھWеU+e?N 2|\?7U,JzRh#5<[ 8wLW;OR.%qgp`Ҝ<9F}C=Δ(C9W,P(CH^9Af$c, +u9,- ȳGՑڈey#WF^i&xQa Bt90_ɸ~\h܌-ILطv XuvOM|\|hl+Fsgm/$B="L=R g␬g8(- 3eҤa1'"srڲb YpgB= W8}<ےI>~A7ưtc+8<`> jl?)<+jb1Ͱ 0'Wϑ`.#A@(GJ48}\B+-zA 4WG=ճ;8oXd}v%)RfL;(iKZwYL}Ml^kfKa5/i26hY0f8xҧhTkhAa, {{j<UksQq8qe#3{,2|w}naLh p> zc9ww ppކ1q 0."e`WΒ2r>݈ 9gt{ @w XT2ʸIP}x˿6dhwMc+ s\0eW}yS_IrW9:eciF]_R %Գ+KvHLҡ5G뛀s4c$՚,E<pH3%`yS mڎnA0;_dG~2?o1X> :|p9! [&#O#T!m[Ƨ|5pm^!Q]aBtsygN <0VL'Wz(klhy * [UMq7>?OJ7 NhLc%H%/6{I^yn/ae%W+=`[WQږ 73a8/)?x |w4 |VV}3kjqi9#Eί%-ƒ^Zݽ{f8/ML"1 8#&\5(f%$xA`Qr9L{0۞Y'z{wRjh `踅th+B:`%tUfzŒSr^R9KUmS-WIŇA1#m1xݠ7 eaC·<"nW%8b(y44N_&SJ$WW0Requ1, `g38rO݊ZN.{c#̬f>A=sH{gt.El26'j^vg?VvvX>x5$5U앮!%䙺1KznЄnAWSr-@4u@-Nr`ڱtUs̺똵0 NYt²ڮB6Q;2X`Ha^}ʆC:4H`bM*8/4<\獷/bqigpm,aBO@i= $ׄϤ6xʸho6'ȡ=@ᤴ0fy?XuCd,k}JzYqr^M{#$G9L9ZF7 Fo*HZ6}Ӛj3)4j$g\Dh4-:!i d GaY$b^1Hu0EkX[-M n8^9GuG>ny#FV"]7H۠mO5D}5TDW0raOI/ S%XS2OiC.?]tV£$WiH *ZGbc@Ρ oviRJΩ@)tJĜekIy'a?+Ȃ1{3BH $Β ' JahK]$[v&g"!SܫgA ' H D!r#tFR =)k iw j(5U*3rV]Q]Ct 5mGX'"dRZ2"q̣̪cV,5bF`V؊&dbP; j=9K[XwR]rVЍ0؞Wu5T10TB3HW0jP# b#2 fXJg\˓2$( Uaɐ .UAFFZΎʽ98#gk g!YTkOg#9\PA/{#B=$4U1L͑ qؾr^jo8xb/}P uk:^Wbmϓm#t:.T]vd1x&i)ue=r,ly"1KČ*DKشA=)Zd I"tCa1F{蒃eDCmZ*}G9# Ə (Nz$I&l!HjلЈVɑsJ.W[n%Ȩк!"),gNsdt)YL93lf0`QpjF\L &XCͥP < Fa KH1ڈQ6tz ҰhC}Ƙ"cN(q]و+(˪TY"bSA'd$=83F{P7 q 9`ޡ+a,$&: u,59W([8&F{B>b] DNĩHnPhr65 ^H ( ߇!=u1lo pe[?b 1dԡC 3ʲŨarN-E/OIDAT P,?.VK[`1лD0] 4$>ݼb@@ %"ABhb+-ɥfQT;)[Ue]+D9/JĂ* ̩!MXmI S8q2M^h,+:Ӈ2s,,Z$XMG3e& uQGE*[vKX7ph#nbH:$jͩ #3eJ*97Ç@IлrnAZ'O9x;|WrpMWZhC)(,,zkC+j$cDp"ISu/Q<[qEft6yYrڎ1ƱKDSM쀜q&1Ĭ)gmb8ԺFWN}k9}͔FO1vZ#huQW;\8k7RƖI } +ůs@0^[rFL^(mr&+f0#i3Xb-MO)1kRIAk&4jJ yU+XǢ: TX'b'-pL.&4qK7:qlsOYzVbia b\cbia 'b]/dmI0亃Hr!3tQ>Dq*&Ĕ( T<ɨtr9==ol)e}W Qف$yݿ*I@:;! eK-,APs@^lZ!HZjA=7@^A*Je eM,^CM,D2ILzk®X*U,p n"v&L&)uRDŽ$9RP:IJJOWPY6t1j(Q Y~-@JB *SiYo0Wd(6sJ{#_!NZdʯcƨk &%jZbJٕs?yN;k <V̨Ƈ^ͫ9R%iﴄ4I iͲCCɪsD(s hG0bYp*Z˲WZS65 ZYQGG*5,cD2;rsv lqWY(qH^2p<Ӛ0cI,bӈ15飺I2}YBu 5ְ ` ⪂*"Hݰ_';#T 5ݰ$#摁љJN_R }$Wӻ'}+<)썓P#:䚤vd%߄@Ι(R lsabE Z֠ ހ(=oq$m␌;(ذ4ʆ*e$ci Ա4q2F8 'p+[܂}ゝa:K@-qc.cd9 :N7pWso@OdT%fJh1WBXC<Ĭ,NhC%J~ NW(s=겙;(3 rN/YqHy3"tJ]'|b(t5Қ^y>HZzwoIM/bx]QjilXuUbPbզoFc8 ڭVhO 9@sUi%¤{e&1,9`De++8]ŲqW&WUUyTLn)l9٥ sHyTovALW*[h>jx饗w=_p:8Dpimy H}4J֬)ԔUU^bM/4yHQ&pk[hٓs ^=yr 0e=0 {4bj4gٷҗYz:c+DDVtW6vLIm(e5#ϑ먯LiW7z"X2Zl!NЉjd WIzKKKt]n.bG<)lcer'N¥~OHaUL=KS  G~YFD64["2Jy&@ x"~{cTL80}1AEl  4 4mx-[K?'a 4Df>"7I`hќB4Yazx{$7+ ˹c4eH X^$?KD&-} طঠS-a6 ~*m1Ħ @W`T7Ӣ*H,7=ʌl>﮼J1|gᗿ嫻x&9ޓ9iyIG>ғ SIsFz\`'<䁄 5⯜`,vn'f0V+T*M-)m>[< (Mc|!R1a1+BxEQKe*u4g'cAEnE앳ﹶ(썕 HtT{"aS9p=<j8fHd9.V$C]llMH3ч igT=+b0Z;# J9␠iD|QV^$g 9<-~_SO/~DQDdrr],>F9V9=*}z#$t:Orr 7872n۵^z%ַu]덄rO%fffVchZ6o[=]`>|Co>;vxԧ>šCX^^?cG?~>#e]c<۷w,..Xǎ7x#_xg9we /O|- 걞yx ˓O>igqrQz!>Xy9tkc8s=LJ?a{98+㤸뮻jd.=N7ps9X`ssoeeeW馛K]҃~w/ |ͬ].Sd0 ?Ї>g>:1:W_}5SSSLLLo~^?|k_/Z˽޻kcxGӟ_kct]jC|ߵpwp?CƮFAI%J(q\$,QD%A(QiKa#|k/v_|;c_җYīFI%ް.2;@^gccK8Y NƸkW n#Gp!ynVx'y/8xᇙ+m9묳^OVˣT%qsy|K/-ɹiRA(QiRA(QiK(Q4EI%J(q$%J8MQt%J( D%NS]D)J.QD%A(Qi XNtoIENDB`mpmath-1.1.0/doc/source/plots/ai_c.py000066400000000000000000000001271340375245600174630ustar00rootroot00000000000000# Airy function Ai(z) in the complex plane cplot(airyai, [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/ber.png000066400000000000000000000457731340375245600175140ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwxTU?3:@H()"E:XA,(DE֮R* *UЋHK$dRg IHrgs5j믿ԩSo5nD"tuILLbhD" ;b1@Ks|c(_GwGЁENEN^,B=bH& \9KZr K~v<וA0 *$46+Uy8 ?3O:}Q(G!MBcb3Bz<@Ai`u볼΅输#h"MBcuޝE|k;+6\SI(xHs|v?5H|z$TeC;Ihl9LOt5 nEtFb7w&a`1@Ks|Zc[f#41-:nz40 ]rTC&[RBL}^3H0RIhl9f?{"$ ,hi`YØfݮ^WOiC 4 MƗ8lm%RVǛf&UZ;Ihl5;A*p@k6Ai`Oq*8Mit` edbMh@GFߨbH& S]BϋzusӥF!}g2Y<BqxIhl1>䔨+swMx3֢BCpڝ8KEQ{r/3䷷`,ڷ[ʹFh&!@Hlv9Hr:F/!S| Vd =;ܢ\N33ar0A@70>=73{L4DlQLB8c:pvf*A0@ &jպ~C9Y?~FA;#B"ݼ7Î FqwZv3K/qsyy$E'iMde'[]Ъt}t`Xt)=ݺucza!-zOQoΓd4n]bTQtlܑPK('d{RoF\:{Nήb?O5*Z)(\hI*]yTjDl&..x&r~3F08J4fGoJ@A1/_~>gx\F+8عci/Vgk,c3(B-Uϟu2[k\1:o:y7#)*O?YS\Vs5škvҲ̘1s2gvUQDﺉkݻkږͧÿ:IJf$%f7i6Y5=ݔ (k~`̑^ZBINz.n]bq=6nܹsy7٪Vh(2{le„ mݦ|zhU|r)-4ۨg2' O0vXYYb^!Gr.$ f߮i~ ^kم_J^sbgXw[=RTǏ{ M)BƟ-ڷeo^pݣFe\`ӻk+0K_>Y -$oݽ隨R̕ $46qsxYݺU1.e 99<-Vpˍ#his8<˃Li"fF|K_8\ sp{ wbe!.<)kf) gC 4 skx{4lĢ1e=g wbKNA/T<) jV9̌)^Lqh4 Ze2y~''珻ࢴ|-[֣[j\M놭UhzOi.܍-߿۳z/ź޴Zp9Q)Q)m&5fpɗS閟WmŇ9,{۸hӜ/[rx^Z{5eC[IhlOQ_<7͹Rg) {WN=kiP_z; T= |? Ob  =~/OʂPhܸskC{ل`6C#q C 4 7qo٥Ï78Q0p3x74ǓĬu|WŐ͛ -M+9 Y{C+ )$46w(w[#5.w6WޮS8ɸ&5 Ƀ}DAxpXm͊ꛬRT 0@Kxߎc;ioV\EY{Z:'uVMw )Eva0Rgt+š(b`P&q7_Jrnt#K.nG8BRoH$/oqTcFuƌm3~Pa)%%BZ;Ihl܉up++鋟滑?:gyЩt-onpÇ>myW{+7 4 M]9&/=?߃l_}]f(5ڧkywRбqGZ뗉+c]G&a9 hi/gČ;ӶGw׶(B+"ogL&S( ܎/-[vMgƺI*`P&) bvϫ= url+ Ok>ׅ/}7h"C"eKNܖ' 3 eHToݡu[r0`UmGѳ5վ]|D<#;綸p:E#!bb|L:gHTo\%9}/Wmv}$64k&oFsQ]R 0P8GƦ{9xlc\?zʊxc|xՇNۮ š-1ՙuk i= XgN&WU+߯IX>QdC{Ihlc׃yuąC}Ruv}|ͧK/wP_.uQ]sUiZ!h'"^ѫzY$\@\?u%5ژqq9փIx.UqRPyhC.EĈ6 D@L DGcY; tSmXKY_?ߛUWÕWBw yBR2^d1ePB!\z?n@kyof0[U )$#{‚B,SxOǎ[Z'VLmq:?K?-$b<iw;~ׅZ}wcn*ӷMYK>G{d2mdCߜ &ժxɓ0s&|5^}p<.LwŭK:\&O.~Rg)73hڱ>|3|w<HBKϴP.HJbyrlE6"K2TXެ%BbE;2& SR?FŤIB;{L5rsǠgOyDZ,|+2iDu.* #C焊n oUsJ Ea( tZ}g6)sxb!wS  lKpyrA0@KK֯˚]s ̙V+LV*_#fG!e2^Z>Ck܇M61*KLg={f>}c>mrvs}wZ`^_C3ho`[j'Gs.r )R Ng>}&hKzڛ'?d!b :4pֹuפHsl"ݛ6/)=^vw۫wCZ{(d] jNRgV,Td)#MB78}Z/ aN}W$&?9ҧ%_ H扛yX5D܊S'^yIɓEjC<4،`Mgd2ޯPE\h]]ToLqhϹ`z!DmHJcE5Ff"};['L8_v.'=;^ebaemԶ׹_H@lyG^nc\r!I_ꪣLa畧9xP;š,W0$B`3FvF+wJbl%iuV}[ {Wƍbb\~Q׃ h^B_C3߫׫97 Mdm2;iG 1ްAqܿ =&xFSlDCNNBi;mbRD 10J%,XkssO˖^{gIZ\Iqr}NN';|p}OH3ƌH @NOEvn6^"qOKh+H/YQgFEE]jlOxr!0ц3YgWשMB0Ao`ݳMi,DX;V|WcjX 8J~ a8b=>FsW.;0Pv޲2LՁ0Lϻ(@a&!Q!Z;~C8{}{snDX">^F|̄#ha2pBH~q>oּšCM=UmR-M{.3:_aN.j?J1=bh6Jlhӌ .`Kv`j@zZ.=ǎoZf ZZ̭Z bA1{Ha,_@{.]ছ 9ٯm>)k0uTl"2p_6nUiGdkmk9aa=ZpJqA!:%m )">]}ջ.-hst%  |m:=3i?@9bu߾е:K%;'K,_3gNItt}#9ֿuPh*t$[b)˷ {z}OxOOTh/QB#hMBRA2z{ IDAT MB !%XwNyX=)7[ 0 wmddXQQxH+ʜ r_EaL:i[q0 !\0bܭT_+Ro%Zy.+iL0K]=td!t" f9^L:삨ːۙG:y1?s^(ꗯZ|-7ί6(Y.SڳffXhn*;b#k cE7~+Yy ĄA-1ь0wԆZFQ94iu> o 7{Z??gez:;[,[fz7 +jp@iiTpAZ3 Sy~=|dX-꫅6k{C;_-~Qhߋp8NVRFz&Ll֓k_˭SZ8Or%(1DžO;$@M~)XysM:SA6TxbN>M׮]պYh2D+t^*Dy@?ɫ1f3k'~n[̺m|d#od} odB(oN3k j?!0 YWYdm;96t3!qwEॗ_ROW^XLV\U" MBńj9dT@%_~$''g}#:r̙1n'IjBdKKEOBvqV{,e+f'cka#?2+R_N֝(%8:X)\ | p[\Fʃ+k=GQ`.̨ړPg`R}'0štK/{r1RRR ##3}f9`_y{؛[~$VYх}1i軽/C 弍1j(/ğ'x>#^}Uf2E/,ͬg2e,K08 1pE`4&\n=aSx13t2'g=GO2٤OH罞e%Oщ.ƞmgvܵkWENJvKv"]t`glذtS &c[{b/iD]زw{[RcDzq/ؼ},!4d6oL~q~X Nvim6m_y*=۰vC Iz7ndܹ"EtB'N䭷"77xYft=㉏'&&W^yo/EQPgSKC"##>}׳Zq& S BU( Bg.9\BQFEEgS![ (RSX;XUV,R4buu #ڵE:Y$,s8v{$t pΚM(8juքSPP@Νyꩧhذ? =$4L6 %a(]k.(+þˎ})Y}E*&wanCC*`"/YT]~V8X󡇄毁H?p /gp_Om{Ҡ<$bR?ԅȐHVgƩ8r̟#hM(8jfɒ%;vbuVǽ%({Ć+^UN ri'ouW-gf"FVMtbmkZ%OzdQbCHOO[n\p̗3Lxj8^lE⭉!dܹbQ~Խ~9ij W^,XԹv6~LB)1c| #GTrb= f:E)ƕBQFwv>k]c "K\"^oZ5L&Q6dM3#*nM[GX\b>J-CoDZ0v3ӎYUWUӧ/zyYDkq:%)ᡇRRnFd62%Iѕg>EXiTI{ )Sȉ~kvA*K6o.{u=ZޭI]WF|=9)>TLED"8$\[oF…[7"P&Z3 'M1qe"taOT5-GڢFUc2K #,1KIX_5pO!Oqj*ąT#F$$qФP0? 7$f$n RM|p-p_!O!| w9cF{4+aO ?ԠD"ܕU'3 0 eC$'Ą3؞%gUFݻGy_3.Pc[3[MZ[NQrң8N׼EDb?(5& [¸q"1cX#-MJF6CBvIVp>LB9F1 E #f&cQVB(NEp,hoQ䔈sJ)9ZRQ"P5jP“ÉM̅1Dw&55V1׿୷`2hADGBJQJN=/ yZᦻC mZëgA[bl0ּC0aȭo$t2jaAdHmXY9+(n>7EՅ5n w!gU/غ6 #(+ݻŲ~}qfJY^5!\0 ׋(x 1EY%UE|=$}F >.HEꛎlХ~(;Rhijː!xJk6t_pup(|j dlᱴnК}n>nj)r.zW/cKrз# `C7=8XDY[{KA?}g]f'S@CwnvbjW-M|={O]D *غ&<#*ڟ#h]HlNQU84 Cj*,_.6.YnYUuƏO?UrQJqss-/()} MB}ѸXcMu鍊&3g©S_%Ю*z;s.ҍ&S@#)I?Լ9|-Hw|@, Ωڵ)B/}Z#Pf~-MB}&DQ#1A|]|*9d[n8K a_5)f  )$/:ᢣBK]|={7nB4WwY# ?AZG}VxXz@wLgFџ|ӥ@oZ/}A; sЊ":`P&8P,g5s[w߉UD*-z黳RBZ{Ih >\x#l&e| Q/-bkۨ-E@Mw:njC/}W!rh0@K8#V<}Z:O48G.S-W/}WQfJqaTIh,zJL߷O/@]t(^Zƍ3D/YevA8I *$4fXx@Lb*$+^EUhңB/Y9h$4baF0uj&_|ujqt^Eߥ^ͳdC?HИl gҞE&Awt([\KOvƄ{2;$4.^ G:%%b9CnQ F3fx@]nmMFmɰe[˽)8t4 /wgx8ruF4D6u;S9gO/f9hiB;S@ns-Fb_Q@7 t߹ݻC.z7*) MBcIX̙͚ iӴnU54 wSb'v˽)8t4 +$[Q6iݫq*s a#}[7h {~{?ܛgA~&bM7AI LJ f/ dݺDb5u{2;$46{Y֯u͛!4jт,<˽yVLqi񅄈EY`(1 rLp8?k0ۭۙ:$5˽i3c 1]f'S#MBcSS|iig643FiN&p;;Vr%<1toZ,2šGIhljoH0kH׵l1Bѭw5 tFz7QfNb ZHߛoBNlTm .n tHDo6=Gz7-QR&+>UTEDOڵlXMh;r 7 Tm&6BvAެRj'SAƦ?zK7C^^VwzMJl OHӽYN4 ;MpfIШp ?{j q*N:﫧{GT-RC 4 ;LbTQЫ$&b:TTbCcެ2%V-RC 4 5h RNT'f3\}^SweIK;7[Ofv}#h&${f&yzDm(<^7s{ʊv.#h&4W^VScCZD-_.]T\4IOLqiO㋊IӮz1x0lbE褨$#8ug<+!QA!&&.݄ :HsE|>=jd2>=edT=ݛfk2;=`P&6^7*7ZOݮ]"߳gs2h3+ڕ t7@ʤIxg<.MBcm|VTklrkۻW(e Koהo=ݛ)[#Gaa!IIIU&%ᡇD*xx R45>s <-{@h~*?ӦMc֭|嗬Z=A&5^vF~Jr!CqѢw-_.A_yAެ(o#Se˖̟?ϭZ|RROw~~>3f`ܹ̙3]vU|dF},55U7mc۷z;w:v1yѻ7VKBIҥ8pu6)<0K[7oU-nQQ^]oƍ̝;7x͆PeCvءqw߭w}U5jU`ذaM+j裊2d8\=Rg=Ͼ{&w~;)_sر7LEt1:gGVyNF{:v~v.Dž zʟ}A3 to垔Ai⋈U <08eg`q!Ͼ[L3]cF*U@4 =OÝwhۭY#޸껬,Jvk\j wA9بOMO/?T5c6àAbGεam9YN0{B k-ZșFE#$Oȿߩ%sr@j }ެA/'G@uO>)fTK[Y0B#"K]ȆGij/wZto&̑fT@iе:_ iiкX9Nm1sK=UVKہMKGI>&W|aaWbu p/xypѺAkܫJ[voZ,8K-(Z/H3 .;#~r;@7,\uZofEp9 $46}a:xe?ba +VmR;Gahڶ5 voVTr!GzAY,"a ~zȨ(Q;u5?XjvoVh9$46Mxu= FԎ͵y7 PNofŊvrIhlĉps'<ޤZZNy :*B9$MBrIhl}[gֲPDtۼyb?bu.,f -[SCAݛg:\4 M k_xxyy*ATp$O͛UmtqF߮*S#͡{b_B$46jw=7V+6MCv-Q@ެ[4 M3`ThD<\ƛjTVlsBI \wȠNJݛ)KX%0@Kh_B|1/ޣdUnj1CokYj{Bb5n0@KhUW q>z&MRqGi_TN#5n,vz7+fh`H&27%c IDAT߄-`;/\Ik3fQh5JvoZŧ#$ZC 4 ĈY&pJ>]FQD w(AtX4Q8uӵvoZBJpX  4 ]|fnf  +|ʝ,^ ;v@>"YJV^OѺcs *$46zYR]TtJ#>^Z{UhS%C*c6 vH$46z/, fFôi*\\%IIn[MԪCUƢTx9RRIhl_rg6uߟtZ?@l5aQk6^΅$fJ-hi=7hHwI!6ߟ@N;$DTTr8SwJ$46zGk`^_SR`68uʣ.<)Lfͼ|:Pk8D{NrC 4 3Dy)֯2/@(nqKH<]Ms-Zpj`H&c|qqbJd|L+/9oĉb`2hՠEz}eTIhlj n ~k7l(~qS 9O{~FThL!RM hi=wGPZ*L?ݯbc KK='i> ^6M(]`Gh MBcK +ŖYb/.3` aӦ:ϝ5KR5ɓ}lav,8L8KZFu )$46FG Ó'łtfffIu9&|e`֚WNw}WP#.ZH!> ^{ ƍ,huҾ}jU^<zkK%| (m!(=bH&1J|f<b˰au&==b$V<_?xy?P42lޯ+(7Ihl,f;`;jтݻW,Dvv~(vxAbT"YyY8J,)] MBccƍ_~4ZFbarHM P+JGzn,GBƨ $&kBϞb;ΜS[@;W/];q\JƉOLw}+(RnJ $46F}{XJ<+: ֵg"-/W2nعeF.|hݎ%G@igiٻw+Qڵb&1\v09HM69ʕ$57]T8ΐإIhl%ƍE#鐕՝Cʅxu̫2՘]usHKhݎT Jp )Ih>|Lb`>bV}i*RkCw}WP% )ІLqHs|Ub[׭Ӧ15t&ݎ%\Ԛ2; MBcUsgw>&QY‚$,+rIhl9*A.pO;}d&%6cczz]]7iK~Ru4 M0wVl={YyYVW}W>ib2Us$ f9bs oL-Rɡ+AZu4 M0wVl=zG5hRu4 M0wVl:œ6lK_&\9h){]v-ĉyǫrF`Μ9Z7s|gf@/ꀊtscĎjl6&)SЯ_?L&3gdĈ|Vj:'XXs5_,KCW}Adžꌠy޿?W\qE󲲲HNN --VusTEQ|Irssiڴ)}M򙬬,ymڵkٱc< >nA&$t``|'|,]T믿ȑ#n_3g hYn ߦDwf7$''WL~י:u*| ׷;p0@e_|ߴn,[ڴiuSŸɅ^Ȕ)Sغu+׺Ir饗2vXE <4@vvvjC tJJJE tFF)))H}|Mv;MQ_۷3e͛޽{nаaC@s)[._~%O<_}lٲE&N&MQ۶p9`6[qeaX2eMRe˖#hU),,d4lؐ2NuTe<󤤤ͧ~Jdd C=ꪫ8q"Z\qxZ7X-H$JqH$ɹhD")R%A… yg8p7x#NH}/y衇~4Ip"$DD")DS@K$N-H$:E D")DS@K$N-H$:E D")DS@K$N-H$:oyIENDB`mpmath-1.1.0/doc/source/plots/ber.py000066400000000000000000000003101340375245600173320ustar00rootroot00000000000000# Kelvin functions ber_n(x) and bei_n(x) on the real line for n=0,2 f0 = lambda x: ber(0,x) f1 = lambda x: bei(0,x) f2 = lambda x: ber(2,x) f3 = lambda x: bei(2,x) plot([f0,f1,f2,f3],[0,10],[-10,10]) mpmath-1.1.0/doc/source/plots/besseli.png000066400000000000000000000452351340375245600203630ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw|T wIQ@QA *^^ AA\@ "RD@K$!''1&${vd>dsvf6/μ(:D"1N@$Dr=z H$ Z"H LDbPdH$"D"%Ġ-H$E&hD"1(2AK$A Z"H LDbPdH$"D"%Ġ-H$E&hD"1(2AK$A Z"H LDbPdH$"D"%Ġ:Ao߾.]wD"C'hooo*UDzz:u;D"q+^Hi0`vءw(D6|oܸ1uEQ_>iii/____RiRzuCĢűtE1D,jMg{<7*۷[&I:iΓ;{;вvK=<5r9X/,-4+ kfZ$##l=cEQ*eʕѣG+_}U;SǨ?;Md}4u|fq]Kk.JTjvG>lck*S^zu=|p~ qaaaz)qmPN':`|&MWv+ //*Yy26 KBQCժw.\H+-Z@v{@ݺоl@:_ˉ!/.|=5T!\)tAST}k w(0x0xyiU~8h]iTXdVCŢw~!nxxDK"]ºP޿Kr g1e&}'N@Djn6?mWT ϋ *GY ZS]kѸdwY:w6QkoS'SS|U Ș2AKx>E}[j۸V4:O5m KXla-MBs Ο]n{bN(jg.Bz:?,b-MBs ޸R¦M}h5l: MYL)BoxxQكvS&hi+(*#^ڶoL5MgMδ儅<*toES. S&hiۺUW{jsƥKJ8D&4m5iRܧ*1%LIhn̮pxcԨW6E x@?+-ǟŔ Z,XZPt5nҦ˻ő T\ǔ ZloDb;^f7(˹_Wuz]!b%mOo&eS&hi[^l}}bҸNM {Z4}B=\=8m(y {] Zl>{^Æ7˻ ZL"#_vmуE ļ<>\EuvE t S&hi3[P̔;|Ym%V4B.g]@4yÞ+H+ tk=eU=S&hi+( Kް"m: oNɽO+ĞKݙ 6{*)4 ͍Ym$<~AiѢ剒w0d1^S M\ޭL$47fѷ`x,$<<l8Bܓϔ+OF}5=mWT I?)4 ͍]?$vLqBhtza+YY l:sˍ%p ]eC'肂o:ɘDs3[H33HaIJa ⻑OܪN t`q g̘b(I]vui38vnwAFHW Vuʹ[]ƿ}2Aa;Z*M+MBsct}[@TXhvO8;f7W,Wՠ!ڎyv|)[R&4 _~رc̙3 6pܹ8q˗fVZɓ'*42z?0L,Z 7L,`89x˄[GxP 趘Wt?Z/OfZ&!C8t!ҞcY3gPb`o߮L>cO>>H >T|N\`":v h[wj99 n>j:m1e&1M)nDG wh[vTlhG5׍\ϖc#ek >|tgBza-MBsc}S=$&C͚E֖g&40~izV_Tl6*)S1OU[aCxA'.p9XVXM-Z=*k%$~ lOHOLIhnp(C\7 oiM O)\Y} }S&hiCŊ7ucR0>]ߋR[|f<"Q+ԻGF^̥ݕ^,a-MBs?=,TɊrux㩧nw#[n:껲 ՆU%)4 ͍22Dvrap4tRlMR-p}H-PUTZUXL$47z HJQ~}'.0ox-alD+mCʍZ{Fñ}6 +P_S&hiefŒN\ >^ިT {طhm<^:t q߽a5L$47z;W}5sC~>< /_[f 0e&C_V|XT9/Odx//?J|N$P!nvmjQpzi2e2ד0e&C߼yb#S_J q 6--;&>?Z3@bxp{vL$47gG[o9y>'6)R8 z璝vL$47p2-[`^1wRߪN'SN4 m%R.u!A@ L$47ԗB EeEKBmmoi\ 9PuXU]g%LIhnܩo|1tCpmN\ >^lXX<-߮|k>K/e9{Í2AKܸK_NL.>w\8KZw-jjO\κ&]ju+HI&TZQXL$47ҷ`ƙiyyb]눯xU\YŪpW^rx]2AKܸC_NL&>m'/jZw-jiqg6R|uh*t)=9)4 ͍;}(KhQUg!jAula4 ͍ļgcԺkQCzϹqlM?!B<4L$47Z{11a)uhjݵ--'mKR. ?Z//6)4 ͍V`h(N^$#C o:d⪶eG]Fro]gh2AKh^o *;RR`h\qU>[NZ E koxi4LIhnзe l;yla N%\v$]U[%Q"sptl &3vX޾a4 ͍VxU t !!AhܩK޳ňEQtӟMaiv۷gܹIܨo8|uaÜH~9r rYzx)޾<α#Z' 9T n Ϧ0l` 8nݺ]w\FM}YYW9ӡ) i絭=d5D՝ZhϦ0t6l6mbϟgYUVpɢ0;uabXttjכ6¥KЯ_8]8yi8 X&OEC6L$qE"g|Pj׽=>EDDffΜIZZFKQ@;͛7qF`֬YE3f |~I A|<4i"F'Nta0r$ ۶]DEԪPIQz;xe>JUhVMjݍraǠ ^Y0 =yO-}o%8^yŅ(W w8=y*h[1螜.wKoӟMa!&QCߞ=WPy!q9.G2<2O ӟMa-MBs㪾|?^|.,JQ:U|0^Qm+ >3[BqhO{{ @Wqz^>Ϧ0e&qVkĥ~-Su*aH֜\Cy#Yly6⿉NjO,}l S&hig_9w.M']ثmξ9wzrT%9*T\gh2AK876V=}psjS`أ-#7¿ǟ:=KWyi4LIhn_0gj.r%8:u*cŇƣfp "|6)[R(WBK}?FÔ Z}bγR5eWWLʼ6bcxΗT3cϦ0e&qDߜ9!J>7k8{Se`qJ39|{p{5l6ƃ7[xi4LIhnwꔘ 8U9+ {O|v߷V>+><_ra6+=4L$47fgûBW͞-ߍ Kv$[/lAH7Y 7_ oWۮ{i4LIhn?t*DRŋNi Ǟ'1\ $Lr[9X?FC… عsKJߞ=b\p0,]:?}Vrѐ%f%o fc5^⿎j=] /_ SO6ĉ;w.UTEOr1!MBsSLxq1]OJlNcPܰmyZs{X*-F8cϦp{uiӦTu̇`^34J7y2;>ch.u5s\ f흅y 6_8} W9/\(K( +M̍22g&^׷R?IߝNP *plO6.&aϞ=9wIhnnԧ(¿KL_Z% "h/FmsKRvyU-҈ @a9gp(rPq3ǏW,rE塇r'|R$14i(*\03SQݲE :FnRj׻^ʉq-ّvʮK]z#00ڵkl2/ &'sQFʗW|11KZm_DK"~U14p(V.v[Ϧp{~Xd O&&&۷3ydo5Ihn %'ða}wީϜ3Ĵ:K9N6K/xn8 2 ^^GϦpIظqc|}}?>YYYiӆ7|PV24 N-Za(*\XQDw)yʳiLIh|EѽvE;CB\]]^w޺RHlM7ԗ:/{x6̈́)4 "zΉiu3g^Re}&'T6t%P|u=0m55 ŪPwr]|+g5E_Y ZjcAnb.[^ f`hCQ^?T,Wm}>% Vz`gӌ2AKИ( L 57i}))mTvl7Ywj;vЪZ+4` Ūr՝e}e S&hi?svU?,,Mqqȷ0 |E"Իr"s_o/a][]z+kz֭[Yl4nܘ7Ih<>XlWX7ҰauJd!6kԏ{\wE}R6) Jz뭯at>}X`-bEǥIh,f΄_57nNJ 6{; /fqݾ~z]NTKK|Ϧ1t.dѢE ^|QT[uԧ(sbZqIIe¦ |3Rps41~JDLI~Eß8jr߹kRߢExE*(S~B|f>w]7dˢRJTMOƔ Z$t/D[_]tppw-/|Iՠ?V.u3_7O+lz:Lr%ȀA0ص ǵkb]wv#-ezQBtրYT Zv13cȋϣcթع[ig,`h$IĴukشI$iW)QK/b] Lc:'_~j3wWQ4^^4-~vu]"TZZh(8I^Ih@mĜ?ÇʕеvkѢ{^@QY 9Ls"wԹál܋\x^>^4 /o&{1eZOбH={BxF?{Z2w\6@ЦL=lbͰ69ݧ4I^LI:V+55Uj۲jtp}*Tb=]>+/`ǓVm1ĕW4 MBb!`iv$5JΨPA>\]X //t)ՏSô>TmgX9iOy ;ٔ\){$t_Drn ˍ9>&:;Mwϭpaz5kw_hȉ̡ЪTTJF&{1e&ddqAt4<'4o'5UIPm~>3P ]j]ֱ,bfCMT3Hн2AK1~ ڴ/U'w.bÇ_?_x.g]f̚1|5+*\RͶ8Ii@@], iSAK>237O|Cؾ[tWm3(<)xó m9kiEE_TZ l($t/AUomErR/=g&¹Λ6 3 80Ѿ 6H*͙5`*TK[4FC˥-5_Fi)4 K&=]S .\㢊[QVAJ]Fӑ#˫y)_^몡 O |քޢFh)8Ix3V+,\o /\0rNý#ի/@:EhJNf!Zstޟjh;Yr.PuXUjBTwە5Lك&l&΍'OIyD<{X)X97mzݷ4 l\9)yCU襁Չ/ǿ?Ϳl]RAŔ=hi Ξ֬_u6^&M%6lozF[^Ҧz=H芶Kz-1_4 ݋){e$LMW_ M֬ :'kaXu6JK/iɡ%;P>ܷ֩YmMS')H.΄:/&{1e.&"F63|'NP׿WVWV a4q +7>jER~I!eo +G&{1GY3 ҄6k$&DySi42l0.e\O1 Qmiv [mH+h:Hн&aQ6@cDP}duM1ؕ}pLnFGÏ?ªUkQ7h1+;K^Xb(#1;il{zs6%o%=7ń;NWi;9RK%]0Ϳ6^ {0ԳY0e6I ׋} S л; DGGco|r2 6,jˈ~$d%\x{]QJUcG5u lL6 ss~~۷{7\~F"!.fgx;8o_Ec/Mf.v^.^`m#3p=%JSxyjE+u,C2A$Ȁpo{Oȕ*X{}N&pl6lqtBfxUoĬD۟ רK.[ߞڒIA߶r/#Nϱ]2)V&a^:%fS9r52@гHکֹt4b,xqhՁq5ewi_'wެskNУ( 7w7 29C'X~m=ʾ};k*(ŖPG|㥽qc+]$6mM7+ @?g]M%}8|ʇWgm eGYl41uB&{1t c… x\,"" ;[|\kET~6_$_5kۺV:ٍۍMD9)I/ziV#\w.&:-a- s.$::z>80W=SذiC'غ M@bvEk˖bUՏ /61# R9mkV8D ,C\fyCmGapC" /!MjSwZ/drv/\IX :v\wgU<<s^0iR8s'd $%'Y_С<Ԩq SDJ'Oc=}z$R%NΞe4(WNs5tߝ8T’!K8{nmTܱ4߳QXu/XO6#ħƱ0u,""5k0sL0T JVV2~x^z?*(O>%4TQ@Q:wVTvERB(2ajM(S6kbc}xAAA̛7F_I*1b ݌It::ɳ]oa rɉ! Zh)8%$t/|Pm4)% 35kZnN`>bmocY/wsFDwGCǪQrYnԽ]z$ՍuD%QdrNJ_v~6c֎aűT,W`@n~RwrdVX&+HнmrZIT+sJO=Yql C=LI8<0t+ i@DrrhmrΠj D-KD毾{@)I<ĤЭn7֌\CݭI6cNXnBī<}3Ai`h4H$'K% x}+அw趣V%gEQ͉Ori3v& S&hiʕbw߉8?:Z}| ֏cʑdeaɐ%59?<ށm]y)8Ix "A+ˇi}]e(L΃u_KS4:O7<]0e. &aaT$?_Tk컸GV>… ԯZ@׺]& 2 85+Ti_-gO_i-vR&MBMlCլ>| Y<9[k]\H@*9AC&Sn?+ h@=N&3A9pnx%ؿ_|bqq?g|[m˵q ̈Ju9u7\>B=9azw291SKZp۪N&3A{Iز%l^O P"\~<#/nzK eFi?lI*|Å/+Ţs~Qi3Lk* \WPAnIlz,/n|0(> _?k)D9Eti<1u^r##hOg4+3 ֯acb'N#9ߚ콳iEK֞ZKÐlo}{Sr}ξ|m; *1#aTD&3A{I(y368ֹ3->76;)6V_ɿ7gw=&ȯ^FbU[Dž_ ?1 >4xu&QhhmzPQ_7pHη.zIxzGxK~w~u'#WlY4@pVjrMiqN;M~b>53wR|&3A$ܾ]]|ݶ-l08dʯS|n3kudzid]rcs99.]*&T\Q{ S&hS!o[yذffш9rGIhCrxS8"GcO鍨1; S&hS{;/5w߅#뢣 3w<83d顥Qxg:={O1dZWo}^}WqH!@p`jEѫl 'IDAT5fًhh]L‚XJ$Uj 0~ `Yr~ -?kT1OQBmUYҗ-{ySslMjM WOO^h2A$LO;̞ QQX6b|GfZF̉,>r) fc< ƴCװ$qeW%-Ūo%?ny>a'bW2E/Dbe{p@Q'fݩu9h&^oܟ10 a D吸:+G_u? Fͱ5 [.OO^h2Akffdep8O=%ڏςcFL5;XwzN+мJsƴ趣 Uv( ٧^Mֆ,2g}\X9JըtW[njTaI? z˅att4nHMgwnvFdgNŪX  `ov?5k2PrB.;sPmx5ʷ)IZ<=yy>aIraOuk1ch Q'Hmodf3z';"wM}z j6ӷQ[ [ 3HQ|Bб!=CB+Kxx8 6%ft S&hMt[?b՟N=9EQMeOvFdG^>z{jWM=^;we"r2:EL2eb9aA)P|#  S&hLBE[ᇫ6mDR5l%P!_>,^ro@Ϧ=^O$F-!+ S$\nz ʷ+Op`B)9!߈'M <_0e.$LO_~ cAA0v[{ˊp1"q(A$C 8t :DZ^;Ի,B^\ɉA.Njɸ]pчM^x S&LBE {8޶޲ʫ-RLB"S#>&W 2\h[mk*M U*'%|rcsoJ99(JOP % Oh6A[,y*VHʕU/-MϿ<~kFNK[[. Uh܆k}*_ZAWJE5ފ kTK*YX-VYVluV[ Ɍ(;țzU}"OP񻸸v$66޽{P~}bbbtbx.?南 x{BrÏпiE>'ky+uIϫW^rsso& &uEn݈nݺESZ)|\c@G~ ,IKK|b09iiilڴI04gKKK+9_|YhKQ@;³>KHH*T`ڴiz$H$nŰ 8J3=X~m=ʾ}GUnʲe(((qƼz*/$7700h zow8}vLwͨQ -{)4͛GJJ ѷ>DpB}a,Z۷oߞspB٣w80c MJHOON:zStll,aalfq(1-bz WftMPTgǎTZM&tޝ͛7_;NJЅ!pq(1>| '& 6M6~}Ԁ_~cǎ1g6lsI6NZ4,xygٵk!!!E<ɓ9~8?Own9o;w.}_dΜ9z*7ofƍѬY3ʗ/wH2uT@O9Xj[l!++ѣGN2 %,aD"HC&hD"1(2AK<_~HFܢDb@dx$}LJ/> dx,/^RJX K$&C&hG2|t7|ɓ&M"1rD"كH$"D"%Ġ-H$E&hD"1(2AK$A Z"H LDbPdH$"D"%Ġ-H$MIIJIENDB`mpmath-1.1.0/doc/source/plots/besseli.py000066400000000000000000000003211340375245600202120ustar00rootroot00000000000000# Modified Bessel function I_n(x) on the real line for n=0,1,2,3 i0 = lambda x: besseli(0,x) i1 = lambda x: besseli(1,x) i2 = lambda x: besseli(2,x) i3 = lambda x: besseli(3,x) plot([i0,i1,i2,i3],[0,5],[0,5]) mpmath-1.1.0/doc/source/plots/besseli_c.png000066400000000000000000001044271340375245600206640ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxmmy{j9vnc;qW&(xgĘK,A`)H틕|p$&F@"AH q2Clw{{g>TժU^9]OwݪzV>YjV[mV{] ozjjjVЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS[j:ЫjS|wj_AkKcfؿ~W_zj٪+?[TzKcf++?ȏ{a~W~oo"i8sݧp]u[R޴uзr{h'ܿh7ڃ`֥}gw8VZyPD5+/J.r-7@О+gw}OlٸO"`D}գkʓO"$IK9%}~w$m7v2'ԇ~_{OMl(>G9_gU{{ˇ>!~/~ 󷽓?=ߛߎnrZڅ+u77}}Z-[e~6^6?~۷^zm:ک+wNmѮCA*Nt`I(*ao{~q8883©;;# l q@7lyc+ Nb1r[w> Rk ?\2n_Ȓ?>翏`[),J%N,mk++MM@ \"oXkmj:åDɸuڤͤ0N Y7AZe 'svz#mhQ-õZq0#M MN\ O p*/%SLQc"`\6o$-j|i$k1: ~YZPW:K =x oytl#%^FT+_h[;OؼwmY=-t]G6iwj܊͉)ʉ #H *ډ}Ya"ą t x Y=5X p΃O|jc`H|pJsȷ7ѡh=SOݙЋMx;"(k \ έmo}"cܗChG\HؼI+{!=^O >oA-m:]m&>vJkV  ]rm_JT@]OmAԖ'Ko^|SVNyqh/>Vg )8P)bS> ^F4z%tk!큳ЍX8osE9!;\9쎖 Є|=x 7雨xHW%2K6֪{[J  a!KcEN+YYFǝVҧVVq:X%nhhʣgǎڣa'](LJ {&)4s-mSj2O)\Y0Sq\| vD-D?𫭀^lihͭπ@VgփRU6xPRs)d,oᖌگ,;mpG^;ek_{g. s)t{"8;!GQJ` C87\Ж.&{"ŝ80aOsHt ?V@/XASk9~uZ&^)o[{/>P>Vc :u>C@/;= vp s!4cׁɔs5+NVECt"q[ }}cc%^I~lsmb3ؙ 3KNw|!įUP 5.jV"tmǡkJ {RG Bsasy;Pq*a@'I}I. >;"CmΏd V@/6k>JJa[1z'# s %-bo8O!tp&S/}8٫Eޫc22p| [8)lcpЮƴkЎ5I#*B>V^c8z[ ᰍ:Nq)5Apɧ}KK{+ ^<xhe )ooA7s*V~ WG kmܟ0]2P 4>oLXAi#V&SR(KsM^J T\TeUAz [rB>>ˮ+#f_NuE4ԅ;hB؉ZG-8 نa/㽽D. Р ;v_7ɖh va#/cx {=[Tz a\R7C͊uo:1!7.oi񲲡+}kʺ&~UHK} wGFUAz :i@ j%0_: Y5UhiقVaN0r~Z \up%pi#UEWɣᎥ'Gᔍ<%9@z_& {U@]hjl2ܹr!&|EDY.V Ŗ)PI@cܖ<X;3C5{cv%(KҔy[,^1*A*X=?2k^mW`w%G4s$: uxPsqADd$cw=#Eƍo"__wIb\um :ЋM@s`v{S`I_쁀+933/~Ze8A)f:ħ#p^BégPBQh΅gұ.c"1eKÆFNhp+ y`H|p]$>_3'W KdctfAep`F]?YY\MkB^j tK0K>/?"ʸ43.HU-3,1X({^BJʅ9. r#8m3 'tlPaa|ZY#{ݙAE?Ii 䀭@Ztp5nPQ99)D 妸GudJ.Sh iK*f(Ū ېt+QY !0ǥK1sG;™g('6m-;6.-$tM=GlS a, ='xddTv5X7 j/zߤ"kqYvs 'wjGp1$cЗ.@Ρg"P6hbq{p8Ɇ-AG Z :?l$sXG1hIUHfګ +)  `\SyCF@]Rzş8PKPǕ W.Ŋp[h}t -wp Y#(hHBYbhԠL&{0%&njz `bEW8 8w'Eqޖϰs`\PZZVpF_:>-T;CaNNAkD,j}caаa#ۨ] "pFb`ˠX>|p|vPÌgY}/=1*ho++Wxy_k5PWC#0A<2.Vj~Q k!~pAWgtaش΁F]-`GVҧ ZrfD}% x |Oz<Ϭ򪠽?_ o}[yӛr=뤎TQ@^ǜ8ޥ2˭ehK:c eɧ􍗫>6M=z pm#kn3FOa:r_ t|kb$+%KJE2a|]Y}g@/{%u='[W;E%]|z F䫌kTPUI9GP5O8&u>6 JX҉s 'iW 4YŶ$q ^t8 腖( c%ZB\ ˕rn11ch/YpiQ1ָ}P7Y#dh3d+˥\C.QHD(F yIAvƦw/ `+ZIAyA%PVԃrgn{үLVp=l𥒴<+)\[8rTA9D/(i8ݱnTQѽ {ʖD"d֒'A.Sv q[r@Cn%Nx۩w1d6A/ԳѢ41kPJ8Ҋ&>FއHLj~xo?WE$XsC!SJ{#it M7٦p'o|Uf}(uo\* o(I7}>lrD+\WұǰwIf'o?9d< _HG 0( ijXcTQ+ӱJ=Nk# VRժ$Sj7붰 0Q ./(!>fMB2~[ o/:U6::UZ:BH¥ic85pO J3Q m T,U&m:h0c\v}IEρw+WlB)1-ttArcx9T)*%uϹѼNΟC>~gXvT8ұE1t+ Fiml$G|r02xEyܯ1@o<]{H6;8緞_ Y *`+ZP^9?+^b2/7hnsd ҉/je&+$خ n] '⎽Ј?  W(b8 t[D`gm88AvH\%Gz8dh;ʻuv^G'u~|Htdtl+_R#OYE@g1I1D\@p![򜶒պ=f4nvrpEG#B@9.NSAN5D IDATt}\&(w] 0c_QיPHh =v~=zη)U\"}y6PP}^m-v>]nX:)C6Tt)|Ɣ䖒R#T6[:'l9a \6 M;8APEzQLJZ(zgm| }<|Q#>sXՀ0,oJ-/Uƾ=iH @Q%0 د~A^ymAC{WjH鎖3vzƉ׊qpQ rfSEvNE(hCC|o1IaL@4J y `qғ Q 1;||y{/;R:NToN}Ÿ7Jy.%0}?1K~_sς.p4)W-'zz~#<ӊ<)pWଃS>X))?g~TqNO-QsзxlXtd+G~#|%z 7U Mrq</<ݶtvбNrarķ֞V@W_[^x ^AuUq7Xwxw s9+ B^< d2T7O N7t8rA_c!tK[6rCO\xOUϒB%A:w9X}^?@#9>&k+m*V@W|K_QyVK Acj}QW^gV>ܧ_B=|jV@WoͿ X%ݿ'x 1\jAVs<nD9 [T(KT/̟C9,Xw>T݂I {.;~?7"w]$siE1S4}f =RS.E%=6F~WfUڧg_;^_(Y[=aηG()\RM sCc@rǔ+6T!673,cVSy( O< wތރ]؞̂1^-qOAUt\Yz Cȋu)o;SW[ܔ0c:L!+nЎT4mX%pM#)d!B9sxASqH禸Q; nD1QO+go77/']!4{<4wAs E{[<%#@}s{@dp.J7Wkh{޶Ơ{[ؼ^78/w1t=28rȉ.@Z<c{_X74F1;0'`N掲'ڷB&7ߤݝ"+\sD@NS€[-4)I%XKTmW{&X{ķ*V@/1] m 8Vs%R+j.A6uW;9Vlqe gnz tOۧy{xZ:2l6H@l2 g 'npΈIv)QWWB'$ܗis^MU## :Ћs?ɧ<1c {D!eGEV:hxCB^D=zIFl)gKN0j]EO*lO' +@#sك9u>Az8ǐ`N BqM[xbqz1Nꓑ4fjms3NE?ƶzt c)8pƑ1ڵ]Nwr\mKB"eHOk--1^9{;>3஠O(*B8xB50[cn60}rp n dz ?#\RI|BDi6{p:;,|V@/qPҕEAs6o{x@|_Wa4Σ];W=d}ݕ$KLR!lAsbOة='aQz4摍#7Ż jmԳW<χwHP$1qu{⼝?Y{G|2}-6mR`K"s##\~d=<Ǣ,W*9KD}>sTM.!:kx@. 6ULҝ^hnK> 7tMcW3i {Db5CQCU"\{ȽB@--!j|ڿ?⏭^jBxhR|0]`qˤk%v+ezvBNqõ:N΀3 Q?\V57ʅ@Mߘ"]cO@^9xsHoEL9Cu HVSkV@/5CKAcu>s _/uL'S8uZD)veU's"p)8pTްFl,{t9j1хyƂ q8] 8%G:T5U-E A>y~"]چ|K}:Vz nPJT]7^Ƚʾzpve$$р4nGS NA''B(ڹϝ{vW`+v]S>PE?=-Ez37UaPө9_+s~1rrSD>he5k+Z.GoUƙjZk~/72QJ/F fp;ucAmx){_h~l;cѭHΥ9pQZs08ثgXMG>;uԒs17=Ⱦn mƼKVmR:>اrź~ mUpbnT镴C'ut((ڇ=*Zz@QavJ:R] q8ǤKqXMbRh2q첊%_c*ho+ZMA9ȓ6Lc-MO-b&Wp`qTI0isl> v9@wF71.E= Uˑ(*a6!rP".!AAK2'+RLQ uH/Q sH;^jv&}zB?s"bg 49JoaT3Ijr3#]Wq|x-肟DSҥ,I9ARx~,` zV@/R#KZZkcwpr/d8Z{Nij }M ,v(6Nbs J\x n 1?FldުE9тalU$rs0[+=0%dv y4zYZKGa9@.m?*u]nŋ~5+ <&>"*C90+"QXH;qggpǠ ş塔VZZiĠrt!SE+uPgu-"s@^We_ܫz Qd\:Xw*٬xrKc>\](lA,vVBg_НH},'n-:ZK~pCpt!;еy5@B c9)\Že8Ztj+Z(gvmr >`Ɖo_$/MB<:Al,U5%q={tN%c7%W|$Z:`l}Q] d&}Aqj(d4:u^OQpVmRC0Ӂ@5nxE>J۹T_IRQO*Y=Y{ly_X4}@8^IkPv hc@7hK5=. Ip>u\ [/'82B{UV@/5m2_%zsۣJI ъд$@ =b_yլؿxNiFh]c=jUe0G"`F%M  ӏ%=5" ~i8Dc% =mp mRh' }w~' {~~s,d\XP|qۜJ%r9}wH:891ԃ?^ۛ)[_'ymSYSSI= u@7dP+X*TYJ$A/֕TsI=w)vca_1ϬP)zFH-g!CKZ硘>M><6mVz_}>x']]o V:Ғ<%\,ck{,=cR)O8ͣ%y7I_[56^up9_}fmt>~pWO%*8.`ZMw)1$`usc|[ eQkRa=si7 9Uu7qkmsDj+[MOi>i` Ǎ=x㶩mI怙(/Y%R1^ h)r_=XZ^z)u@\[W3/58LQ0nޯgCD+] &p)|?sw~65j+ۘ^xsöz"O5ڞr!e]AD h9PU v#5y x:}Hk$dR 㻚 îK\I{N/sVg+0sţ#%ޤo M-m-aGT;EHGzю:u*vKXj&8lU8NvlZ0hE'Y N5feM, ,V3ֶT^ 棡o 훂;pXJ3%*;k A1J:(lhuQ;ڮ ڽVh7X8#q#Jbss|@H|׿|c5g+`/9 %&I:ZP:lӱOGt{ ԽtPm|zZTwb'4ZNN.VѠ(V'yNgPږnV?o)k{[4 AM/}x ܑAMsK{=]]þm*jɭ/o6!‰8@wP tGn:1Q2pf-7g쥀maF[ ЋMzWkPMT(%wXs hfb|Bu mP5\ui:tvFQoVq cN9 zMЃGkݣ[hF1`Q?ktlJp_o,|w{ꊟÇo{#)91sS}f*sNS}J6jX`4z;@m3hW9;iz>0GQJw)[Ktn~ҵ?jUKwm?_*ް!?㜞|滿]w`d-s7xwIRХ͓PGO>ıGuzz AZ/l펜0tتОWFMGE[C^A`@wOk`}ݵUs{gggC-4A\ٿ9kMݤosi>-(4)h38|nvnx>R-AK}\r <Rs8 SO7j-_%Mxsf[tooX@]''.oaT eyϗE"DkO2qI:H1&Hxe<[oi3<Ï^{g}|3g>ó> W(̋yY `a21dؖ?PnKy֘DoW_6K(?_7ɦ+B |gS lg12"#vQgJ5PSFK tUČs-HѨ)Iݚ܎Dڸ|ݽ$zRAV]3k$}ك7F,g?K#V4{O|???{|_k~i{||}-q}Iai%cNQ eƱtaA;8ss<0W3zЙ™7l `=8kwӹ`6Smܒ*QOwr-yᣟd?~>)>]k;wS?Spo.l[dmN@9Gj>|/A9_ ras<4 |I9{MxZvvhy'l4<9+Hp/\o k@oI:x:Vn~~{!"7ۙb9}s)vlKEo{̏ нWذƅ#5J_Ҽ,< gTWᄆ;4HH{J+A/Ć6)A^iWQxBNN3\`BjI^?Q*$́{7w lK%`ΏYW/oT)&x xFX(%}V5r!/h|(nS}¹# 쮄DjGQgeˆ ^E{%mwH??6ԠD^KbV9)[ _eqn>hMA,Xv)@o;,f'0'P., ^&z/pi E/,50pq ic8-  ; c*vEp_@6L)ֹwXXFO)cߪa??o`%\$,AqKRҵ.U9'$^E;H$R4pr'GB=!VJZ<X1l`F(k Do >7UAxe5x=yf`e3༮j5 x!aH9K"vǢ(A`߬^A_ p&p)ebPġ0DزaaUNA;?n'y<:)wlܥW_KM?m97gJ)O)bh6$w'*4 ')Υ o_ B 6FjhoZ}}=JKyDK:&V@/56o :,NAx ʝ0J֠WRS٭M 5lQvbi q]W{-m A$z 15p AsK!;yyUV@/5% q}k91.US lUu9 yC?HE.(iiFaE;v 'XhFIAwЫAllE0}U4= m>6!5Ʈ긤WmRa TzO)]Ǖm;6[ )g@@5@. l0l"vjq Yw9ChG [ ,/ǹcBkߦJ4뤰O t*9A7XV@/4=hcъ/{ΧQ:4*wԾuQK::7s@,҆93~{R/To`+oP6H]=q kd0a>s668ϻ/E׃7ӰO9|2l;MAtbcE7[ЄypLƘ %u^2`_\xt dQqp~`Diz ye}@l`4 PN>:l8%O`B%*]򚯇+^h%Rtt>׉`PԿq&@&Wֱ%SO_͠Y\x9$\$<Ŀ}eF3\|IRVt j~<ؿլ^hBxdl s-h!~K!ġ2)SŠ_X@NbߌyLh_uAsl-W@[4Sm5(Sh+QD FzޯP7v amX]3)b8K24nņk<RK幫dpjY1IUNuCd/o[Є:rRyj@y ĩCu s =Dhz :=~ʜggvXȼ5xsm̿~%uc} `+ژSAc'C%1>Isըi>>I]'sy2F4OmGl+ /~s>nG%(_|lJ0k?[{)/ɋV{MBj&@|}o2V-.6~'~⥗^ C&> 2b 4}Y+^^ g}uP[KC9ó`5ߜǵyheTe^FڦiU{@ӟ?>}}xAg@s]jkYD !<6=Kv!5)ͨeF4yKM+=(+DVU3!=1OcD\S1dn=w}l_%~gOI>ɟC^x>/>sc sϩܪ@C2\m/WQ 3Kz~2:k>K׽)>=aIK|/!=`5k=Kkk|y_K|7~#O߽mO,B]V۾$Ny yۜ z.0*rpV% >?Mc?>k{Vkaq٪fOc`9F_vԿ_+ګ8*nKhbXh\H!z8jگ)8'N /_od%u;n"*5*z &ɀI2Vor,%u7Vr$+.?: amLfu-}k_qOpaoi|\KqJ ]RV=ȖӶ5I7ge+Q)u@Vy+1j1V"_K!ߺX z J%u@w67'ӫQPHD@$M&&%FFطiZ+s/Jhω~;޿VtHsc m==>T]d=J-7.H0,@7jaO ca i@P=(F*t~(wqJeqya\}8a }d$Q >u(^to+[YB}&udL?f?n[R&hM41oVbc"MlG ƚ#@h)F-M?j G_mķFZ"+s93sf}}`랫5s~|k̬:Oϙ*TԮl.o P/ߨ0QQ0uB3΅, | s`. :tDYX/1KjhfsDLpQ70W:Q΄-4x[}ï.U7=9@s ] ]F:M> :%% M> O5>+;'[)GN7c~j&dg`s 4RX` oزvٵF 肴1nEouS>d%3ͅ8-sLYU`\QҺTs*;)Sox_?7$1cK*J[ASVAmQ0S@cA'L6l_9rƘg80ڰze Y? /ǽ ܃mڶ =CZ7u㸾[pְ QSo}8d&1 T[ ]Tu/?s.3 T,G:Q*L1Pv`aM]>N0Ra\,@{2$S~`׷TzD}:ڧo\{O)?^[dI4yJ@U}XP556uĘ)#;YE6Шh] fRQ PL tjU`Ve30đ8)Y]jxUr@_nV]*d\@yS7朩pFuu) Zr!msTt2`”S8mws hf"6+S guJ:ޠgN951D=;{bKt@u)1|>]cV'͆_|8U1ΆzC U(S 76 ]vA&!F9#,'YJ igm>ˆTgiZ 9Q-Qy qlڦ4>rC>v<@m-SViOE~x=AP1bꂂM&؞oE]xège1.-m 6 upt&ԡxz_nŚZP^5G?/*5kl+U}iW6Q\_hfwtܿ[t"8{e[)h3 c &)S*HS2fUj@ρ]-إ`>Al lU !քIKAUn)e:r=z6>e 2AA6zmSB@*hp)_`XHkPt=O1`t*1 >I}˃m&6)qA BC+}ggs3(Ŷ}Gj(1i7s ZvSS *6tAbc(I%0v)) -KF خLcK`jTtJAS5YGE5tlUj8i:XjUj8ʊN.D m&z'YamPn畅T&ivb׸JZ} ~ăvFCV YT:dNɂ1Ba! #W ^">mA٬`CB]4[Y#3~؋*g _Pn8:`6ѣ[5׷UGe׵SBr8 aPxi6Ufj UeZ!`}xueTkxmژ?8DxiB3H8d$ݥdΒ AxI c2A. کg1S frs, h_ᬱrBꕻ[QR=[?/"Z6WZS|ݿtKMA?//S>wlea_+v6w )-NpPԀZ7)a.KD( 80\\!җBiv:fp ׾=(+0 lr}nioV*O[%4 ?r|O@k9.{l/Re¿ni_ qWe~%^  ܌5J䰠fêXp1zeR+SV; rƋ?zaEjw *OA?LɇP|Z}}}\sB@k&|~XKi/s˯a=_ VY-LY+57 @udCc*K6Y63=Bwq9/Wn"ބ?BU , UoK7Bp^l 8 9~93L@lWA+32uG]{ec6窪ts!&ڗM]ZQղjC&Z2B1%le}@1%%lVl0-( bHC Rǖ72PoƅO7/O7 AA;aGxGx衇SаЮO*Kmg]QX;u}J,# ບPkUN{?Ve_ȫ^/%9G60d z0S>`BKi(.J: IDATk\q>(hg3}׾<#aSА*߹@:nKBV:+W%!W7W־s `yr:v=9t>φ,pK@\wS`]pG@i'ѫ`auB'0-eW S̋ xqtj$v-MDgq*:.U>s؁0< k5\DvU@͟K ^yVg뫬>ͲNʛ&Zz+Hz}Że[X_Uے)qW[]ʙuؙ22~΁Y%E)# 7 (;TR46qhĠP=` k}.|EmcKWP Tj <kZ]n:JS%_tL=U/e}@]}xvΗR98W҈6i-z Yy!R9;Q!beMQT̋9,dN=H(zԬ+yYN57T>k,, ~kץoiMnZ(Rػj8t~T)ᖱq[qq9"^ PAOBO%R Pf@&xB2`Vn% B U-40omOĨhg!X,/xg&o뛂kBm4od17 a9Voj!Bq_7dk[#Yn Fr43Z}Ž-A_] elHls7جѤzjJUxQ0y^ B4pYLaFRRcbAۚ$rԅZu,L}"Co }T0kZJA}}q\M#?׷#hG~%("0X #z/^Y[ib,0/`Y}aQ0Є9~naR+0m_(xxM^xmȎ,dq;8j VAAm+:݉sz_m>s@ﺂɅ$\gi)MZtcfi,Մ@݀ۨcKR1.yw;] \a]{@9újCy0Ê8'o0c4Ũ7W^ Pi}5S-R@j*t&n}X/Ք^[ X 7 =r+9<`MRIݧx`׼v [tN36zM)U]}95CRȗ|WЮ\+(K-@c ;bJ~$~ITN)xSql<.?^[vnwAq< ^B }@m]~ 뺇w5>Uy4 py@!v1QirUpF @ƠkǁS퓤/Λisy 2·-﫟O!`׶nq=y<$Gr $qsR i\ܤ)ǟa.nk& aΩ#wO}ñkq>8/P`6_A s*h˱@}n кT;mG61[V%WQT Z<_l)xbTة _w s^ NlO{l!5M >HW8}`YHwզyߕVbxqYPȉ4Ҕ??fZaRvDWunbw=Iō6m$5W(uZui[hU=>ok8HX;ӀESk9KRt9r0CCRȱ"N7Z*, /mBawksAA76zM0SqڟZ ©vwA?g}jC)7A=6_NZ ¶Հr0V\+a j2__[wĎ䃲c{3f֨\|/>WЍ ^̯Db&0UFvPTmw6PM_46+m恴50K/=f³jaQ[Vlo*umXa5/ a\!᧳V}@h~,a{}MhTQM=ye!rVQQ*^[{C L@ DL^M gE8T6o6*cԵy-܇s;H7˦>|%NY%,O}2P/Z0jwmxM_6P9^nztm׶9l0ZϚܼۦ5Bʒ,u*kȗu)-kk}E($kuL+ձY!Vڄڀ)b7UwvY~+5'ҔǪUlr veѭ WqXo>kK[}l=*Hm+5y*ZaSrO m2Q^MB 8u +!9 u__Z]wF"FS Oըjwq E';l(G4x#$٨.|vg']E觞z;3p lnnr}r?W+^}>Vm_;S~H$U=1nK%hhHƆԛZnJXEnP FAW0-`Sa`Ɯw. JkAAQ3%>%ϱuPО]ky衇O??x''_⑿"\}Z>U<:|]p^5B gC!1}h.% dY-iŤ98Wv QQm>`_(Q?2) 7-R,*'m-tܱiț\B8\غnv}3}Y8y4C?|7׆˿ !,T@u~vrbQpG3pPF 9KSeU[3R5% T+Fb]Flb sJOԻ\|qŠܭމr1Nȃ1yGW15@ܗnEcdʩzΗuJPaN(6`b00Vg5 T s:CZyaNj,6,&!mZ,b%+\XIĬm0G8&Ą<]T̖s^Z0c" a)ANCTs;XMWGT:Yv"ՠe> BֹdF P}_|ch |`tc`2 ^ߔФ^/dڒ]kJ |3zOQքeѨkЉABM^ρcjզIREɩ1,UX|_A^RdG̋)svs'^X8rA+P|X[9ڼ{M" <>붌0V j|0O> ^|CӇpЫa}uB ܵOc붔*/VjzPnCV[Pm yavB|2R-dPIZ1{`P s9+SqSM^6򑃲]oOFT}[43ozϗ)r'39X7_A) າqnw&~s>r rlm5ri~^.ͨ.T ]\n_߯cϳK0 7YU4&䠡Bc"#TGH\˅&,#rpNeB8[_ZJArMiTyf9Kɫo]JR`,NR,lrISـSn3ڄ؏QsiõAWsu43'޵Wmgr XE' UqhbU+ ʹ`0z}s :>]տ^p;bX֕T9ȋ=f>> ME";́uo"RUUj9Fn +U ]pA `0z}0@m-űo =!kylsJlQ9?CRJ8 [ ;z#{n#՘eLe?/F  wac#10rp Qd`jV߆q+N ``G oP@k]`[OVbW@>Iў~cYta ,6f; 85B^\+\R6 FD.œ%Z nC͇o*T S$`܂pJ'4Z/2ahONX; @o.|gӧ_[u1{<\R[Sx}[oΥx\ЙN }A8#\*s`1dۨh %"N7,}%jׂrXW-@Zj9"%M99bЄK=''4s]G׽N31ߑ6ps RrvW3AiW Lܥdʘ)#6)dZ#aQk̨1ᶊNeߟF9YVqj8G}ҡT9 6z]MXA:OW\ۊc,W>V\^;So QKrĶ(ҢxAS R0*څ9P{4:~v UXcbRUJCЎ.~>8 ^ה ܺ5Ǧ-鷰vE>~ùĪh%@Zf:SQ6K؇IŔֵfl0QgL,h-XQ'jN9u7Ą)mHnJUm ^,U*s_@kS`^P u(V]3{߹Z1hibgp-fʴ,BaVJ1HQ0A3:bGaۘA4S OAKꫀLS Xo)_T9(hg5)Ih_ehur{Dg`?& >4+ ],sʤ*P6)X̬dwziS0CQɄM?,\l)g &ZώT=RПqM KM/kRmsq|m4GpR/W/p ;RՔ+ /T)֚1hDŽp֖EUԝL%(P ƕ0`C6WoPlcr?~LzPH3b"}E|l8v=R`\#&/U})pzZM{\kb_5s=sUWsOՇ/.+P]w8 ^T׫8sb^4v; |vEQ|[ⳟl&_EU ιz]т10⑿ ~2 lGe\֦H'צ>E<+G~=P#4FS0b&U56p.p$~f#zPԹisS;:CT3LxI X=kxm+ϥ+(LT?þ {1|A 0..{9qĞ_cpN8F9{Z/'3gpwWgy~a` v賰^ؑ#GW6sسk|#Gᡇڳk<}lllp>O0L5Μ9ï~ ~~>߷X.\wus={v-r//7={vU}{/W]uZ=[ū^*N:'>=Ɇk@G?ʍ7ȣ>g:v<锢(ؿ] s}kW]uG+ѣԧ_e~^x~~ g??ϟٟq/u!+g>ÓO>h4+k=裼o(w\vvٺZ7pw}<<~{r[o~{|qAy=@6`]6 6`]6zЃl_"o|y;6N>}(y;f^` ek"7}Çgww~w}~?~}ݼկfggn!^~;_>ƕW^%\“O>bСC8psx? a`/[ַ;oq\}uj?#~'~__`ss^z~߃ = ?̾}뮻xoop嗳c=Ϸ-3x'fv0zcǎqm>pwp5lV۠om7x#No<ml@mPЃ 6` l@m` 6jl.P=` vl @6`]6zЃ 6`^i,/IENDB`mpmath-1.1.0/doc/source/plots/besseli_c.py000066400000000000000000000001631340375245600205200ustar00rootroot00000000000000# Modified Bessel function I_n(z) in the complex plane cplot(lambda z: besseli(1,z), [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/besselj.png000066400000000000000000000557751340375245600203760ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw|S?ʦlZ%R*"!CpARʒ-#ҖQ:hP(m8$iiM{y^ɽ|r<9yIh\x \*5оظqc- oVB֭Ty$O@Q\\kז;wFam8rX(-wv:tWRZ oo殺aOYNi$tsVF~wH#gmj86Ilp:Q>YNiMezx7U.rϖ#gmj86IX&mO W=[\R&aϞ̙Z  h$>rwp}⑳6s5@[Sn>{زDAOYNim)7:o,\ ue wG'9k>W) -F[>mq̚@Qe#\֞}ԫYRR$ rwp}⑳6s5@ړ~}`@a!\x \ 4bz~1 Y9@T#gmj8ӓysw`F*!\x \ 4b{N.]ʶ;!\x \ 4ж: ut "+GpJm,_|:2qEO8}ZQe#\'aYƎe"wG'9k>W) NBÆժ J2$;B>YNiu_xu 7WB;B>YNipp6!\x \ 4R8 uЬp*͘rwp}⑳6s5@K$XQA.&ZOYNit:ݵm;B>YNithْms\\hXrwp}⑳6s5@K$쯽rwp}⑳6s5@K$ԡ3лv7!\x \ 4Ўp@vll,-~;B>YNi$!*ZOW) :5rwp}⑳6s5@;Iݺ[7o~!\x \ 4ЎtBaXEmrwp}⑳6s5@;IÞm;B>YNi$=-S4#ܺ,ZL  (@X"Οw>{F \"@NƘ1c*eO>!V*`Hѐ!DIc6e'iHCekq:mshlܧk^>@p0p4[Q ;)˗+E-Q#g}rp}ShG; u4lĨҠx{))…A^  K@B>9k>W) te8 x=Ӿ LTfo =V 0leKh;jOpJ]NB@^~G ~3gxZDDk>}:c XxV wGYNiI(* ³x/^խ:\԰a=l'l=r撳>9k>W) t8 8y {G ?`1#GU5r'gmjTV1b&OoVxbb":w)S`ٲes`J! cEA)gvXR j4WGސ@hI@~>&39uǧzcwP;oe)CRk-},?!`LzbO6m )1-"Y+_A̽Edgd#ei δ91ꝩ"twGoTM[*^BhP\r E^~9k>W) $Np@bC>vɓ,:BfAе_}Ԯ YOCu=l76^;{L3HŨB=Y\sx3{㹢;7:n#Cշp᳈tG#I= cWԷf8`TJP_Z6 6k!Zwk *:vvAyl$&RHRAE!MB{uq8I(v; oU;-msuu/Wmy6=ԩ@zM,FSqyeMP `xwqQ}lVߵBh6JllGOّ$gmj8I/,r㏙sF fH~+c ֟ԨchZ`l6\s< qZ_ g4ӣ谶x8<ّ$gmr-{j JO=LϞl7"*roQ%-JG԰!BAt@W?J*H妢/H[-w?A j=[!ٖGʏ?#G$\yƍc["1z.CvAj^*viY?pZilifh54 ³'vGۅmV:xWO~/Q wuFQV _@^D!gG\ZtO¢"`ru F 4aeJK=޾P( >izٴ 4zHIZ .3=@>nXZԯ^.CaCs 7گli((~sZr['gmj8$ܺUMm[4t—CB,.=G5oЀ9/j` O wu=;j1޴VS:WcR;BۢVhpK=#] /9; \ 4ТVv4= "4] fjaTQ~n$?_60#zvkךm B"!gG\ZT&aD t<$: bJg4ѽYwa!- 7,^&[ߴ#lB5נN:XaailON ^@kr66s56Љظq#-[ )4YDpY+00;p"nGO>x _31<2Zm淁[}wUI͡P(nY;{/#`_%9; \ ~UV;vDDDƌ+ⴀNBؾC5J2uXSPӳ& ق'xR  E7qoJ3J;-miװsFAu7 nnnwgh[vC2ѮH6s5<9~*_Ik n4HGCKZ/hSt} NKiP|h2 .nk{Tb貪 cD6,'("zE iNj>Vn,j,96s5ZA{{{c֭_|qGbP1aZ}ģN+Ѓ/#DťF+ q Ԩ&>>E٘4G@Gj\Eqjh}rEհ{:++ }Əv$~؂MN«W@ ߵ=~܊|m=Ҙ" |mNev e5BV@|F$c7S} v|,X.Đ^ š+m ={}n"w'Zmk׮!==/HlMapFwx'YYo<`@ bދAֱ,Rzý[k\1-4_quޝ_n%Z-DF/̺Lׯ@Xl0bв%z#dg-I&ZTz뭷$?%%DMݼ)FQGѣ.o? 79TP6V{b6ORuZҒ&J6nnx.xP`@*+lIK#1]ukӉ'%*-%k׈m#3ˋE4g;!_-I%i42ȑ#;p^M|IKYYTX/ժETTDTP ]y]_Y6<^K˖Dv^m= ZgNDRAEOP*gӧ7gIUo%RSz.ym@tђ%DΊ~X':z:qvbg2>2Г&M-[P\\%''iԩ&Ċ 2ĺfݻ%;57Tv\k'5_o * DyF l'XA vq]cE((pRAEsE3ƪUDrˊJl*a͚D'B[z:kÆe>>D'ED.J~* s)pBھ};}4ydZbeddH(8V]ĔѸd+Ah%ß{n:UiHV,Mb KԖO H+ɘs `D3g<Ģ"ŋ5' G& e-c/ @4jQRx>7nфr4~;mΧ'rh] 2'x&OW ؽiS'h*mQ̚EsUz{n݈n0zXAI}~s߆1GyeDMbׯXEߍJP*MY+Sb㯅; m) E'Ւ77h]1¦}iˎҜu̾u/Y^zMmǜzuA~Gم٢7ŵﮑ *zD0 OI%asS*)!z}"bvn;we/A"7nP JPyi~|>Sٔ JP9ПMn{Zuv87:MW?JwKaTRDE(beΠ_=ϓJHc8v(']۷m Z^RnWA"cUŕF ;tRAEǒ`ښx7 #鸚| *pF .]O,-แNc;vϣ.QSJ˭:gH" 1|iN p6)lH,9je^#wwS})ʱ]u0,1)SXLL4 6oAX'עED ujӢA zd*j˦FߥKuUW},h'S{=SLц4~tUo/zR$~Du7&zQPDۛ%+]n|\n%E+Z~Qj/l *>-RleBd65KfwA 1GI"k.4QYOP6/g-¬hZ_\cNuIR)1{[P`} $[ffS^j32.Hw#Dbmw,GgDw?h 0$,.&_1d%׎CRri R( ym.zTPQX0*ͱ3u5k\ek5  N 4"iu_ɧ dHe@ߍDkx[ǡCD$xz҈' ZN.5 ޹)EVu3iSMN4 e' %|@*0&.D1q׭?%B^C]6եJp-&Hȑ$ߟ} J(Bݻ@_Np֤f^~}l:ZGn%u\4QxRAEѣ+GGРA}S[&2D[,zӓhn9^w}:$CLv@C,!%j겪 A qMŇ{[tBmFjh}Mg6vIz L@o>_+&"bu `z:k "Fϖ [JPMvm'=auluQ:/?u׮mUNL pjsMO՜[bt ~tB@/j ~h)($ܴIԆ zs3[9tXsT[w\Ƥ=m#9}q6, welq3ɜG̿ ζ:Qb+O6rvD!N| 4rH4p@{|&ׯBxCY}7 ηXb Jc+΃VgE[4:e,hDÆɻv%Z 9  y7)/ɿ#JGqZѹ.(_uX+?=̞o|8Be%:}#i PJj a[[^7$X z H+*bC} ucih5-#(A^?7t%z O]O^9CDn߃ELOg.Flvݩڜj*mnX.n}Z_4_|>V67D;ۑz#S/e]6/]bEJJ]ݺՐkG 9/\h{F%jk֨a^GX)HZ^5YԄqɾL] ڕ -RD3.1JMްa@KIz5~hw5v\b܂V%/>|YGɓ-\С&:^UZYI}zm}Đosv11m{Wٳk[]'<HI +|}Fuqwu]U".բrsc SΡO4>%Qw ؗhf&70rHgP#+nQcc%h6;h2Of곰v8KyL=?%6HkTvcҐ%3l@P6Enu//((ĹԪW~IYmPڴai2Ǘb7 +WXwp//.]sIVh5ws_4,ݭ/e6 4 xDixLGq-C 1İMw/-nwrbKJY|^k1bHo>AGƍLGY=}6p-)…&k6XCnPT\=i mcIr5|]K]Ç~~z]_ s>ђ%Dz` n}JsOѬsY6 TPQxpl2nzd70fΜ1{Ŵ|Is4 VgTUt!] Di߾mpWJJ&ӡA(7bp>Z-#tRSYg u[&MwyS@eEY |{}{K=7o2 ӿ>WQJ~͟]gE1:Lj쯼<};- YdR)ZG<A;ZI{I-qMt{n n39=Hnu M={:veD3=YI #u5ۧ=i*WBRm)=NRC->?_VPxV~/ U t d?FoG~{Db;PKG3'W)n0?Awwgh̑*С9rrXu+w+hY LѤoԦI !#0wH1aF52֮,NPSP ps9TЯUU");T3^ Gн;sͥ7Y%,D4^-p]zwiҤIMհV &ɓiĉbE܊ &(YGA*QH)+SK7=*r_1r$>+n%ل{X 'A%hwn.^ n~&R`@ H"V#F~mٹT>5O1ӧRIU{c;<׮RZX=AʻͅL&aG2lڴvdƓ&M*܏7o>A{>SO!굨5֐}֌zݛmFGA#|A)umM{b;}^JOňbm JPMu糄O5 3ovuVW`֞_[1vI^-)@z#ɡOJ# JS 4}7wU~~F㘂2̙3BBļy3[n۷A۶Iݎ3 Ha(azecS8C݆JCWCL<A'>AP7z̢E/bie١6$-%U4wRsSFgSRvagEdz=QXUG(գT]NP*% +0 cWp@_C:}Y.ѹs6+7*III$Vx<11~~~+FT?uXcx2Pjh0xl1~C]Q`5<[,jfPu Z 1oooc@TT⤟cC@ +VX'8|DT,\(>]OGYM>8ȲuAl&P$G&hG)p٢'nߎłq"PR"+ jh(/.%K&Ma?kCꫯh͚5t!&L@=v4 9J;ĔLBNJ'An%Hr"X4)}V󏳶Mc5ҧݿS^=/"U /{~Cy9DT؃-lWJjVEs^/glܣHUH35 SFqTI(39BtݻW ݯR: ˲+zA zzmWN`g@A5HPNI}'>CT{y+|R@zW'j]f n%@nP#L9i>h-=Qt "2Tu.(QoEȅ7V{b%iKYەW(tjzIJLW@.@@vo̸uGIͬ҇ڵgO>Mn7;v~Mj؝^ aaIgj :MJph,H>GA|]DFVJTʤ:,g@4z$|Wy9!yスRەEzv%hqbLJj^H/+(T  "n߿/+WX$׊s+JP_PvDB$+twG1ZoSa"ϔ(S"sy5 kI9t+dU.WCiUۮmS&eUbrf^z-aMNa6ҶwvEE6-(0~W Ɵoa#Auj6oC ]3hgv-h~_#7:M(۲mO֑&U_3ECVA^=YC B@auNƶT~쵻p~^]\ t~ȗ^8TgR_ZuuSt*ߝ"}~bU]D1;>[1w.J)g-T[2e9 Jn}84,<<JPD5<شܲh F剏gQ :~Yu6_;9]#_6zHLR(F ]77 (]We*qR] vV$'uw'{xA 곱㺉ѥY$ wx-bM1u^љm(ZMԾ: !IN"^Bk n) ſfδ|VK.PP@ԭ/ Raur-NiI* ]j͒㏆ [A 񕫇nIDATQ}6: @8FAGc^>6 _u)MٝAӤɳ nFޛ0çӟ}UiyidkE]=D1ۃ];fIn7lޖj)_>\4Ю$ԑ<͚Yh/D'NjJ: WLaM%T{^moyc?Z&*,U[?u:KBi1tuF|NZuQ̴djOLAVt uF Ef?in2/ T PZ͒2)fC#G̟d]BKf# ,^a4#Ύ;lzb&PzACJ @1cHI 3L7}:{#;u*&M*gT_lo<{JDmڰ?Ht# =R Rn%@nQ &Ofŕ++y] )"YYC$Śbj=A :xHĺZ^F'>Njz-;iBQjzJ&" vBt.|s5j8rk~q>ڟƟ1:F:J2K(/sЬճ(%'Ev) +9 u9Sy1iJ76 ;^"}x&mfι٢ 0AIF]w^A |`uD}*<(3@kqaln}D/HݣԪƝvcJ_FNg[߾YxZ:7m+v>3n@nQ ̘h"2TxENs4xyY_O-@q_Y<md3g1qƱЪ+3EBF՜[1R9 Z Rc'VؓC{R;{iB֖[A?&?NT6 -ړ5TF-މ)4Z <9S?Ǘ}Iw%TZ \I#5E:;MGaTeU\tb"[9׬iuRW96FlouKʗ5M6' W:N6"0n2*EƯV˚> `wEѷӊHxu~IMi4,"!t!j> pa.cwEZvwtJXa%(a]ﺱc+V63oiOxm67<:AM|XU5{ KPXEm%umhQ=֒^c/m[VQ:* wSs6Hza =ΤQGW&y;^EX}6{Ͷ8vE']ҙ 15.} K/&6%'ίK ]^*;|p/n?8+09<([ GߍjXd {pwC*7xPVPUZ0L'F_i) tw7p1g pX%/_6yΞ=xQcq;m`liNQ~w}) ۞=&<7 (5}W.tfBt]Hаy˅-zg\Nk!yU LqܱTw~]ǥ?wwߥR_ iZ'_S"ۛ嫘$-HW `!!ևg-_nobhHK/ΧRU]s'XӃ>89*%R͢QGQ5=k&Њs+,Ͷ8vU'ݻ IrT^fg JPB4h h5}`ڐsk2d3ߝb{Qg  ]z )Z}Z- 7 Zu-Qv,q _\̎d׳z@w΋/ Wޥ   4{VoWq-$ԡXԧ '4S.lzGz}o/ VXaPʹ/$I+_yo3fP`@RAE6+C77-ζh6C軛#ܻYxߢ? 㞞ꫬ@7snҿҖ [hCZ];F]DG+}[%/;f^BF5X@\YBʽIP*P8Z}zd#(HV#26+.&WֽFgz_ٍFCV;wT mSTi#KVvTVLb\mqJNByy,ӓrX0-ZL1ۃ'Sk]d_퐹Z-k=C^(zu)־bưN7>DJe p:v!3ԙR ":b_￯"&Aj(|guᬏa@Q}:h-M>08QJ1h J[)QHa (ٞ1 0̙l'Yn"*ځ]4Ю$q&+SU ͮ1 fʎ;yյ#%J4zhtqS|2tk=Ohӡ|殝XK7IX#8ͱ=QPBfT$''K2/@v60{$CA7s'=]L,~=={J!!رrd(2KroK?~\եj g8^ :~G?c ON: Cأa0vj-lNaHM~Xx5DHsr'7Dt@תb cǎ͛ZFp.ЮPX\? ߝnP>7}#nG`{'Ъ^rǐ4?%^)uׯ:P+PPuYdz+<-h-jviT r-NȨj flƍ4૯Z}%%)g߃ۭT`pH!:22A?GDP(o t <9$d&4tAIE{/ @  }^vֲrCs蟈 _ggN?x4%hs4Qjiړwڏ'-*!"16rfG,qMnkD.LFIԆI* '+?s9|^s\Cp<=M=Ԡ*==&rw[:wFнO;ʆu;Ot >=ySRmktx7u}zkk-Pڽ9Ք( ^\O}j S[tfu::IUѸ"UD\uR|TzzimGLL ny^BBBIP\ t\Jѣ0jٳ1X> n|Hy9̛gޘ1 `v6]&Qc%*<)Oop_4]\9Wك4&n ?2zh$}-=kS_]ݵf))׽ړO7Bn` {햣5ԩ-E[ԝ[to؆0җ/{2܈?@>th]8 nϡÿ _zu5<: ۷w\kmƯ-MLEԖ7/72sLKPPP_Sne#ް#-7[nvg;yc o4n(QTMRii]WymJI:.׃.]ɓ 3^y%p0s1q {7\iO1"#ᮻ8}8ƥ(`L߼n-pBn_V]S7r!d@c )y$.\'4.۲`|c/ =~ **`N7d;oƍv.tns[^[vvdTHKx _w<̝k>qZ[4ex=c%9gs{}:ѹ iM)e \9ש1si)̙cS9nŖGнi'aG࣏`BpL>15]z gw4C :S=yO>1ɓ0q"|qtݙ#IO7ʌ+5= @Ɩ=eHXa..θ޽ƂANLe*c!0z]:9-to_$^>^テѣ=d\rNO0ÇOn_ڿm7 I:9-/ :ScƌΘb޵8.(x9x1<ܤg~]sHhOsHر~ ! '; 4^Hҹ ily-]&]:sm }NqTd?gm }Nc->tns[hY$sHr@"<@ƖZ #}4вH3O6>t@YD/^L}}&OҥKY|yEBHy:9eԩSx<}],X@^^Hcc# Y$sHȀrpDDDpwp{eŕ+Wطod?gm }N#zĈٳGLL q42˗}V__Onn.J'Nh=h"}}[dd6-9r|x<'xɓrJ^{5 @]]YYY۷bbbpV$w]>tnnOT^iii>0a&LdEBϵIy:9-/EBHy:9-,Gӹ il9e'<@ƖZvGӹ il9H33O6>倖EBHy:9-t]lѕsHtۨbduBNsHd@@ss jhh:Sgm }NcVoNJKK૯$ <0rE|䐜̎;vQ]] @SS5m544∊:Gqq1۷owyf^ -BjjI>n7֭cܹauRzjS|דilld֭V'(--eDDDP]]|@Ğ={?>"::Z\. 3n8Ǝk_M6ѧO֭[97m[ h!MluC!zB)‘ڵk9u(Nd@ GjY%33Sl ±Ξ=KhhQQQ䐔c҄h\f'#h!Д h!Д h!Д h!Д h!Д h!Д h!Д h!Д h!Д h!Д h!Д h!('` IENDB`mpmath-1.1.0/doc/source/plots/besselj.py000066400000000000000000000003031340375245600202130ustar00rootroot00000000000000# Bessel function J_n(x) on the real line for n=0,1,2,3 j0 = lambda x: besselj(0,x) j1 = lambda x: besselj(1,x) j2 = lambda x: besselj(2,x) j3 = lambda x: besselj(3,x) plot([j0,j1,j2,j3],[0,14]) mpmath-1.1.0/doc/source/plots/besselj_c.png000066400000000000000000001110561340375245600206610ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx[lU&y/U266UvWjsg"/V f`I&dJfpwB&dI&|0$L2.@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2$L2]*@O2$ܥ2z'nxߎŸ}6~4$\3tC}kX׸u;IL25A75y 뻾  f}N$Lrd膼} oxwoo--xt1 W `W >w7c[{;kLgqrFNv{eSwwɥ''qkisdo-Wۊ5ڙSܸyW1;e,wvz7Nklksܺ}0姟I&nʓO>w?3| _c=W |ӓz=H حk|C?M+Q?JUӦCxfn㳿S?R\Uo|S1@ U:vvVm+lMzV[O96ڏѣG5Z9^qT63MS'T/`'@7䛿~y .M1fR%Zْ ^FY&vU븆;V2&)9ڮTPE*V-ֽJ鞖 @zQ0WJlrE}xⱇ~K|xFS <艇?ߖfc򅐬^^}[vAgw2Sܓ6pvy⡗؝Ψ)x%OiK'jtJ9^k!@) ' 30B+ҚGx=|\eY~oz<6 |jFk򫶤L#o Ww=ffg'Wm Zj-1abRڵN{C? S'պ[s}7_][zoqlUV_O.opuY:gljklQIWRWÄ2~OQsi2€[^G5 4lܟln/b׹uZS}:+e;1F?IiVއ[ )-v^/mEe&JJݻ e f'_#gлxgEU/gO55DKF*ŨLV0fIL$h ,F7<ʅ Ʋ>!ىfSƺQ+uJS>/S. lԾ2i%ҏ}ɭ vK,ͽ"l{TnІ@6K&dQ-V1\h~O+ ȵ5!+J< ь4ӄA&S^E_w%R %vSMmtINE=V=xE k7>kd/6U52ZFs.9խQKEEE=g/w޲hчdw]ji9A,zmu '?xq_Hk@ ЭE*\<4r`ŠV[ui K(B98U>T(Bݻ8`:jݖo=05UM Wם\Z&`l6fILݔ}۷x~~ ԧ#8,bRG:Z梅P(-򮐣"uY_270 TIU~4mԞUZl=p?~Ź=ةK@GRT]ER@ww>2tC~a\]]|AK"d4d"D͢V߰q! 5شXs4hKW>%Xs/Mj!#% Nl1T ]$['kORY'>fI4NdE®F_JB9ڬ"3IpZw{AӮ xė}["k װ6i:Uf%}wjEuы褷.dDzpj8*Y&re=U`HJ W=جbupZ9Mn~*CkJBN*F(LŠe 2)9D(~Иvغ8!ܺyOs]#e&Kg..\O.&2[bn!)V72I9y"i8Y@.n3!s Ի4 =kjF*¥Sun -eRi.$>y3=O&SANJL4 TW&>QKK)/nwIJp.3;*Rۀ>DʖLjTf:B(Lb! Pk|ős.&0Ȣ:f{K.OΑN4YANYc6{uȾn eCrC=Av{\T2=YK}3+j|)1EAdP,~.:i t@h8JԵ @6 /ET& P϶beC㠤b/ڪUhnʴZg[d4uƃqoR;m#+Q ZéY'k6@dA-Oncckg%ȞTltٽ骷jV~lϭ?4@.G#i -5HkRQIG' {F.㠷ԛ=1y K2ӠG(a-D Rx7w.ב~aԾaXKf.jfi;bWGI(dw?n4tIxtT3t pKFqPȉc -Nn] ;Nj,:k{aU)^[⽚}.HcULĮ5ut&TS<9Vgr<~JQ ֬q}eo|׼?3?av} ]O_WƘo!|iŨ&VRYtT# ]kI^G1\Rq KudVn%uQ=aK(8tp*c3ʳf ߆Z&w><.Y6pЖ@HB>֔_?RHqQ AZ(Y>L>U ٺ&<Y$xdUF Ed e7]' u79ǰ) Gx+䇾iV[-cdYH;hU2" VIFT+!29J٫L%%%NOO3/PNB<5؛% GTk cEN_,eUA6!.VAԒթeDˤPfuoy/pf|}EE} G? |#E|?}QNgV8ykvI:0)xǾ=p \j[կ~5^WϺ:M \.ۊPS6K >5HKjOLu# NI$}P v6ͼz%]aQǨFrdqځ`iFr5ae?ьKu>xݞWv;4VGL0>)(8T<@`6{ %ŎE* *EU@5AS_PZ}]cH4Jt.{U;sZS#͈SUn[ Qۏ^eL Uޮ+Z/Nl%~@\4( dMaFPHAѤ!$j(:sؤMͼRυ( IDATe*YYBܼIP$Mj[fnvVXx~+Z&XRnTb-T4hxU)R/AkK wHJጜA PkgV!zrmk;\׎лYf'2ޒ3G"1ց T"wH H" ZOj]筲B,Ubv-`ZUtc9`y89/]J_#]Df1?t!eDzOa,[(OD͸+.(' mXC/ aKE CD1?8kᅷ?l+@_Jƀ9|2QmI ZmG36MHU>mJzOq.RtQu(sF«6} \:?C~k̭e#c8 H)V .;/!iUDT{,iF]ufo4ǧP-C8CK]r4+s=A ,l浓 rDN 9,IYPkK9ě} ;5PWؤAĕj:jGTUA62cIhEZC"Z*e'H蠹,X_nKe,t:˾A\"-oK&S>N:akeM@PȀVҲ)&T8qzηs(8u2J#F eYHpN K?dyh1dEC]M77%u ȠE#)2Z]9)!9z"R>!hA+ P5Vv, ɛ; [إ*t}Ҷ2BUZX8Y 8\UP&SҙeԭkeТv-&k g#5~8|Kִ *05{[~-%`CEveyiYV'$K ^c,VEېP 0h1Q«VRW&S\˫c͑'.YÁ2#* $:R6xcZEc+̋f=cweHc zآ"FYR`dwOl2N+[WއExIBc77 FUz% A7e轅aOZ]u6臆\/*{ԈZ9sFǣ7:jj+ߘj;5gQrO_wi0zlPP!IʢK@͢rJ+zc,]@C&S,NeKH %HqNOk)pb$_,P9mSK r Qj~E&!,=|IBajj7rjWU:-fZ[47Bk)@),nm1DݥƷW%Ԯy؏tq;i@ "͠s`1N:\|RvEqoJ2,T$BJq[1IHրhNԵw!qEre៫szw$n:]ݫrJBGCE Bh-Qtdس n*:oZ@uXfrcIiLN@}Ր2=4+Ĺ%!~4gVsm7LJIHۏChW z{e-0z5Q&[Gi{c` r FnonI k1Ҽ A:ű }UX U}EBFTI!=)h[dx܃exe,cwl ?:H N{rJ#SHP>1]_$ ˲q7oٽ/:dU ºOK17Kn ..sAe] |Nd-{{xӛ?;^FpG$oZޠ  C@ :=IJ ˀZ =1z j&@S]60+, !.`̨ʥ*HcIeg5)( 8\ds y`Ϥ1DRBVLd_u,KOdgo_%f/c2ZȪWЂ}T`Yౕ.*ڂ q.0KU{GޔdSZQ]zZp9yFzG)M5xi@7 -FSΐT% M r~rm9m&޻XXϢ%Æ_?c\,&q2tCwwO'~'[[s?)x [\OT| pf3tPlKs`y <,΄<6gO5y8ܲ0!_9DAVtT#-V‚A VaMtfw#z{qE9OJff oQ$N&n[-o|׸KĻ2mOnAg %jR5v:uZX9UsOA؄ .= wsnCi˽5?ze! $̶+9.N(D-k[,چ6 In>6$f,[2: HL_rCPiph $+:*QrH%] U3<@;2R;V's"Š98Ԋz|ɠǀrs8”!°ɢ9ZQlRv#Ի{܅Grdg@٥2.s*k$@+[ܬ=9)+gPOge&qՈ@62{=zH~p84U`oa7 R235iK@T9c!4Ժ)Vpj;#>4{ 2e d? ej w&d=xeWɒF2@gɦ+:Z֚A[*Ln8*Wph;% ʂҀ\~b:7 k2Hh%HG00(t ,?ieCg@ٱ\cE5g -/ꖟ<2 LD ି"MKӴ0 QP:0Ҁe=gC@^ِo|M ˰rh< ٿgٍߤ2~ypv8ve$Z`!0уЉу@".F}鯖UY788b3縟1jr؉AKz_a! (9,:{/A>hQZ2Zg*jA9.6@[x%H(8afm$F.Y8ΑR*`Мy򈂒<K@ʽ@<8~ȷفr`k0`- Zo )#بƐ m<6l^t,`x龟:h\h2J/d^jxY\5Q8žC}=܅f%`rr'"+]Y1f {tXQ0 }5rpր:Hzh~6y|+@ZTjs`s30=P`a[nYuKV0B*m a`Bό^2,!l IBD: nOȒ%hAg#~h!wspQ)D)} Q,@-{wpƜ3DWeb0g3t.fb˔&{3"`w1Pa %Jsm_Uk3g`\st|AgQ98>"V.(--m/G/{c.=fqƂLd=aJcCuڒwoZh偺ll\uW\i@¹ d*a ;w\] -Y$HG,`mH grC Z{S6=̵Re|W9'fщk&^g00ZW3^ 䉣4"W`AE2̩$(ϣ.^ zŨ?6y2$98&:0c@ +(s&Âz `2aAK,/*w&vvF)ORyރਭx^vΰk9㖣KW"wL:`АHQ7$H˓ /p5F 2{S1q+ ӝ7B}_ żtcd{X++X4rb1Q +x6УNS?Sxހ=888}/qfʇz1 ,ns l}j3KU3p%`Ed*,0Nf]ԀspI0 AGpdC:h$~iz<.$SaoE`~;/6@bl7nծWZ^j9Н|9Üp:t|EGi-@HijOs:f `y`1 epol:7'. SGitC(__^ܗlz`X Vn&W>Ca.!.{8<</;ίI E6wx8`/>9gD̳6&9s. ݕw{fM=60_t "h+LsQ&ƃ?C\p`8|̠8p$@ú 9@swĘdNy ZN⤽뀽1X <` ^Yp mBw3fv@l/'jQ ^c!w;rB]laf G>ֆc80u #gҲeGAy*p:[`npiW9ss0@^2}_z/~(ξr Y`X +آ30ppq׀]3̆`7IɈAh|dr86 \H3ccs97فn|@8$` ,& ~h:Ӂdxd&!XcKrc%n~Wzv.9pFn[ؓް@G:ƯگאA/08`k 6WXD@7u n3GmA!^,>\A@[!, + €6A Xd<=@tl#dKc޹I9AqqPbrS\na;+op cs"fWStI~ bYnGV V(GCwvW|㜀%  ́g@7ɕM({w,m e):g Q>!.X[57k.Ԕџiˣ&跿ƓO>o/..?899<__1n;|qp}lv=jyk t0&"[v` [=8 eft $*0'1 =α ƀ܂odЋ<c :w0h3 AvL9vLQT1&%=;e%[7D ]h0,}^W~9@W.890pa gK|re_.?)Pە[c\t9 zC.*)&ﻼ B,zZ* `~gZmp~ρ͗ ,݈ŬŃ`Cp( = |;ַ> ~<o?||~~??|3xK^Wapu7^ B>lX`u\[gX}`v ]]l݄eeo͹ rqHkR4G7A8À6|5?#{Gn<ϟ'8fḴe̝H9s&(wH:{K??>^lo `s K3\~Ơ{0p}W3&Rs"˅o BFgװ0*#lA8#7a^v|朋rYN$΅CnG_׀=#3a4޹E$NY=Z??8SO=׾g?glfև!py } χ51\bpRw)X>0y1> /} # ,pG|瞑yl<1 eƻ-2p.!8°$quml> fl } N>9>ـ".(SZٛѾ!;$ߺ?7p xnXq[ \|| ^̓Kz`;a 6WWGc 37p?9g17`'|"!;I]~衇wӟ4^Wӟ4~a]`'` _/Nap+ S a@t D ,8$coGB.)GRJ9;Z0#= 3# <| t `93:p6ST8䘝S֤:kxԸ M|E.*O:pf30 .~f;HڜǕN6.C>/"p$ʉwEYc\LwĘ?hq/pRA`y_.lbRP')1;edd3g+8n 388~%ї`=yS g,V°qnwͮܳ ~L?7o{{c,^ouyES~)0'XW0X!e%;3E '4AIFOnDf',^,onvS;̃t СwBk$ ~Wd$@9ɸp`k͞fJ|II‹<|9txapWQm.gchcuY7Zq1 *?F >Ηe̿<& vn0 @G:h83H m"uG{pʓs&9Sxy#sxr= a+p!^ڹ}j޹rO'> _z*@W4:90_ n`Cf E,<*t`4l"HPhsY莁}$\=@wg=sw[aa,tM$hq)Z :sDwLn<y@i,Sgs2A <¸Y6wiJH|\ @Z]mj_pe :g2gg3=K8ȁ Z`f8@Gtmo"K$ SH߄h@Ҩ%u'gľ|h9$tG I aÓ80Spwt3P1!N&S0eÔlc4neNuDaϊ%:Ðiwa"Ik.4@c3 |ep3%grW0*k~ot a D<[aW9ʰC>$7w < 7<:&AY݆> 5~2>PXM=(݄ȃCg9NT m_ 8Q @S8-bmp,@{{a dso:_ a;ӈ ,<>a9c^2`Ls\80, sĸ6ݙ́[z:],s򢃗).##&9n|)N 1[h 9Sw̳50t{{1ʯӸ%I _bKr=(Б f04UaC&Btn%3]8$%a3pA'=q ~cXKS?d<p%kHPrWF, 5M{8[ "==՞p qgz8D "D0'hK6Y5,hRB p̙{K/Pf-{ȱg$ csv7:KYI[C1&MbС Ƴg뷿5qπ!GjZt0v)tL Z= ?;;_C'Ҹ"&tE6n#3]tgʚ@``=0n~wcЀA7\6i.1+ 9(4~GB?(00+z&6_b-Aᄓl |08cs$JwF_|;Ft8$0CYE9`q$3hnTpnb[*+:&M\446`ࣥ]+0EE.;ɍ8weW.-py&OyoqHKv;Ο8| &#aw]ޯޤn*sl :XPX*is (tFDŽ; }|2^& 8b`1'N6;4z25x3FpIp-D!R]XM֓߬aHݍZ\iqK2bI3 a=@H| V4EfN27H{l:Dv 7Њbzq0~fB!u'ɑE[ҁMwd[,4? oC5JȤznN= k-;A3hØqkI>*cBBTA ax&䠟 ҏ95|GX7+ tؙ8t6'v_+:hB: 2iD92ɫ',`@Gr11w: !啟Y9z8ޘ%s7X:΅ zc1 ;.3ڴ|90Bz4VQ# ~ ȏb8߸nr|0iHWX A0 &_S9 >>zrqg5yͿ̃@CvO Qdﲙv\5E 7A s/2t+NnÜ9s:'ICYB>>datxe-cnj,U(P[0u`YD0"a6@DCafA0H.};#u1OѐnBM:t~  NLtס˃]e RHbBQ y!4P4j4Z,ss] #KQK@g_Nȯr00hH"Ȟ@&Ap+1fi$I8m(k{| G, nmë <+ SpA=-p4zœ8tFz߇uQ@"C5<(?c3EUI!` t{r;Ann>;"F4{A~U Ďqިۿac*I&WRX"Z{,FOfj;7F_4xAsΞӷYi3mw` rY3_3j1\apSM@-شw1߱HR1& \wO3;f=b6n&Qnan>`tX\|BUJL92$3^nr!,42 X1jF73;HJ P , y;W4w")PF<+9R >+& ±M;Bdw E V@Π%`=,q8ybנ!(``qlD69j;G[z­~ G!CE.K?6j Ln#@#Z'e-VRwn$"& K`‚ Cgl^V0EݎE=Xgwg5tNCV@ub3>t@zO!(eMPp G; ,(}k8wAEmE8 tAE6e$p̵!1KA?$P8dХ]G&,@;("!W8L C4wA3G\ :Bgw}tpoozN7K-/-f3$xVE+? |m3,/ A0`\ZURcص <#晳|oebMvd.}HpfJ o| KX ߿+:tv \s- Y`2sWvh=SΞY_K@&jeH=\=NhAD"P'-ˡ@zo ,Hg0UQH5`D U*AB B?jArp|,\o6rrD0w k4'Bغ|-JN\ʆ`4y6ilWX"rV+E-Q(:G*FaNgN~gY -M,m<t.@-@g9}Š&0Ga 9neW٠>G[E$,zF(> Y ^eNQ`"6 at/w0w~RZʧĢgpy`<.U,_-\Y&Ȧ 0~( T eZ @y:{ F ޓr_!m;k':q@]ix|6*ZjKA06" H2pLοCا= \u᪟~.F98G6&' >'(u/7嘮fgId={-u\t n5$I& F7ki4-ֆفɕ@Q8.毢X@-`I[h2Q' DbM$^`%QL%M1G=D=UBcm)Ϝgf5k>R|f5ggY{7kY3}n{$Δ:FAhWlZ.:@ Iɰ7?CϦ#ۢ=8e `٭7Vze#n]EOˀ7zM)FV~=#k>rI4 w(?Ғ:@9ҩD6dXو4h"9`H.fz m6wst[D Fׯ3k){McPedBnՑRT?k">Ayk!ŤEm1h"j,́zP. f`0ŜGqh\fAgj=/ ] _U*kJ3~PUU`,hVt-[jNQoa-eEM^?"JXIE ^& 3gWj;ҭ?؁(YYL>,-C`nUκZS9@B o OeLV@lB85cJN!Aٶq/"68m ph(p OeZe>s( fA}Z."kAk6^K;f=DB #}99ˊvg2vZK hA[mP6Yh )~ 92f]X϶|.꙽w"8s.QGr_^^O@<Ҍ[ ;ou% i@!uЭc=`/9z~ѯ9L4ǜlKFxh4^ 듺UBomΊ}0D IDATo%E,aoi{]Ay0LF$  CǙL 1CߺߤuQH Ŏ#h';`qs`̺K^b-ɞۈGU twdXlK ۷[nիqa~8~:٦!]f`RE1 rӵ_/V?QK yW\6 5ۑ1(Y} ,l^L{CS1% elfM!{)` g]0Ԇ*u7I20 $ޅO}к;r5xδzزeyflڴ opС '0F,_n@2RTdq[X$QhŹ/O/|yXIb@J0d 9(@ߋ+G'л0iP'٠ԫ!*+_H `MD3uJ T ͅ%V^zD+7l؀ᄏ~};m8Cp 9avU1RXzT4q$X %p3ޭ֫΍]u&iQ O]>/,v9Y4b㥑IL >;$iqvNE8h@:,q`j處\̯d[W.Vu();`I=0G'V*xƍqF\uUkqYgf'+?k E Pډj^Ů17G졒i$Kȕ40V4sƂ A23&5C?l&jи(J繣%,ueXL>_t"T>@ a%hUD*;;T'oկƹ_~RLjmg/=B?qgyj0 :&W+ @/6M #:q`, e Ϻ 3xtňP硰c u|KPV0뙀.d&P[ ǚfŦ_H[>\Y-:Q9@0/Xmhq,7w!]5$!V ϘI5sK:y#a7JNv*NC f=ɾ* G~M {;vy(4DY7s HW'8/iR9tpX!Aj~j`VH' 7SnEK.As)Bu$ ZRuOLfpW9Na0 ]>:hA"D n4d@蹉/I Mn`ZC `ŔsQĜSЃਗm ]bLWuJVј3+kq&š6F"H"^l}cmXϠ!9D6~ڠU3&HڴL 5<a*c7zRŤXB3fC[^~Y$]Tېw*^R򃾀#?ca^ l)E JMHwD;FR=@q4tuPfՑF4Nz 4cmS1#iS&2*A_]%-htn!j׃uYD*$qT4Ոe֣tӄP\Z}mDCV H8fCWƶ5$8GP3@fYJz:o4:"tqrVb[Hhٺ{a-c{ H. Xҍ%q7ukl*8IMԁ*1_pwNL!v 胶̋*=gg9h=7z@pi ?z ̤]:AGnhTznu_t5:Yj.v#}2%)0m^}s1/-^$6Z1@i?G B^}j`EJrm(AsY5|fzN"?EPƬ[м =僎[ I&*)YSE)FRVVVgU>82ػ {E!oё&r,Z崡ΥS9ֶ5;hS41wtsRP9 Q8`TP[  ˤh 8<XByqОYMbX%D=. !~-Z Y<.<,b܉;xlDfFtja$0aq9 +aE2H(|ܲkl$+\%z +]K b !˟gǂcJˉ* C!DLUUXZ[ ~ZGsRuM, Ywb68}+/=FxYCaMēre 6JƀZ<4ӎ%R9` 4R[{z}L^H] ^^NE%xEvq 6 CYTgάs?9眃_\'wqpC2eWF^Y};6lzb\L[F!hblʐݱڈYx 9^B!,X$lƏ5@m…HzÆ …wy':?0\|q\ry%Z͐f]W¬Ve 5SF­$bZdЀw 5@ 8-;2=DDjkA[t4էU5@荞Ql< Z@Er E?rsϔYڢ7bƍkCPJ :ZVWκ;so)>?ׁA0xj@YnV`ad-y !B>W%7fA{NXἶ5b}W98V #t]w:|NOƹgщhnA;Ma$X 33s%J엪;tma ˾j 8)tpGPtN:gf)WbXI^v>{sA_ũ+@I:J[Onuhx2"X*eo?mckȫ,(hAsKzqSr8|FpV)s[[ב=pgb6%f86F'j='y\"%^ڙG9XPɑhŏ_0ê_`͡ :>Iwlp$sO>$AK`t^H])H}J[ނj 3l@IB7;p2(zh8:i|a8/i6&G梜|.bwela? #5Ձ:ڔP)hq>/D+ $[2哊6`7YXKu?W#ưsKThj Z%AUphUa9Z`P3vҞe4B e.F'`Mv]_%1:'˔sˊ'bN}uVLF@)AѪ_r4CɊ|(!D^Qqtr} E/*,z'j='jHmoYH3p'HXH/4q X6IPp a5HP\*3@cboa9MA-pRԭEl6YFNAu#AjsȜh>D 4HPs#$̺hZug?Wd0j*4"Mg:H$~"h _8%J{BjJMx-z-hݕHG֫SBh=7_t720VF2tG]]G2O} WCaGYLb{a%ͨI2/J#*"@C08|Z+D7h|s&(Ɠ͂Nz^|VYJٍ4<あb(o9Tjт.{𻧢 z@aK(CHH̹5M&F:c5׆b=Ctܢzc4,L# '5pzNJavF:*Y否 5#'uH*KX(#vkPiX=f9Tu`4uH[s{tt( {a*/0;1C.)FjtsA;8]^\ԱҳRB:.?{-Q\b%wQL}k/C -u>?r8[GYHMJrCm-Hv*RPq[z#q-Lx#D@vq8 $8mҪvQ͒{G&Uɍ]O R ᎖N&)a|:O9w0Z] ̀-H+AGG/QzkAS ck6|NzNq֗%PPaٓ6.)TL#e) l4{a"Xԑ)݄PwAcg{k&G*XdhFv60wVB bHDzzL"44zN"00RlH0A Tq=nE;S<`ړ)fdB2&*a琤TwW3&1'7ie0XvvS!09Qy0(?YTfđYASA(IZ*C$-J҂N^ٓOSS;]/ri吏ISF `o1C Y CJCgN $R[̧k, v͵4t/͍ dC9/K9 `"ԷE \- n*7kPi!bZЎ +9*pTJ4QcM%8hY:\ՄVm8IHK7 <:^dOz9 q)\Wpg fA'jgFdjJbOfix=CG1R1/KGxdi3[*kix:ԡQh tyJHV:˝FJcbې90܂q7.WEd{@;}v'믿k׮0T4VaOo9Ujjv0"OMiQATnzat]*u&5vqyZO.e~0P3*SPw8HzزevO-܂;wbΝiHޘuіVun!B'*K%GlX4+䫥_1Gg~ʮ4AW+EkY$0rv($V{8u9'D+7l؀[\{'֮]z({C8{F *ɞ2iE}~ۜ5?yˍAmÛLc4!O윇1Q-gއ5ƓX?%WSܺ6vx9)hъh18pv[w+ORY(Rյv{IDATlMhĿJAj )@cqKsܽ'τ ڼ^Ay+YW C(W(Vsc)Z7`lPId݈0muy^ (~=I@ `^'8i4&kଘiN&%+NmKw4 ˵\8f? 0*6#]Y֍~)ݼIZn 7ׂWJsR&Bk_Wfb%u66,KRKaN [5,Y+PJcEX2Tqh.ǽrnA뒇 aٸAUC?ӨDY+J{QhVu /f!BQn A'0_ʂ@'0ug炣J=9YHb!ZmīB`j"M w,Ɖ!,5ґ9>B DH%TfSZEeTs Th“ώxx)ޖx|*?4/T)AMspqmప 3zC* .S Z6A[L:m*jAKl<>4CqMg^ /8X0n8c A3S GW5òyձr( xhų,$8WLƕ)𘮩҄[Wt͝ĕ AdxsLd]=8hG(Rɶ܎Pǰ]EaD @f=l&j9Fä:FM٪P꾅#,u>e-OnŎ5Q<4 Z6q$$L^U[,VnA>,MX0,.¥@,bm蹸m d0ZBHz .cjf8n7ײy,蘨NOOʀ"=V2Oc5*`L &*w|uA}Y{pJ^ M]Lyc+@IA-;LPVG|X 1% Ɛ3y ~G;BU/_oxLQZ1/uw1 ЋRq^=bEӿQ,.*(BOT{j='Ax%0/T6>Sy1W]VyJ-Zе+sIsuj=&g/<J.vQ:!54so["]6o^dnl ,SS-_sq$jҕX ƠJ:1-\S $#y"81-׏UtpCǬ4Aq"vTyoaĔ*/VwNAEj='Sd8jypEY+eűۚ\S敁QFz"%/rLF4eE,#\r6[tڗ/9:RP7kXlDP`%89NhH-)c&Y)\OzмIg]Erg=h|I)RbQ9 GgLult8k,h/g])j7;Hu#_S&U䞂8/~n%ZNqyl][WB"#+@It ,L+nn1VisQҹʷڥ-lb8,J14(8Σ4zlT׳yU1ծɨEV TI[GKΩWV[,h/KдV%,nSlYN= 旊ST_i`.w%S@F#d461׃ <54j='EkM(%w8(&V3mQlq֜Gj.- g* qfߐ-IšO)Mł̶`fMA:mD*kua*Osl\.'8Zjrk.w,Ƶ1jŧv2vg3]&G츘>9<-&rEQ90;>fWiñژk?#yM[fMA[ddcF܊V,i|9*hV)lu:3mpdծt6RfV%#dl+@/5$T*2?K>{ v:<1 .]uXyBQb>A5w{1giz}2x,\LΜGV&]q'>~طo_Na!MBI+Nz=ÓdG ,F]a:"#{q l.YI؞G+ #}|¨dл{a|)HI3NYxrFyEݫthӽYI3>t\7ő#G} ]txqc >Nis`eJ {UƑji +5K``]ݻ𘏇-OJ.,d{'ܬ~--]c\X']= j@2^?@GZ.ݻwc˖-͛u>]wݕ%Ȭtp./"H&65}&إ#Z*3~[?/S%[B,1IP %36R8&(,<6Px-DvΝ;/?#8o}+VZO>r N9eΣj^l^nxAƕW^38{M7݄7 /X5Zaz tW`͚5ӟXnݲھ};~_O_k./?w}طon݊իWøq 'SƇ?aYv/9'?w]<8q//x|;O}jOO=֭[oqxO'> կO?o}x Icǒߏ;ve/{Ú5k?9眳<`ݺuؾ};mۆO? ǜw܁}ضmz)<ǜGw]7۷?|}<裘f8Ӗ< /_&wJ?HXy5 .'x"nܹ;w_,6mڄ_׸oQyflڴ op!nj_{ /Ş={pgs>oߎ.lYyg?駟s=XV^ x[ނ뮻G{nlذaYx{?G_[?ީt6lP|ڵ vJ۷oOǚדO>|vZSO=|+/};>ࢋ.l6í޺l"g?/K|\6GG>U?o|=>bطooᤓNZ6~/jݨQF)AF5:NtFK~ӟx*|?5݋~?ѣ-fFKЍ^DDp-=~_᪫µ^n p-/ǁp 7`֭83p\r%"Q#@7zR?p?9nV~x+^G}=|AyXv->gŎ;pI' .bQ#Zt,.R|S•W^?+׼&=կo|#wNO~\s SOő#Gk.l۶ ?8n=z=aߚ^߿7o.x㍸+׾EQqjtk袋׿޼w饗6pnt\S5j8fA7jԨqJ 5j8Ѝ5jtRF5:NtFQFSjݨQF)5nԨQ@7jԨqJDǏ%IENDB`mpmath-1.1.0/doc/source/plots/besselj_c.py000066400000000000000000000001521340375245600205170ustar00rootroot00000000000000# Bessel function J_n(z) in the complex plane cplot(lambda z: besselj(1,z), [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/besselk.png000066400000000000000000000356241340375245600203660ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxyTՙ[[{7;2 J\81F4IL8c[`Ɉ#H~]iz꾿?.tVUWy|Sݷnzhۇ{ιi |ZEA޸-  F HAP)Ђ "ZAQ@ (hAE-(RAE HAP)Ђ "ZAQ@ (hAE-(RAE HAP)Ђ "ZAQ@ (zʕ}z/I BJQ@\. 8|0Æ K BJ1L\ nHq%;[E!ex- \GGf\.Ldȑ4TUr%#8t꩔@NNC=l2vұns;zoUUÆ mm>tIKl vg .uvvDcc#lذ!ծi5_6osƌ>}|ҤIׯ7M0.s97&0~{q4M\ :FQ4%~zzL>v<;;~g=;\_.f-++pst6v:FQE a`F;^/&vv-<@K=]ҍQ%V腖zȑGFG=GfuAm qK8@'@ `?tKKKמ"c zq.hYCt#x *))=]ҍQE,!A'7n\AtI7bG]в@:t~sdBJ[GxDQ)l;x肖:lH6GsG3CBfIWKW\R".vTq- tؐ06GtP)l;x肖:lHV#WCrTE\ Z!!A .VqRCAU<@\tA6$39_78v0dH*-bG]P@.R~َ%ŋUB R".vTq >mÆb8Z!C4U [Ŏ* .l~w(--㎳5$2$LӆI*-bG]P@lܸ'x%K}6ô Xx1 .Rv6Gq4t0Z=X߻pB۱;h@} MֱP.\qXyyy~ؚ5kXx1= nyT+Wz9sf7\wii~zu&aZ2{{R\ s ]GeGA;<^b S$$TU\Tq t(+$f`äH+ S=NE\ Z!anpxKL;$! ⢊.hY#$Ϸv|xZVA>~cDPiEQE,WYύ%0 |}tLݖ*;x肖:bHAQ à(rpxz :jSׇV)l;x肖:bHAm/po+*-bG]в@G hq ށVP>JaQE,dž 8|R?V)l;x肖BBp>#\AwH]V)l;x肖:04^t*[*-bG]в@9.Vu5a{-!aQE]в@Ǵ0E-pG:F*-bG]в@G nIY#\JaQE,CB 86ivaC# u#hq.hY#` nܹU [Ŏ* .eBBA)r*-bG]в@G !v*$˽S4ZE\ Z!!t)Hroq.hYc !]a]I_R".vTq- tL!!r !˽U [Ŏ* .eϐ6G}[=]fp/R**-bG]в@gH\.)Hroq.hY3$3}M)HZE\ ZC8GЃr9zpzJaQE,~5 ܗ`PΑ:0U˽U [Ŏ* .ef7sB-:JԎU [Ŏ* .e͵B¦0'$:iqD 8\^bOz*-bG]в@VH@6/Qύpj颳3.'U<@\tA]P`a timGG1ێ`R".vTq- e$ [㺾t#&U<@\tAi$ [=(*@;-Hbq.hY󣄄`9# 88RXEE\ Z薖(!!$އDKG MH=HZE\ ZJ˜ t}hGzBU<@\tAmQBBH@F X}#:EE\ Zh?JH)AG 822hR".vTq- tII!!:jH8Fj JaQE-k׮[o{{o(#h7؇ӌ%VT [Ŏ* .I@8Əٳ袋zVRRBNNZQFбe14#.XP)l;x育#hEq饗2y^[$d OMZE\ J諮_իWaee%1 ,/JKZ;z,ya5n鼕+WF^FYTS..X⒪cb?V]]?f/^C=DCC*a8-"}Yt)~LynF֮ǺuP[kQ[ %%pivo ucǰm I1_ Ǎ7ȼyҭэ#K.?̞=Wq랄ardpH9<JaQE-Б())^].k} ͞3F#5$/*-bG]в@CB!(lo6MXfr@U<@\tA{~ **@"K\ Z肂跾e7Gv̮[Ҋ,q.hYc !%˽c 8220fn;R".vTq- tL!!kCj%T [Ŏ* .evB.5HjBq.hYSF(бɡR".vTq- tCH-XThq.hYSmC`کU<@\tA0ǗCqV1vaY4$JaQE,Щ F5ʁ!_9$*!aPE]в@ #^obp$UU!_5peYRUT [Ŏ* .e.((С'5N`äc `gΐ; 8220;L:bq.@ܹsc:~C(.НBg'ĹȂ###h'GU [Ŏ* .}w0{lJJJ7n̜97|n(.{`:ZvpLq.o/@M4''= 1}[ZZzy"9ڸmg,v߈ .tvv6>+`}#h'G֘,ZOjR".vTqхHkk+]tk1DŽ99]UL7'I,Э_CK"U<@\t!-!)Sؾ};wCGn8AGMCcCC{mםGhq.@?S+<3~_rd]Lz`yoшԇvpd ˠmg]}¡R".vTqх觟~,ʋ/0HRE NWAe]VPYbG]Hy5k?<[ne׮]\;3իW| G!a2 tӀ-mq.<$=z4?477s)p=P\\5!aLz@Ȁ;vnqA; 83(T)l;xBG+VG_Qq{Hr֚#H-Ghq.|`̙F0$yȑm8Dǟi?GqWU [Ŏ* .t^^wy'#G~8JB@C}A}!{ЎC׃V)l;x肖#*8 p1`Z?&;ǍoϚjבܩv*-bG]в@CBuui$nS<G֘,̀I{ur7MR)l;x肖PMmB'@YO_AJaQE,`0y׮oDڅO&R".vTq- t0$5zaNhn&G<GU [Ŏ* .en1c;"㱊޽]Y7A<Ghq.hY{q V4B3 2*V>OH8 JaQE,=C`#j7 {Yl9ή|ށ^Z+[1;woq.hY{@'80 N(=@[>tGq٘fRwS)l;x肖gHem\Ueݼ;,Ijw€|psx[|5ooPU<@\tAgӣQ oJTK}<68Z 8rNry JaQErOXY|9/"@ѣGs=CB?aHzM 8rO}R".vTqG^x!scʕY6\#D tGtGU [Ŏ* .tsqWt3$Bgf A4 /N77cxo ZO_T [Ŏ* .|~iii;>VUUł Xx1 .d9w&G"GY^uMݡc"U<@\tAs%afr ٰ!]<۽0UP.s8AǾH VdU<@\tAw%!8q`~%c߼C-^݇^xZYbG]в@ !4$cODd.XQ)l;x肖oH  9}7&p$sɷJaQE,БB¨'a&DŽlg G2F*-bG]в@ mv KZg ; O|p;KfںJaQE,СBBÀOVؼ9ě yyq#tWcH[ϖ[F0ȟaXޘеT [Ŏ* .eqzu75nnNho賆EIka̟'tq.hYCp@i $q3XNÇmԢR".vTq- tbACR`zo޸$< 'PE\ ZP!!XXHT3Z >qqsZ~ګ㾎JaQE,СBBgi爵7 -"+>ʝԶ} hsU<@\tA.$Х֭lGg;Jah=䟓xPR".vTq- tO?ݺgqг`/|;Z*dP)l;x肖:\H tpދagXgUyL&A>6= U [Ŏ* .e ju/6l_?n 'pjs6 s1&[R".vTq- t3Eg@F|A+ Y˦/9\5zhCE\ ZH!!Ȁ΂:kw[n=frU<@\tA)$kİ0H=tَeq_#Hޙy\ԯ^E\ ZH!!IVcrNB߄ ]. Ꮭ9T [Ŏ* .e`(݋ɓFq 33ûV-kb9~JaQE,БB ^j=zӠrfꨩ,L,еKNT)l;x肖:ZHYo|8ƍKj:>4~HAgwV)l;x肖:ZHL{v L>LO&oxή1 EPYCE\ Zh!! _ N +r8q"L:47͡R".vTq- t0H1x0z*lj= 8(mPfH*IDAT!*-bG]в@5+(XMos 8Y=&yCwV)l;x肖:` kӺ; M/v 8OIV [z9ވ͡R".vTq- t,!alW_p҄ 0|8|%p 9N?wGEVQE,бAz_"dpVΊkπM/9F(r5&U*-bG]в@L'Qnls8C 8Jaf!KXp0 ^;/6V)l;x肖:֐ 7X_ϟ΃x({3}L79\;/wnŎ* .e5$ rV~.W!zˬ{.]ls䜜C4mekQJaQE,NBB2Bس'ʢt_}js_}R".vTq- 0HN2kW^ئ 8C/އV)l;x}{uY; \uE99Xm 룄 8m8K䞖K樋VT [Ŏ* .t.++cܹ0HN|[e}ƴGtcꨩ k^Kʽ ~E}vct!.vTq t8A_n*dž 'Q*}4&:Nω˵'y0y_~<q.hY7ô Xx1 .JС ` *+[X(y|3@p{ 7``ߞ#&p*UwUܱK:Xyyy~ؚ5kXx1= ݰ0Ms(-b1¼[v4Ms̙q_LLsD sRCifg[?}/o|9k\ ]aAHDjK:;;~*z)|>_H 7#Lχ뮋a9zvG'w|.Mkh$tʩR".vTq t8 uo?zH|#Yc9[n(a0~jcT#.vTq- t!ao} =|3TƏ/]{HoU'`l1;pٿ`?{q.hY$wDn=?uD[u7eNv=wbM﷏:TZ%.vTq- t<+ rHO93K`ǎF[U]gݎ?5k<7{Ƕ J+Ŏ* .eN$$ bcrYVR{߄jpcNv5J%^l8fIT9vIbG]в@'S[~0'MlMض fgcpdpǤ;6.IR/_MG*-bG]в@'׿keaNzAp*w9րs$?#g˟*"0F@wcT .vTq- t!aOiZ3뺺B4~<'.KG5(*g~ {u(28q.hY䦛7>ڧ#$#G…[$?QEX\E%r3ޑgcF\ Zd=qa\̄qRN<}[,'G7/QVL,jRFRaQE, {ri- q׿W_m-^կE/⻧~M{{ 9.F?8*ؾ~{BK&*? Zd=yGxQX*K4g>{KȹtZ);? ]+⢊.hY'womm jӧS曎?4G.y,m'qde_gKQ)QE]в@';$IVu|2A?uÚ&wu,\\2*Vø1luk}:RJ*.x肖:!a_;0߆%K`30i-}ft{ޗ0xOSY=̼r.ZD-jlL>FGU<@\tA!a_M9s=OvEf& ¼y?8c k^p˒[ݷEk<AGU<@\tA_!a_nIVmM:d^}*?)ϸ xwrINNbOs`a FU\Tq- t}6kJk+|;_/wI]]p+?cY?@+hl}ǔhf>'6_k/*? $ G:ֽ ^Ӝ;7 s昦am;~Gg9&aN}~ޔo5 Vg6mLZ'a0wmmfe͗Oytnth<./}%Nx *q ;^i3lau>NU\Tq- t*BP̚eEEVaǷmz}L"V޸I&2o B-i M߰ˠhΚsв5uGP)QE]в@*$ Up puX 5//;ۺWyqV1nXƅ^Ⱥ}s_y{Ҿa28O3[hlc54|K"⢊.hYSb#+, GN"kk㏷fvʋ\_.Ki㦱vQ*lq\D~RFǡ]vJ*.xh)!atu/fi k8aw=M#wtv2Ӹ0fGgˮGw+ cY*+k ?"Ԗ Z0[ش jj fδ6\"/^x n.kߎٗ/gʼ)T7E [^> Wʻ*Yw:v9cDŽJ*.x肖:]!a(0`b2Ffz?`-X:<ظѺWCȵ'_˚[p3`:T!~K4\5O$߮g)¾/ W)QEm0őTjkM_4Fviui8`Z= ^X'fSl}0\iUi~_X-V\olkq|AGBڢ:!aOEEn;vX1겾?X&\p=֋aݐvވsoK\\U\ٻQp1rixi~yL~cIO"^;u<4̪ 3W|'sM?? hjE*!!D8FHw qQ ϬMͳ0uG]]k_2ZfS]_Νw.[q3L𻆃 տQPJZ+[HU\Tq- j!a, ju5/nnm+=fb##FZ't d`_dqyu,~\g ۷~3e7ƪݫ2h{LbC~0Nџui?]VF⢊.iNKnF͛n(Ysx^VO}o{^M q|UW[>G5yym 7}iOcEkƗsdҾK{xA^QJ|\^- BHT-Z/#쩮7ް˖AG=tp`WBFsȑpsϥa&~z{Y\ĚJWQec/㊱W_aXnfIZq/촮)Ptq%_/k-$U\Tq $1R_ uq/~ox25]4E˃[_Ĝt5߼%[b1onΣ358.;sa dz2Ci+9!߮h#<.."|N7̇a B?ZmѲ@Ϙ1^x!pdgggcϬGy5.]2|zuIV>$8DɛVtR> 7Q>& egs[2%c3Wl~e=rC<*6{z.ywFUhH'pHNW^y%q"quuYac`vrCLCNf'lCC1ǝwpZF |]ǝU|Tmyb1x |ڶQYzlB7G,2$X9N~Nߑ .T!@Wl6Yϕ~<;r|`#'q1/BnR㽱ElPYF&B/bd18wpFʁnŽM[bx 2G-Yf[[SpIDH>O})**~*S… >}z5pC<ݻO.+jk;md!n7m5qY | [Kz?(/s[ɛYw1et ?<0nŵ,¤(]):Z%^_{JzUos=F[+ʹD  F ~_ӚAk^'3hAc΀F2pj'˟Onۑ"ޒOfG&dtdPy3$#_Zs2spփWs tvf3Mrma EXyMh4LLL1:jĶcJe ébTUU1|<] z ^}~Or1k #^x#x#ڏJG|P.>̰a7 .d۶mn2M'Of'?Fڊ3~\>W&,Ԫ@PVV >MMMl۶ǧc޼y3eee|i ,P\}|ͼvOK---ylڴnG}/ /ٳ:u*?яx'tR^{5~?cǎ%'''-?`?F6 [ǒ3G?a&LH0uT~_ow^% Ъ! )Ђ "Zdٲe{ܹkӌm9 hSvw˓O>[+RXvMAA---V-C?>yqwҭ$iv "#hAE-(RAE HAP)Ђ "ZAQ@ (hAE-(RAE gk>hIENDB`mpmath-1.1.0/doc/source/plots/besselk.py000066400000000000000000000003351340375245600202210ustar00rootroot00000000000000# Modified Bessel function of 2nd kind K_n(x) on the real line for n=0,1,2,3 k0 = lambda x: besselk(0,x) k1 = lambda x: besselk(1,x) k2 = lambda x: besselk(2,x) k3 = lambda x: besselk(3,x) plot([k0,k1,k2,k3],[0,8],[0,5]) mpmath-1.1.0/doc/source/plots/besselk_c.png000066400000000000000000000734231340375245600206670ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxm.U_yWNlf< "\E,0bKY ( " B"$I D@ɵ:y휳tVZU]3hv35U_^)SLsx8g@L2eJ)gL2e-SL" )SLy)SHezʔ)S^2=eʔ)/R2eʔL@O2eʋT&L2E*SL" )SLy)SHezʔ)S^2=eʔ)/R2eʔL@O2eʋT&L2E*SL" )SLy)SHezʔ)S^2=eʔ)/R9lUz׻W_>=C2eiA7?g x?ۇ4eʔ+&ӂnț&|=O`f<裟C2e ~~o}[?˾_7o=y=(}Y(_QYaxgÏ2{NJ*ۻӸU=Wg1y.wpE}N7\*]>\m# nC Ag7^):L̗t ^D] RcڇN7X| 覼-onگ>O'^s]^3gx88RY ̭<P:O-b̌8;гF߾mE#ǫ4ΖGU=Y'>*GU,~itCK{%~WCd;`pȑ{ؖOJP ݲD9#h}UoU]? d5lsuc:w⾨W(el+H<]w3ehY}%%d=6fݳ۠U IZ[QּY7^7BP]JX+rW NmׂZc nx>S ꐦcN]dOԥsOE>.XNuEӈ*,6ύm݀#9w!^a I0  > w|/,Μ~+wWtI5'>$<9s9pX:,fTWY(yޏòF5)lw nE="綷áYu,D#z2WH*wZț. ]oRq0KJoYápEq BV`}TzoYҹ|lkQ@MBC*#P  `;ھڔ߻m6U [rmI*or7UVsG6XK0S NW`Y 8 hj|˙@KU.;ۂel 9@]~2W$ ¸a-W(w@ܳ!NhX봕v tiř<1CLD&/os `kRaI}c] 0. V;6߆yv4=ezh@7!;YXqm /µQXzbVZS}lK|}98W[ť~{MŶS-8o* nm;Z*2W,@Z.7,X7š,͌ЩAb^tΧo^ .PJ~tl `sN[9u<ڗR@VLPO 9nY^t`rPt.g}A͜HxE6ihV46b18<`RJgG٨ dn VK/ vx~v_˂xy 幟2S(q#eP1rVfSUzn(oJ9CK6aԅjgv]6 r=Pݾֹ՗uJ ηkP[稭׺V<ezUN7vzo:6'X~ T/XYKY$vTmPuV&, pHVwǽ#Jh\6ez-{o bʭ[nyx;V{}L:6ʠM8{uG\ )g5P:;v{*kjp.ezXqh!*|~TC^3hcۉu9qgVr-j_>_/u?WP=ԃ(2f{wHVL@mJomc V ,nMdve#]g(t kim]2r0{~4!@p!)sNʺVw} -h`[#Tu]mð_,VЕDžZ$+۩~ {4!(Smе.cbK>&bXB &1I[gO򄳔 蝢&nTfwطU^i[ #YI$,Kk<_5TKJ+ycz#5D5 s# .@օp(Q-]ч)pziK7!ezݏK,@2VlZS:Q0JP "IQQӶ=RӢn dmzX#`n %);}\`kg*_."=0kVhy'VZЖL@ 2mBo^]f]'{zk[EEn|IwCLYіͧ,/>dVrYzPISJo?VFH !G ZyWW&wJ :oUM acu|%:&Y@y*QNhRe 1f :4)R\e= VɁS*5CҏxУ^)L@-&S^ZEқji U UM8U7|ZlDr`r J=p.X|2][ʔSemk2 ȧG-xM(ۊ讶L@ h` {ns p-?Q_Ã;i-噂Wd[op`UX0 ʔ,f鎐M}ߧYυQꥥ\Z0wuSn:NрN{FxzT9]K&Yd_5Nl-e :.{mfRr¨p&DrOߚ鶅ܳa곻Q0[SuW[&ӟ4^WG~G؀NmzQrWdQBeUVXwF]sR[aنm )ׄY߮▫Pv*m 4̊G@ۆzhhz 0ݔ__?<㛄QTr7zFo :n/c"@Rn\[A\TnYmHK@ JnAW2 <5=2iOߔ2ݐ}c  ;׽Qk]OSm#͸a/PknnސY+0fEhE:[@,e[G`y ҷ\:{VnUF]+Ֆ 膼5ݻwx+|s0cO ZY)7PuFVyʝB׀1r i0Ϛ]Q/7ˠnjnm&8}E[V:<̜Rq:WQ&SO;;я~5=bOabުgݐ"tAT$!?mXMw֜am[L sa?,K<:!/oY3:]uYk?^s:X-kᶸz tCnݺF #8vB9 E y̪j i?#GwĤ)fXZƤDD-k08ނ>79_h> s|%]Yǔps bzO\5zY[0*V~d¥/Vrϗ!^&m-34!_1dQkrcŨyc%)8_9*CbCo qc[t 2 6Gݳl/,do-,8YіOyŠn=b/E|H˙⃌ͼ/AeA>ū(clX{)CVƦ7 {n:n7= ܽy-0 "_%\#wلed[k§7YK%\@ͲI+H깰n|$%(@dy/ q3K8;j{[ԝ`a=cjyJ/Ԫo -kXBZo$RX^Ŧˎ9_r8|[ 0Kꅡ { VFCTY>7ʺ<-$лeno0,h.,S-d' 鶨\^i `>6ezPХy/r9r$ D"V򖪽Jzh.H[FFҖn:nax@d)F(3+d ˤ{"5Q\8X[Ο:nY)(eۧŁyE F4 hbsvڈn*mr@7,}Pt @Ū P.ZY z6[ rLcGO:F"m dXRhj VNQ)\:ꪴ9 ds&fFӾ8c}.}.TZoz@2W[w#L+@UK'a*bi2V4y]#`>-T9D9dQ7AZں\YA=.g:&6!~ZM_ouݮmz/owܭ6>X#t-՜n4Sn y)Egj5,  s+?\F*@aKh۠;b;(BziA'+IV6z @nwj[ֶKY?鷺 JS9) mY@?1&H ݘ/:j7@IJ"H0 ݨB0EǠGuf)A& 8SP/Xqf/݀1zNEQmsܲm ̪趆l./h+x$kJ<5E2*mx qY;[8#Y6&Ds܍'LzK]VFzJ B(1`GC; [ 2?s)G%#T>R'c64\7z 5Y1VuuaC1) ?l4C2륹FzT0O@g+DقazQրެ?Qo:T x˅2$ePǨxF7wU1< +D^u ֭Pӷm1gֲq Fd>E+e۰z{"4:Phi,cc/y2me-ަ e⻝ 04ls\Z{Pm"R-U 轲 Vz||wE duU-k;V2U:+Kt|= Ǖqp+2)(]{\@6Al1 9\&D%mĔ nvz~!ԀL+C:m1ֲ~ 蚽 βzNXkfo<K#CH|r(iPll5qK.HܵKCX *3'zZֲuoZ)]9oFMo+[~{6H+DPvU8- A{(,!>hPTYBT[5N>Ӡ X. ˷l؂qe5#_.;yTU'L@w'~'__detF<Xjrk{iqeU,d4Eڅd8u]eJ/LʕŬ= kuz. #QFn@_0i{e!?GO<QF{[q'7߷yk <"!H܄r֯t4*,ai=W*-HW~e*#d ʷߊ|Y3/FWQFzO]Sx8Y&}o//x'|-euѬb X PMUv -0˯FPA)-R n e%KEa9@dPe}zYoR)y[W- >0pw xKmK۝3 <ɹ bw wAl[P|c@nC:Y(!F׆W eIcg.eoT1O1@`zXV n:ꗧ^C 66Ai96vrdzC7o|cGhtOWX|KgC׀3!&J}˚< ] P pv`ASs[;}֔ʷ,fQ2w_+ ]A#n=#If呭qfQ}?wdz0l@mx @.@ކD  V14Q1BR2eGp;R oN_(YհYY@ ۬/a% 6rQXeaK}QeT' )[֝mk-li/rv xl9艰riJFٵqy=NEf`: m9kX_Jrt%jlz)U ^ ,m|_~Τt 2 SmGھ\ޟl9di-[>fidWNckb=g1Dg| }Vrth'u%x~ #k|D 8mXl %K$h o8Ft\$Wr$W^KUz | DzL@l<-- n @iW؆ :,}ХK#[ƥ+#|qq6+H#؟E@wDw u\FyS%bK Mڈ/I{}L :Nѐ2 IDATU;*!\@\Ztǀ\6dm1ԕQ"_ * 4|=C\^ʼPR.@hrBX@5 q񛚺 (;!,.۪U67j#`^7Z΃|ku   ݨ1I02i(B 6F> u9TvWwJUoJ " [>ro-9`.]΋9 %_R@:B+c\X,j0IRK]iPf~iAg)#me eN0pТIAÉ-(Ǽr/چrt8nRI:Wѥ[.);d/mi@F*2}dF7+-ADWz<{h!2jݍݥԵL$ǔJ8kP@8ΰ peeqp7Q>xmH]3OE \5)Lei ؐP}}eKңnJ B(?2#5wE{Y:j]J25֖(p1J'/p{05|*ΰ9m .U̽?z}NK-0LH2[m^ha^aY=8^(W~_5˳K2 -ga=x,,"`,A2p\=`XOŨi/r~FepրN̆/ `EL@m@|_75gTTm݁9 n++(f"`%)Gp`:PqH|w޷0*({+WEd[]ċeS&O譞ׁUg].P_TeStE>[ڷ_ ɵނVnְ#8! -PFL% M#[Y.; `x D8F`~D+57÷u;nW,YR):Cܛ fÚ|@b g:a70Laxr> Ć+FSL@(G˾+uozj%-GC.+F#юws2 dE'+9 ƒ`@Ɓ21. e9fHd@9[roѨg{2)O۩ ;.٦ۺӬ|KG*-LJzPF ,@ !ZB>0KdK4|sHഴrh%o\vv5nӇl1 K^l۞2ݒ~?8~8D`H/iH]v+wE\&1j,\޽A] G^EL%U,L߹z&.-hM/jK=s a.4eN0ݔ7x x[2>{Hކ[K6FyۧBӿH7l,fVsQ3#`!Ӂ\ [ɗbeP+Yddٚ f0ruHƬڴo&L@omo{D@/{;'ó|0noOy5km_g9[΄?+j8Zȸ$%ermµ #Zm/C nZs8[ q+}?lIoWX&;?q{7}Y|'cO!=1XKk _#o}H{UGY^DYmG"ՇEf:D@3.9AŽK#B:_֐`Fе pYؗ_׉g{A.k|ߙML@7}/~oy[~Q|۾WjxF65jׁ׆r1vL=1|.O#(~mV VK@^K0'7E0]DYڃ.Ռj`O. iZ@WPVtaU4DZYևXL0Z/lƦ+ݸ\%vy:]p H7Z]n;0JÒѿMlߕ֥P*b`"x.lKX^{.b #L÷rs`!]Ksڍ|Tru9bX;/N7~HRo9îL@G(SYI,5}R!o/Oಞtsi ՘ِhكYKn.23C|"LfP rًaLBT8EQo&.w#A[m3cך^a(]*yu7-`YYr=%TuS220 g ߙ! J׆3]=/x/\K.LW)b$q~,{Dm!#C_vZ熫KouSV2_"@+K4T:%480ipP5b@(^=Z7d4ċ\Nv3VriC%u:Z Z;{r1ͨ_8w gõ7,fq½qAM tA} ,G9ΘpίėɅLµQ`lu-zFoO+2WH%:lFʶz~j_@o¹Pq񦝴<K_np79XˁpC^cP9 +ZZS9fYeuzrνG׺0{uXL@ވ[u돂x 0vEqZg^Y? Z:&#r\]N60w[՗:טq Y4yk\#`ӗ~{f ؽ::JtxZY&N@io+}|.1x'M+ҀaEs{t;>, xn` f:׉p-Z3#6, WFi'{d &gI| [~듾=XS_4eKulܞn:^uwV*߾A:}J3O8M+JsHtG !P77p A!gވ>bxL|_ d8 V˽'sAD=V ,{Vft#Vmo[O3c U.D`˩vŁC| ,\w ~DAD nq[*zF oY~ӼqyHקӖ5Slalz 轢{3_n[(-PGx0`G}z]77@ɌLI n?u3{>a8߹rb(OE\:oC}9=H3˴}){{[_:*/{gqmɃtM;jjX@Z.&:WR>t vX.w\;7Mx`n?N8e3[#4,fdJ&x#=t jQK"̺p4 8zmkݙ|34Y`zh@e {[ty$7[gGyAx@?[̸n$+څB9~%akHŘpL5瀇 V,@~Oρzle q޲e|'5-U)GR!Yܟ³1/_{ ?[k}0A!ƣ ~\wsx,+8G\ AtE?ȄM(ۮ t:mw4`@c@VՖ,o}[S?Sy&~y{ ]bb\(Kmbyc`ybŴX\ұ|YsmlӺ5T3Ȱxu~;7x+:NF9Z: p~@!%ˉr03ƃ̸8w8zG~G܁p)Xٻ1H'` do!X0t#0JU֪?x _;w֭[//ƻ{.!2v0bYeֺ{ g92/BBUI~l:,jc(gw|Jx/cAv\<A wAt K܆2UVr dR.hkVϰZҝ xt,=~~oM(?e{,묷-i3F3a- a10!}g_CiM8˙\bg,=s p^ \@|0@b=:A_^{^{ K7aK˿O~m @V=@ );kpe:Z9p4 V1.p+h9]²g{pmfG-Çۀ i x (,g2fddˢXd2g~oc#-ЎVjKggg O?łLo==h!S{nvM0n`0vAfoH.3Bx$a;۾ʨ1z^Pu@#@t/?!% w][]mo߾oo#<1hh-{p߲m@99!3pK؈cxp׃} 8{ɵ'!|.>3 xCil_[GOgZWhi{M; )޲^-t,w[[W7}{O++7/雾 |w}~}kmy(7뜰vG,X~h{Gom_sű tK?|=C:p7!W? >. X>%epe,=WueuJoŧtz+xWS^o6Ope/{[uO~_5_xxk_ ܼT|ړ~%7.ue=` sn!"CKm6 %S+8Womb.qX8_g ^c 89sv8c@p7<zA= 7Ag ΝX)|X;r\ `9|a94k=ѮNMoYuDaҏ8>͑=S,yկ~5~ykO|o |k^3_/|1g(Nr֫=tNԫ8Cuu|h[e~0ɼt_q\#8οH>} uVvΰa/ ,x%z/у]ÑO|5g?}x]%p\<z|%p Ɵpxl-~9 H} QM:O=|0ҖnޖU`_qyI'?oZno/z=[(ezvRxCuѽbF+8,pnNs=p?a9f|+pnي88 sp{Mt3.ْƥɚ0] 'io]萮|ܣ;ʰ#QXO@ou߷= 8xDN+i)}2.r% #dR Ua _'ୈBW BI0. >xV\]M9\p c>2`U7 ߃Y еi}'dU_U z!t^c V8yp^|=KW񮴐^LvC,E%v IDAT/{@y'Q)/kp8.k#Q&n-v~3Zx1%Uz@8KNfQl5hYqV)Sn[m8VO@'yMoz ee+Â#wV/_k8nf҉ѫ7>| Ѷa>M| f -x .nיq.`Y|ywXo [-HwY#nC.F}]I^~$ܵ`t{G݃]> VV}{mҊ8Ê4$8_{@`4sOsٳ*Y8 sPE(!塡-H@{8jitp>S -*vt { GگV|ݿ~ q v9s@M"rdz ~]?"}j]uƭKhG˱Qo/dzX^Z_ڭkxnvжIAgr,aw\×p ̸z5YVb:D۰sF̝ GY_ԡz[LNHϘu9>@OsLsNUhP8Tz:nvrhk -8F:j}VvUHHcP-6. phǸ梛\J{’ JSj!.jv umHAX}_rsV,rr}@o ݢ-7t|y{lkyހ+Wo>=HYC>.].?bssf\.3n8o=l=pBu<N\º+_=/gm{}ioӝZ= b?ԇ)^&wuUfuVz۩>> g0jsCq@A-?JAg h9Px雴&KX˫ Vg>djf`ȏ\S{UX[ݔ d/Gch:=Em$kVwK(G0~R]u9o*2_]wOc?#9\ݑ\\UՖ@U `ܬ;0WMںVlƫ*лEσnK#ݳU֪U/ `EkY-s%`q  Ǵ|.p9saA{+ 75hXe.1uSss5R64;){(C'L@[8F=s|X5[CBZ8rrGaσم8.sdWo9/ACPCXԬ`]v.U^[ZFt{⭲)^&w;Z6Е{;oW)P. XV.h)CV4p||-|p_ k^|.#%?ZΗYRZ=+l9{]u-큳ΟΞt~RR>C,V']'0-lu2u7Sq|Gl']=KFJ'`~0hzxL@ ]Jk4woȏXljZi @-iEDž/0']ux+9zdAǕa}LyG;ڼ\1 P/@^ռܩSwi+U*^tمVTm*_duo;>(lڧN綾r f9Pk>x .N֟RDZtH߱ p]\rvH_C,v]_e=]O?ez0G ^ڐDv,oܕ]8P& ih3+5C:A]~$KY)\× iY78~5X[ip,,Ń9i Ƿ;i5>˳lX]uY& ԧ>7pm=k|a ЧSHʏCOUVUsÿ:rx $@!GtiX99ZT.D qe~JeZFh^>Դ;8/:&u.3ev'L@W ?? ~|c×~B8j{:Ti B>-ji}d]OaEb-`ⴎ/f$k鋖c\%]ZYҒb=QaAW k|5@k*ozRfݱk >q+x;Ywo;~~ `V "V7l:AYN0^DDPpy @=8-a mQjpJ'+|VPtk p 3j!?8. OJ9duQyew(9o/`-f&5ahI 93ggʦ@s!΁ήC WGtL鏖9N":-ʺ3>j0+JfƅgKγRM8K+{n6z6@G@BC)D}#A:}:-ii9XZ֜Ϡ1tlSR>!ӧ pgȖw7w^-`7}=H[vƨ: 2 dj|%lC2 iܿY@}'82. iIAc֖tswiߜoلr p^|3["t1mU+t]K!^nY'L@ @p.v^nP-hukݯ {B޼1rPUyR P=,@,hRvv$YۅNAB|q`S >MǓPk%lѠ.sezD7'[h Nt!/伎DZUTdژ̴҇t!۠@ kZ8AZr_E OOI\[9#[B]WcJ:E ߀F>])-?>c΀G; 2}:VPaủH/kR$M7 t5#9&P V3=➒<K8USx`[FпIQYO擯j 0[ֽed#qsp*es0y# rpk'륿W YVh- ؅ Ҝl #W+T 77t-Vb`=n/?Vmn!랺׋l@mX6zX58XW򄦥{$ڽQ.&5!pnU78j}$\bn[N p~mtj[齺){E:ޠַ \cV4A[C.|2EeG>FP"}p!3}",,]oZr,gx5^SɤH$qbc6{uM0[,@k+=Vvp܀3oZ+KHwG5 /ٵ}s,yxde Z3>ȦU͵J0־"V@zI=#P)&wfWu)̵nq-p[0n)H-k:pnh=v[1?|OZצUr. NSr+6flmc^NcZeߗ-x -kp ?-@aҬ@Թ^Y.XvV$(衚1װ22,\x."ф@,r}L@ 2}6X^y]-XJ/QX+_JĘ s5)57b0qQ;~]X 89$m-*Z׃(4)cdzҵ w \hof5WQʪ,A9%KQ\Zص]Z0[Ż_;,lS^e(~_iEdsպt#= 蝲@ gtv4J/,u!M88$̹p}Xt(-hnVb`V;uK]$M AG+(;h+utW>#zZ/lU QXJ5A)u\]7׭hzF)|{Q<^ȏ#>&~[Jkʂq+"16\;eM`B^a3q g ؕ j.y vqy ԥO|AGhϺ[qj4 K˘A.kvjWfL@7W~W׿GT @pMym=rؐi+? gJE!"]X2- -Gˆ.k5V=Ccj8s7Au iTrQT}FԓpmN-uon˕?q,toɟIT FГ^UUvO]-oRS)nB$l#ڲ\+D,֖g(CAh@hgu%u?6uVYf|rِ+׽u ~< ;}CگZ>| <5@lٖ-ъFoN@Mo~ `PnYٕo%̭p޵7yҖ&nR=j0Gup 65u^b \wC?_җ/WЖ( f1i'(ާB^SKL/cy' \,NE Pu`@-,aըSCjhiܽ79߭Ѓ6i kۢ .t:?bU bzJێq$ j[ThU$;YZLHY*p>@;$Kvi{[`,\03) zhm/14t+^ﻪ2[ `FBă6tUU=..^i%{ak?GvyQZ]jKt dk`i7#,z懆Sy~E^e$tϖܪw`( J?m+!'4 ~'00щ%#<7 <UC9lkLJװy۪YlZuc:22WQz=0KHVE@hӷ斾Z5ˍU1b>o,#]##%ĵR鞟ڲo ,a=ƆNGvOezgpU=h#zu5b/[Mb[ BF|Z}, ,N).̣ĥ K[GmV~CѲ5-kZZ bh_ 1t tu 0N@F;N>q<.YG!r};K<дͪFnylo pV8$x_z=\Hs#3@lX[P֖nOU2[F۞^[-ȶڛp@_~>jʆclPBYf[@޶1LkTzJ >^l-!p_m1ظX쿺-X€NQDZLx+sVc$Cڅ8bP7'bnWV{ciYCWp]쩔Etu+6tZp*mm/vy8cvJMsպS&JJ~IQH$Y8 yqJ w'|iRz=\l:!97ѹN)q44.u8Z+yO;^oY2W @srُ+VA÷Y^ ٳ=yH1t )9X=@옥r8𷪺Ndk^x b n.91R]ÚbL{ Gm3ezX4T~+,!ޛ$܊hcoʐ&rCuzu[E>}U3| k4,uB  Co 2gjXY[[czY2W*@$C&i`QM~I˲MP|9kr.^rWdppPMq,|ДxX@;r{=ܚwPڹQgՋgU {m \ Xl 0_ FDPpF͝x3}].>mpvkQ.?0", ~df]T뮶L@$ ZtIDAT؏ȷ@#xԲ *_>"sfp -Z.b^& c 8 c\腘lP+ -KmUo/ƤT5d8v~zo ({%8܏7 8c7>,۩hrD4`lj?6C |s&,qyX..u;-{^ϰbKo;hM8e~:^{ICW+oob*>r(7-"B ML "1 #&1Fc` Q5b'€!W Rxy+{̚5.}fϬY3:蠵ɣg^ 58,iѦYTZvxf[t$hZ[[~1k׮Emmm jژSJ2'ON% "ռ;Ln5O,&!sՏ1kGnD*-&ƅ2W;/VHS}#X>#9 %:쯘<<uuu ӧOGXDMMMRh4Kǚ Ȯ2 jŒ ꙠNdvQM9xH 0:k[2MqjcH~LPcl""}0Dzvfz(K}q,^X͘1hnnF{{;X.T XXgY^i~BByfXGpU(Gy-M \$zQr3[C" Zڲ<xWV._>lHI>]<цɓsNىjkkqС?aMd64cyD+Ɓ4vۉM+?$c9%hvY"l6(/ΰ odHɒl3NO0y4]wܽ'uВq-`ɒ%ƶmⲛFĜy3J%Ȍ+;|$ױh2Pq/*:)QԢVHPH y->{tz Qbs:L[?(;mii?%rzTw!!~FGK JvgdA{! &WyAM`O"B[K[`ͣli$-6]$H]`NqԹd#KyZ}X9-SvߖC!|HЉtHluňa[ԛ<.c:tNWW>/gk[쭦K?8BJQG*ũT:GZIw4T¢jEi$P VNf6Żj gZtNmfq `$ײ]J)g'LB!N=G *#tYRA}Тgi:aDi(MIi9]#Y'/Ny@ >(*{hؤ mHpGT}V`#GyZ:tNEd]>Y:L;9|ܟR۳7/&z #HGs.a2E=u!GV#xR}6(TGP7pVʭ ol!by@T  +eAzyJз%+`j>S<4dt"q 'NurmGunHdb/u` T}f\uLlm}4[ ev.(}Fi*y@At@<|˃yfOR՗2mHNpmɒ||&AkL$a`/w2m)%ڕ: ]Ni&++rAtV@d]u D_2ڗ9j+# )Ff`_[2fm˶^R^llcuvB@<ӁQ%`/)eKSOM'+(Xڻ:ÍʴIa.%>6Qd)hm:k*KVhBc?JovyrOgMй % ?mHߔpWQsJ@^*ωJ!K!#'R ȧPo(,'7!=}IB-e|OLI ȖIo4ԶԹpʵ׻ŖLI>P҅0_R"h`&;}A)|\B[zy~5(F O¡ztnYoJrPllR>UTʰ6WH`/OEc ܼш6?<|)qMx<+IyVߴ|O*#ͺ|Љ,_tqʝC=Z,1IRfuA<0n/h|Ix1~_äHވ2lD:| &~D 0?ӿtb촉Ov;M?=GP=V,#bԝQ1 wxZضEk~b'b>污YOxJ(,j?@2/ܞXIZMkUЂ~7wo`޼yai _>Fd9Qui6гYtӦ0ΒcTO푴iq٤rk9 |MX'i>P橓z~I-':\i&yamwPՆ97% X#{5H< i&fD6`&hж"j3ln9]r+K+Q]WzA:::ގW^y~)9gyp=`Ȑ!1bFQFUtYΟ?_>|_+qy~b}]MӃ&L8'OĆ p_o Z[[~1k׮Emmm^x_}vY>Μ9իWcذa1t9Ӄz 5553f ^zm__|}}}2e ֮][<fΜ+WV"š5kpY?ׯX_OƳ> &+դb-[0{l8pb}uuu 7p"jjj*|*?hiiqpcǎxG҂gϢs୷Bkk+S~"x*G}G cƌh_Ye\t)u$t) ākƌFss3ގƊ`|ؼy3}… `|wp/ҩS0k,IpIx?Z[[}*{bܸq:u*+ÇqwcժUxqqL<"}͜9?0"<8quuu'͛1lذ9\ڵkzzzg ǔ)S*W]]/ܹsڰzj̙3VӧWE~ :k֬sݍm۶U| ̙3`Hq,_zӃEaѸ馛/h{=<={6u֊i޽믱bŊۋEaرoQ~Glܸuuu8s ~m >b]-7 < ]^W1o>lݺƍȑ#qQ8x Q[[M6ҥKhkk1c ޽JU9hVBsʕ+Ԅ_~MMMc H]k;>/WVЦMp7bٲeXb{9ѣۋرcXn.^Cᮻ^W9hkZwFWW.\h_MMM4iX2/tٳ ͝;kPG^^^^T>J9e7%~IENDB`mpmath-1.1.0/doc/source/plots/besselk_c.py000066400000000000000000000001771340375245600205270ustar00rootroot00000000000000# Modified Bessel function of 2nd kind K_n(z) in the complex plane cplot(lambda z: besselk(1,z), [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/bessely.png000066400000000000000000000463121340375245600204000ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw|S?Iwi)-P[QzыWUAQ+(PL+KYڂ^3MҴxHBWwޯW^瓦<~"DAAAAAARxw7DAAAA>jw7@AAAAaVPPP(A+(((HŠ$b E1hDQ ZAAAA( QVPPP(A+(((HŠ$b E1hDQ ZAAAA( QVPPP(A+(((HŠ$b E1h"iO?Ç) sXf VGw7bbb Z "Btt4*** ,,LnjF#"""$WI-6[nhXf3ja0pyw[ ":KE)**^x2DD4b7̵|nKYڈ7n8w7AaŊ Ν; .g}{nKYI Y _ԐA+!YI Y _ԐA+!YI Y _ԐA+!YI Y _ԐA+!YI Y _Ԑ!$4|`jkڴ:uJ9hY>!K-$HICMM?R;QQ֭0f 0z4кmw^8޷v>}bCajt(ջQ+d|=|a=oTC4I !",;yXxח2A/gm`kб*C;ہqlgF#> 98$&ԉĉ2ÿJgtiN5GR#:8=zZoLjN#6n" & J3Z3LZj 4Wo^J)Hy,{R 7nfd7b]J\\'zaΰo+ԂTD㶏&p/ވh0xL۱4`Nv;v%_~NA8gtȪȪw*J^a."#/o_O_Ta5{Z & uH)IAJI 23Qi{#182; g*3z ЧOÐbsŀLDQ#>|=|=ؿ=x6V5ޛ 60g!RRy:~dbnj""P?Oc>XǬNݚ?؞;N[z10 h7N_S_GZiRJR\y'q$ʫ˯^[%@;mSœgn\j5{lO܎ KP~rXL77@"KDBxyWgVeeߞS vBM~ 땧7K~.A웣[a̰#d\4SGk{(-e}E lhZ"C=;v W>2!ι bڌywQ}ѣ*>T,III޳;v%—[~y `Y"6 grয়0>$IړZX-0)AzOjSc*5w=z?¬BC4 -*UX*UTf뤨hsWO Gؽa.-}oquöڕbbXvܡH"*,dQn.0VTZ!wQg#F?,qNBb~̘oEO7ِ7dgd=!G(븯ՙSC =šVV._ |Q"?" %mh1NĦfkP!qg;V+HAGű /CRXEQ!`O G嚂}جskc06}p0{O @u5YYY/nbK&_5hXu5 Ϟe'{viŊA;ߏ]v-XM_4A?gӭX s|K\6&L{zίYxf; Qc13ǃG#O w0 f:M7aŭ((:=K_´d6;ʎ+Z vCW}K Y`04W/ߢ/QTT]MJb#.\`_ ެg}]뫮;8zec_%8uͻucm#1mZI4,ɌSEED}DQm[4vEGF}h =wh(vjh Ҧs=# - wLWEiUW}QTk@t]DǏ1VEk<A-vT,|CչN7h2ҏ[bA)8$Pr%:U!CP] BOO'z=~l/'@At-?d/{kS^NoтDwMJWIo]YQX-\Hy3D%%^]4ɓ'5ʈ b{%2]w-Ngrr~Ɯ4(7WD_MԦ LDѷ ͧҔSH5_EI5jF#D]^;]G(kQt\?4Ĝ?OԷ/kTǎDzjL5c% At6X7ROO~XݏI0 tye:ѳ1~ʏ:UU}1eGD͂3!Y0RG׏uȇ!)9DoY:n`rȥSl ~(yz2U9a:ڵD#F>(SrKvlŠ[{Gǎ#">Zɵ/ BIZ0}guO[} Az_oQE[o>4bI_OZ"~|<!dDmٗ^bnF ;AzZ_)ۧP\~u?@SFC塂V'NM>uzP|2i[-E_fI]ݮg5?k)R֭[G=]߃>|8mڴvA[n%"s|;7pD|9ra{ N"C=}Uےv9&oLzt#XwL,}-Qhh": ߎ% f/O'XOӡU[ZJ3fߟX//9s(1+#") 0sA֍O}F{kI8)gimL }5%L;bs[hjʉ{C{\e @?^0Mf=CxC'3g믿^1W}edRZ͂dR]M4e eݪ7MٟQ;ҦMN *-eF0Qlɾsܘ8*; hpE7V7psXEN.1^E:wӒ%./C*.>yM>%1<>"*,l6@~e>}t#곬~ϛ>҃Wf3la ܉.;ͫ"#v1TD7}}a>H@CsΡj¡Ctְ^!36t)tf̣[P@4knf\U3JJ-"jD轃m:yK]ՔPΧ9t-8]YUwgs.F^J~wu惆J_JX1hpאKm+q7KJ %Z:UkfLK/NOjuYDee-p^OtZrrXÃ5M?ltB3RS^|6RbKK>Lt"$=1xEO4/_A?iO/E:woAX!aUmoa֭ E_,#5!"/(8>2_+5l%=D;PJ ɶu#^{m3ڛ&3!tQz !Dqql9Ϻh~q @rO콳VS/PiTTȘr2pOLtKx\8UAopS! .]ҠrԧQʞWhQ2 ArG$\?xQ`fef3 l0]TDݓr*r`~hTg0yطۆ=VP_Ўbii ]6"~xUo0_ET*7cDDm~=B `|xo_4O 'rO`ra ~UD߂c16lF^϶=9(mHBoY]]%(Ue>TW9.tñc0zzĤ>0$ 0_$NZdibyy@Ϟ'.]DiZ˨Mceu2BDX{v-^ *۶/=: s5V!4+ xt]>mUUŶTv&Nd;BKl7߰7R<U܇>0@iӀɓَKY0X1lN؄ QTSj}ܔ zc{{٧5"Ro;~/Sq'ɶYm9">]|hox:Qf1$:[ٶvzT?6pw7Zޓxns5WUj:U;>l(z-Yx; |{ۢn8*a}eW_ &Mbf=v9EqЄ~]`܅(X}$&v?4x[Jm-p pp0pS: IDATJkđj^+p+:u{/I`F6%H)IAji*RKٿ32P+xathe .@Զ06rMw7|}joVAM\iS"7vg?Μ c;qop^<أ3H]񯍘gʫ3'=##Gze y_A0 l.s9M&mlvK Qhl" 9سfwᅬϱ b=[n1q|=\#''Q] cըΪo-:caBŠeʔ)ظqC%bǣG+qQYv_?Mr ^[_O?A^ [x^ jy_!,LPHD;b賠۶oC<ˋuNǍcC}8ٯ3+ 0w0ו0Xi+. >m>>,g`"$( a/T3TVd$& Cd\l5sýZ jOyha=ѣM끞a=ѽMww?'"JMΪ(@0 #Y-*x{@G޳'}YŠřpG= hloӧSf(5"&4k\[oq_K }_0fҨ~'Y*~8xuiiǣX`]F׿"!rAAsTW;dHL#X1>+VZ -gO-"G)d\c5Jc%TPU2-μξoC{/E֑뢮͎h-uBY( ~ѣ] r{{GjT588fݺRa))0cGg;vNC]B`k08G[(b;mqdVNOgؔ #Ht:V BCYE $CCY'_?W5LZ inn5~w 6diaMbbv?{v+6 X3-!ݼC0x7O~K&,AwCnFf؃}|hFWhݼx'5di&de1lӆ Av)%%ǜ<0i⧷4DK,Nǹs |Y>!=!aM +oT,t &[PaؽC bj5wp>>1⋻-)A[(X]=>[CD94 _ԐAnT< %:<,+gtΦ98B &$Olg ;+[-y_!s^&L&x@ׅ]Pyn<-AI Y8 Ϝ邆f#;wfSw;tp ";V™39 f͜~/Ùgpi%*Mb'HN/tr9|MEI_MYgF^߻Msij6}RC=B“'J*R†x#s'S|m>Ƭc90Py՜ b:3.>v3S!T 'Kʜ&A7x@ \iNk LmH/KƶGۊʑ :'G*t [n@q &A7S%$/FlX+If4HG;'Po|c͆(bQu !B0ɚ3`>96}RCTHXR:&906>`; ;0fi0m40j'_sCmq-: g}˛6<MFh>!B >σg[O <0P6 4 _Ԑe՟5WO?v-[A.W]ƽߋ c>fTc1U¯&4 _Ԑe0!-4b["!JKJup;z<Ȫo bH L9|MOcth}pmwn(!b朿2^kAI Ytc!A0/Okؙ=v5u &.;hY>!i~饗ЫW/;PHX[ ;>~ة"OI?aɟK_'0?vX6)S7ҡU-_sxOjHڠ-[Q =n($x W:Y̠}|ŋ8XWy ަ.pFiMv&őIO'j ~ 1gswtqD"]}ؓnu(TUt$籐e.A:sjJj>B4-D=xkע_~׆vOz"۷1,t"3?? c挚[eH#* } 6^[^xxOjHڠڐ0#d[[:ϝ'|qC޸:G]Ҍ]QxxOjҠ ϞeyX;p-Fo| ս_PK r;]wq\Rhu\R砉gm$&Kݐ`ׯKg۶l:O>>X0vCKAfBӝ>9hY>!tݐUض<X  ~:;t '*Q>|qzG _ԐA -gFplLqZ,?*tu\  g}ZZ .>hv1!Kl@Ftt ۸;Ygx 2j gm, fexMؽgQm);S Eנݔv=YI Y%$dnc':t])Pm9,\pA@x{ó>.5LY99"y-!".+cC>"#oC/l. ǎ4c=׆())N\NSۊmi|f A xOj|rرeee?-[rް0GF g[_`4t_)џ=YI WX___t,DDd2Gx[±cY0P!x8U/%Bf^ ﳵxdz6}Re=c |HIIANN:ٳg̙3N[Y :يJ}:}ϢXQRgmJ111Up7⭷B6m>wppp av`@+\ ݬ3tw)4׀ g}x >S됸Q`!ai)wLH`Æ9t<ݥ  ڧ闝 g}}NlA,jpg̝N #dw >joYI Yf`X׼hX-̕f䔺gm, :88e=d@RêXe-yރ _ԐAm)o8P68} AAԡ;6LrhrrJ]xbxdz6}RCm U* )s O坂d1P;^*V@ipiц=YI Y%$ 4Mt-@X17'+!G֡}xOjҠZt:;90!ܺ`卖֟ _ԐAF F%S'`18D+g g}!tvZXHNN>V^LHXSC+/$¿.!]l=Oì3#`P]g g}!t׮]{zɓ'XjVXQ5,YA/81!Kkn$AGFu++wxoz󵠍? bxdz6}RCm2{;,+UU?[g}4&CBπ5#` :1!Kn2$tb5qC>A xOjҠ 1 x=9Z7hރ _ԐA7:8IPk@AU[}Zʵgm, ɐwh933868jރ _ԐA7ZGDuNkىPP^ ^r{ó>4&CBAuN1FpTULd{ó>4&CB Z1Ж{ó>4&Cbo_FC^ן _ԐA7txݳŚ8߃=YI Yt!aE!<^u1$8oм1!Kn4$t\j(E]CBegϻ.d=T^*tqA xOjҠ -ݶ]cwmi-j¯TM?YI Yt!#8l@gm, ѐЍcIA xOjҠ ٽ@1!K;$cXC _ԐA7:X6Y=YI Y!@ʳ/ǖ%p϶ tu=YI Yt!J jZ:TK|y?YI Yt!ŠZ= TIDAT -OZ}sOq g}!Kn0$8Z][\ ({bxdz6}RC`Hg g}!x9Ԗl6C!vA xOjҠ (qke wx=hރ _ԐAѢ%ރ _pw/2T*Z-֬Yoo6:`RE Ou=xOjHフ+WbŊhӦ =`H@:II*b"bxdz6}R=茌 ̜9ޱ)S`裏P\\ݻ{\PI*jc!cCgm{]vݻ&O~aÆ 7n[9ؼy3v܉m۶@kdбxP,4s#!5/ԎTܦ;vX\\dڢhw}'u,>>;wŋQQQ)"!uIOOҥK!JKKl2Z6m֭[WIw $&-w6>=)m ΩƉ)TӠ8[nXti:[v g}4& hy5h,(1!Kntр@rIE"x=c.,\Ճ}xOjҠIH ڎ@uňJr2hgkgm, 0욤Rj(̒E#xOjҠ 4I:*O<#<>GCgm, -T -wgoԎH g}!Kn4$nٴJ#A fuf7 _ԐA;:kЮgm, ِiv g}!Kv6$z g}!Kv{HA xOjҠ k= g}4CB;W+qj g}!K:?4jv g}*": `R-[`޽ Ν;rJL0x~գ[NTTTp.83{w=_S Ig|ZSn_SD[iJ#v?OڗMrUvt2MML*two}91*cNjx|ikAڳ90gVh̚]hB#MAC{Mն#9 8ERi5 ܦ c![iwׄɒ2ZvS[KԉM,4L &_?:.x "8,FsG13('WLhbUft r.bJ1#CSfZY?ogdP+2O& -޼JTNg:Nꚝ\Ml$n?C5r? uoc.A4gkW2/ʱz,/Qk#|Xe]c__2R)eD8LyL_5 _JOކ&Gҩboȟ뙈iɶԠH̭Š)TL39b`LA#fJy<5YX)R2 $okUh+Z6VXV^%rZ%ʱpd[ڔqZx6\j&7IɷխYIsQZ3L{`^,fJϡwo8\O#dޜzrU™cƟb6ljesMmʷ::N&f&%KchVq _UvShj>tQ||hU `iPޫ"LQ.~ϻLj!9ı%x5A{r&p{8͛WDL_A{UT@;*hi$;g-qpc(j.v~;6کC)dcu)MRa5T7ԯ<0ҡ7Rl,MZk-VunQ}eMG ݠ{+|Iz-/e<̋<6"yeFQ@HQ؍]թcu[H[sXo- 3ę"ҤtRo*blkGe9js;N"b]|n2oWX.yyi??=1NOnGۊ}LQnMF4bBpRǫT-qLrŲHae(KRomv\Ngf2=;Uhp#0q=ɕ9Bx/>&qtzzg>mEenU\wi¢Z≒hjL:PY-6)mrĎVJiJǰMRUelEXٻseIf7}M`q MnծGY}F`Ĥ ͂h=]]A=g2׉( !Rǧ =TrU PK3@_Ԃ@9⟪ͧIijW v R$)Cmb@Qa$y14B[pMDH>=v,jL< G,8O߈12b^5dnj}EĈ90kqM S s 6(OTs GM9[Mh?袜+VvɱU<^Q; sYw^J Cm4cv3Y$F1eDQrJ*m!a{ &"6q,(4aj68S!ׯ&HkD b!e$R6TF$Jѱ7CcJ.מ ўf&fE;ze b۩pi#LgLh#aA7RuR-IX`NOԹ/2:U,H&K5DٞZ5;-ikRLuۊZF ETTO v_SS4sc]Trm5k]CYfW2@)}JZE?H`.@ هtgikR*szOCeˀu:Sp'%1oB6kE\+%6Y+k2J9p_>jB)ǔ9[Ss볩ҊG*{h*@5|'(7+byټ= Ri>mTQ Zr u,%XW3[ѴcM(:AW ~NUb|^-?aXn4 $Z3q؇$i`Ma% =* 0O)7c(" *lHe `wSJe̡Z>+Ɨ~rN(%g' 2ZlTf45)1qtvLFyUڬ耒i*!e;ucRe| ud%PTy=x X5Cdlm^ՠ ]ECL\oxsZγcI(mXJx%TItK:2b~-,sV*> S&O@z[~\9p>%T5/C{Ld(8r:v_(]`:d*z f.h 㹴2zPҦA-B}h"I>fu7A>)!A* qj2%A\tXk.DQ;h$ I|8A +rIMyi> =tIzچ {%^~lkiHuX r舃;>Mkh"x`ÝG#d.š4tnh( c;ZXWv U4|F~Yrށt֠GhvJGuUy֤G-ZtF6]vlPGzE_7Ewqt\ks:+ D=W#*ͱjaZ\SL>m'?;H3@_T0 rܪ-C@Pӝ6b8 Ң?DǑV]ET#Ң=3d !S1j#- %)ZTiÔ'iCҜ V#3}MRA5h&8]Ӊ@!?V flqtb_%l$}ty KBZǤ1 ΉP20ӆ*Z}ӡ%-!dHhqy?Yik3!h^$[ǮE@P--;CFkZt5C(r\Y]U"uj f\M/S((Q5u#f^eAxʹ2 8 @\]F2ws>'h|w}?? ŨAStGj-NL N>p6LN+ُ0q-ƹ>G@76YBI4t9k1v!hP+_֠\fRh+WHP։:H*9=A??ΟS7xc1SCeQbWCHpԞTk&JXբ5l H-~S)X´QՠshQZ :c%ZN6h:Ҡs䬕s+M= dj,=/u~6q4t~z^x!hU cۨ'ZtD_aטՃZ+G**y @DH9`"$Bq׾ 44D0Mʼ*BTtʯGaF|RL-㗮=CJ*'˵5*oV@Uo}|mfi}}s|k_O?͇?a6/OJmQU gDA ="%\Y49FNlбKҊJk gmjœ"J7Zop',oR3k ÍXd|JKq<ۖTMkеK=kPl^X V_U>Z} =e:F1C*ZYc4sĮ k=q)Ft-5նҦJD;xD%Ɂrny=_~/A.٦"B 8KA⠺Caz%4-~A2ZW^+4p/, 3Y}w~'CƜYsS m'y똪858EsLfl3 ]<@c }M + ;Jӿ.VW<1Xd?BmC|[R&"Ajc6aB|2uhdjg`Pcz\2nrǯV2dʋ/gHL8}Cb/LsOyZi9) $e\jbdJ8;xٖ>){C4;Ӥk-QJN0NVՊQ^ZA0{Ό "h d&i5sG}Y0s݉?z %s1o εI؁*+ cK\BO+UJ*֠g45)ؠ=@ҞJ{ҜCVrN,n^˻PǎMJ“Ǭ%ɞ#88=􃮱OOu:@f\%|PأFhri`O:#i $š.3« !]%vNX_9i#^-)?hyV IAװ).0j~LW1Kʋ.N}_ФQ0l R 8`bT\eN9[A#5![m}Y b@(Y>5:z0vS3kTy.\H|tM}=AW^VKjjZAs]?ibW5p.knC/T9ѦcX3i֠SL {\2[6tnԠyJs6Lf&*I\ D˟S0' k :L V* jTܥdaR|'O$--WhMNJv~NDYE|e~%{~<J1є */E~8I5o$RT7Ic()vW\ŮlwCUc01Ȱ_8_XV6;LҷS(lj\ g(W&o=8*T;^kp:hlHik;6IBio{AR5Γ/Vio0r4C@ Ox &)fb^s+TwK'f :":sQeM/_b,?ZtVJC<5~&:Jn:fikfQcpYS{=t!>R$!!Zzm0uQpjzmYͰ5Vsm׉fUxM U[]Rr jȱV(HnSmЦr}^ҏRgGL3@_7In*`rc,8dE, Zg6V㤷[[ׅ,wCYZ-<֛8*{U& %XIb5ancQS=_].ZWګ&5iRЮ˹]F3Y 749ici8_ūU"Ký1sR؞L4@%*DM庸{$(T,jI*Bܳ#G#148 &e׆Zse63 צWRE Ft~RpA:Q|t)w cbaJo(%>Ф->Ӣ%ת&A:$ChNhon- k٧Hb9#,VTx6[ɵͣ: Y1aؓu؞O *Fo]g45L׿d>РS{J xqH A>Fena 57;#q8xՠ>P!`3$^ݽ#EBˍZ c͹inBx)sFTڱ@bpN٨>!wUMݵQcSZS_=CH3@_4A74&kmƜ̱#DEюbS*BgLMJGJ+KUiu^.S~nZWڠ pXQJIiZ:ʽ)Nr?~m|&K3@_|,0jAŃ=, Bav\&u~Sj rE*-d?m2j Ɏ9iA  p])UB#_bD1SrY3\bhmI_ oh״2O>=-]-a #}MJlqk͑8Qdf d5y<%rM @R(CbQF4X[@ZdnE7=̰Nv[Xڏ%wmLH{5Y%Hb g{{4y,r΁9c^How9W'>Zfg9(.ohO3@7~i=o|Vit`]kԞ@s>OkqҪZq50kgM@u2ɝ& -Ӡ h7xj8YftxKDKcʨ}֑a)\A5Up$&`1E&,LSCA'i;h:2hỉi1rԤ[Hz'z C/:Ѕ{q3k|30]2ux]0PKU @[Ʃ)#eM >, a$+]zS\2O+#߰qRyZx>B%(Nޮe,(o5jW;W C Fk8oѷ~[yY0o=.>4t>?/e?'MNWKеƔs ;uG؁Pv;Zǎ! 1( V33GXK2F\#[ɨIg(VV}ktbIh0-j<1ɵ庙#H='t=-NIe?V#Ic>H3@7:D6f&*vX&=hF cxIsp}] m0&q;P' {64TAE۷ " 2zx`.RMN$ӈSNw90A#bٷGLwשC2w)#,< ՍI *p⊤%8=h> dAADN'0U9X amE%֤ vcYy@G Ket)7eNΟk݃qeD>䣹90k+8ޓq҆y9{Q4:Iıg}ldk^]F:ӐT0+Gkϡ2`vH3@_중bjd ؁l#6F@aE"mۋԂ^ДZFpK * `_RɚLiu Eۊ)gue.~71]Nj\RXH)qA (/JFihKݣ\nCۭjY%󯝽ӕp3@ GC0Erόvf E"M:hV{6NNFBҊFMVaoMȽPEѥk ;`k]P;R= jijfjbuX1NJ;,i={Mt)S:=W }^.čؑycdyiCA5Xc`L &QSC ;:sL;IdȆXFv,0j8h#}DzH뎏 H!a95K{O 6,؋lDP+eʨ9wqB)3: *WhAغCOyu$tSekh*L}SF wOotBn Hm2:kYNhk V5h_Qu@LG3"(XwEf8E`(*zFC;FЦ]<(;XoXb ;XyB% e3(Ly^P. 24Q1Nk[hPvy{v|f?øO-ۑ5ᦈї `p9_&/t%j6Q5yEaR0tv3kЁf&Y60d6|> 0l# d#r&ʖ ,AGZ(c<"(Ӌ6§t1+DVt.;V@3 40.噚5zFyưSn1춆•c3ݺ`}v  WlPqfg# { 1|}0:I*B$ dW7ڳ[ V*ewxJHGS.,0.CF5F 1}M`:*֌(akƐ+. 6";,@/D@.-gw(W=O1H{5Oj`eM'+`miK-Va2ţB41Ȩ9/Q7pW_v0 Wspel݋EЅ{dxs+_yA;+d҉&c[<^#)3hH{V-[ȏqG0BxDTӨ45CY@YbmN\m,`艦CpEwmPD:{D/@KD&ê j4h?+0{0ԫbX/xptΌ5k:NAOP9cM ԃlŐT-:ţheÙA1ӟu`{e0 z:GzAV PBxCY.B ܹѸ[Ry#ӞnPkAlSKtDfCE@4JG<Ӛv3@{K k43. ,H zbF-НCAG>Cq`8AY#֝נD!~;th5xGE5F9```jZ%'trJ)=7P=7,,vtVα=ZW_v=rkG5,Dݞo?]wU5 hu͕vH(Vl@K"٪aEKPoIg-Q?{ 0b zY=8 4L< bxїYI{ iVCPԳH3@_:GzoΠ'_9G?@#sD;aš:D'@!4̊Fn8Q̉b:W+ zF-MDoaAt?fƀ ?G:Yv`oJ +GϷږᙽ|_F tx[$$¸>Mz6jXc`(cYpGZP*W#}ׅYC=Ho8_nוw18[ I#0-VN?yl9L}mUоlc0 rS7(l/{o,\bϩXuRee$E{^wr= v.Z9e}z 0@3r m; [d/iB"ؐJ|IYk0,T9usJ4p;~K^[W`,%v/ɬsF#1f`;i vfy "~-REWwA}̋Jiֆz 7-hh'Դ|g3;t5g;jYDihO3@_zC~np\ E[7a:xx! pb fVjRhfH#2qF@n;riFS[pk0͂^o ]OaZ7q؝C`.xuYE|,!yW96~+o|^u e#nLkA"kl}Hh;6;ƖMS/{YGw {dze`2aڳz"toy2t@r90sIÊ)q%'c' CF wl45C9P7 ;^4;T޽[oedU!ksX`^xpVXҫU42th:"SCv U.̚>ZyIvrAm`]q`%ɠ bIPq $a{<elxx6݊;=82fj 'T\h k/Q7{FY)` [v0u v0}i;(èwNXбvJEH8KZI{ :ty&q×o5g3AG45N5*'a g:pю ቇpK͒q]r*b0cx_`hOyOxMqXIlnrQ76- No)Doqϲ$S Fζ折&&c-u"JF(g"\X,~_A^Y -Ŏ7zQzx)m'6_6OhK%Rf`vʌl' GźC*mA cM8d$ʩQ#&g1w#H;Vc]1#zfg~g7#[=pJ-s<垷~_FϬ], gF81Ke D]~W Fi<5=ayvO]& IDAT繵y^ΜDߧRywqAtհC {t2r), wN¢r r,X۴&}.}6EӁqڭ1솁 sN(aBh}Rw&jۡÆ0O_F.gcYcDcDtJjٹ4Lg>h{#QsV]Fs8MXO~''>_{;,@C N ~iDG))V;b7W9eͽ}Sv=z!=婫&o`oA܂yvZp^=-Dߢ,y.tFX? BHpqZ`kx [轜7jAٕ`xd6-]JX$q@;۾!^g&ԚRy]3yHq#4!'Mv"Rn-Zʪv{u8/N 3@GO)Z8G?ʧ?{]j!j26|"rŮ{WԳz]a+® iH=߉;#}t-37Cf.xummzn"N`@M&18ߎ.C{7Ex',XD;N%;` D/䂞+ R*ȕx  Ͼtٱ;y(=z%)S:=ˋ+9;fQB4aɠ4b@=Rs .Qd V`>d v$܄ =`= NY8 `2}[?9B5W,զ{$y>uf1f G){wo;=@>⼱-WXa5auKN,`n{uV a!w'Î[5s . BÃ`nU>/ngd`Ϡ6גB/{8CN{8=d<5L'tTH#߻Ш3)qw6@?g>W?w btg=F7yao8kv,PoPCvFOˀk2y ^$pZ'$*Eayy킡[˞qpF b)X@ B0ql$#Z}Ň盧͚|KwO{%Z̝_c e;(g EaCQu.TҘa}n j"-{ރpF0.1c][pփc\UhbtAٱg`1 (Wҡg=r[ &v] K8MI`ڰ_W93F';EOOi‰ӖMvt# ҙ;j}9^#VCN [MWȻgnxbAg3]ܢ(+xE{Rk7qvS+0`Na /`=yzUv r8WJl;½:ZbQo/6A{TsSvgBK.`%;W7`@:Yzwn'jѫh;%LFE쾏ǑVt+ g#?#'>q/۷y'{~PX s3;W/^7v"G߀~- X,PojV&>ovo/˸`bc,0uǞ[(A rnDn w;X|1z8{`#0{܉|\aUV_v$iJ9 Ȱ{pBN)OwM1z l%M}d? qS K0g)_a6½/p{l^Qkrnl&}`{]M9ʮ_wxoxZ6,W\Ybta͠󀍞ԧk[]{ O!7 0~稟?">`hn.jLOO>$/"gx饗o/O?ɟ3_җxmZ '* D!C t v )gk.PZM[j)~$ތGdT hlqf6{Vv*7Н!zmk}VtCG3'>~#j-rb7"CIJ1KԪVV8m:܅-/ 7%[5WʸzpQio$V(GÛ=cZ0T늭d<|)! ΧyԘ9Kr*.t@ { #8u8W;BX?:޽˟s(pW?q>/oQel6Wpu6]\ Gr'ȫ7t_;q n}tl=~%0H4p72wnQ,r 7 ny9>g/ 6dwlEXuZ"¸a &`n`l̷d yuo# m| {; ƨR6xF1v6mV]<Š˗c廍$1$n!_ޚHsp g '-[:w&24|Y| tpw0@?>1/spo+=y }06 żЗ]AA^{ ȻO`Mv9nǞ.qWZ"]j <40 RmAe)O+iFw_'ݫHo}{X[V섥[tGay-XsPdTX {1I*Tr< =Auzo_.Q15-E׌NMd]i&p7Qx$}W:[n`!_%vC`g(,Q>rPXuF>Tҟ)}t[Wȍ SX  vUf77Tڿ8@vq m0@/>^c};?G|s?sG?/w`}߱T09Ԝ*F]:Sbz``NDb]itZ};ʠ:chT=Va{Шzߧ+vab2=X뉥Oy@ ,pB5Ȳ0zyY<> G6G`4;qE$@f1[AnBQգ/V~錧KS˂< ,Mb_dQThUFܹ$kŻٹ^d XVOiV*Xl?]ko=ԴHD1z݊s7[?ǣ;/|ƍ/c{UƆ)ݰKz.tD&Mrʎq[Eڱu.6rvġ: F1\^v>tZF+sąF&蛨c9YSaKOTX ܊C [|&5ow);#AB]yϡA·wF1seJέy9_aBP ev?;Ip)py{=ڂknBEXˊKr8q>~Z{{qR ,"=W IBBR Н*vkX5^4Fu.U3vzi? b nŹ2r xG?Qܾ}}-4Ņ[5B-Hߴ Tɉ.[,l9a4gtɰ .k09B8U_"Gk0tr`FШԀx "J.9378-:P^RY`veXӇSmGۢ Xv;;X߃5n%:fgpjV\a;XxˁDdi//fqx/EDF9^X ܤ z=<ܟRy >3)ʾ hXraG<쐷蛰~wLmNĎfa]zƒd@ٻuŮ&!R) _a@z5n z"艢gpԷWoT`ӟC%v"2$Mlr=ˆdn{_[y""ћ7޴| \i_ )1A j_Ԑ`Ro^h!k[#Q8(ߞm͚5ϩ{Ϭ5g~f͚5h"-lx/riMs MY:~`#p;b)bHaT 2c\Ah ?c:V;`u麷щ:%h6ƓYNOb]lv:/#iL(A;FEM@NtI`uL^2X3ǽ: 09nYsK.K&h:3e,f+wdfniu^:m{ Glmw7~r'QU6Ɗ:wߜŽۑ}Ǹmg0 [uӝ4_&jNUlBg_p`",gbn9p#R??$Y<mX|K{þsE-O6Q~8ۄ5ܴ|6\#c194V0<<Qy;)B83aKpRZ3&6 A pI`%a 3v?Z4~BȍZLdp '4V$Z 9GvVS LO[qۗmUf@h qwl\ɓ7vlrWl-oy84C x[N`B`Mq(aeôqS "wZ;ܡ|W-:mEΥ:;O?G-;8e`{`>colA<BĪmmvdmVg.p V1*,{Wq{cQwn2a%C4)`55 %Zs.Lb+r EK-!F zo@)R108'm]y<{K<s:0]aDCw:]jD)`kKY#4+I 跑pLp3Lmy`id~FN3+@ЮX`Hdnhu08ĝ6FO[ ,)vv4]Gb# 9lnopnѦKh8?-g+]̼fmz)v5%]SF)%7eAUۙ8lE{MڮJYuI5,h6a ]$0d `w*݃[n,vБ^QfNk1O†%L=<9ׅ{ `G&' Nm'1?uNJo1?\CJ7,JB6E~.U2X.%)'aۙ.&tнVu%^gLaP)͈xLÑmn^n-6{vU³7L?Uq#rw3 c8aʻqML4Zb0/bZ?Iv)!2_6b08&m LG)| HD^V:#\+HҤ!k_Ep4aǠAGzAQv'!7Uh\`IX 8t>܉^^c"w犭0\3`u bch 3l6h ^A; _<:5l伺NXM^ m8 MsVVcsp똙W.>{;qa?1:Lf*; xy0pNk^V9@qe=Ǒ4h= @+ֻ9S m:  GH˹5PN)$9limzH@/H3mtĄΗi\|u"!byZu[![&51 k(#8cY*5ΆWm aY,Cc=,{&`6\%낙D\wu&\cF'ABLgIkq S:/hx9h X*-݆\}%?;`<ݱf6qarioIq87]5_497-m:S.KNzKFNZsr`6h+l͆5)& qMHNnV!Vׁ;gr^6O,010S=X@#N:FL#q:iE@wبE' X/yypA]w1hNJ >44c13 l ('}ӵbe< ȩ'4 EҎak)7k äar@,(.%<(O`)EH.>3;N;2yFlDvi3X,ٙ]iuɖApڇpeNXIDf.Z>(DPRjQ88cAbZZ4vhF@/HN-%Kܷi9s=S7$v5nn0١̫#E N4mJ59@X"A/L Gs-@wnA@;:?tm!,^vƈEy1YŶu2FSufd`g4,d2L'43D Ar?̌#v8KvɇqN @$'l4H(&W5m^ af7Xy)hbv ٠΃prB 'X񾸫^^j>1a:%Nc 8f?נ]MV˰Q*:d6DN{e# g/"s a/ۃ6  asfǨ̦Ъ<"嶱ز-iJфDfŗsܼ:L`} :݃07R 1f,Y^:^MAGNBn^{ysf+q˦ (<(q0G{נAszAL;7[wj;m.24+Y}09@vyH:ZWAN}d%.˃R ξs1K䶽}[hƛ,v,0 >R fA#:G+4rh>em֕VG}2l aE.̽F)&UۢG$a´!Ѳ1O0bFYt1Б^,fua;A/bN+^f%tBAvrzXTlb;ZHFPYф0Z rO~JAfZÀzFl\? EMzeF~0Zry 3p|֏Hy¸yβ? #:R.=gZMU†Yr%T˶!f{nvx.x4d Nl(MkvFqG%D0phaHblS ;5!E5jA{jRY2q9$II2ff1'`#N (4r5p͇"^H"c$Be+do{VCf.YĵPݙU048T^jPC(Kqת4BO=nV`ccwu45iAw#|klWظRQ s vPդ5 M*Xn[!&@ N~B5F"[J ]p8t?>7P/Z%Uk% r`3]bR xPjZ3r30S>[~SjX(:~g\N=eZzˍ6kk :5]q V4hUmʉ?;,L]i4۝9H;J^M{U`F(z6}.El`eC#4hv=@9r7xcvõ^|;8~xgA%e kEGЄ TLXE[if;"j=0E`It0$ ^לlA D#(L`}#F&ω{}⋘s{{g!l3do^a>Ki5OR9gܬe`0%vdgN/w}~{qwfg',61fXl j7J`\x{)#'eWtm`\ٷr6$0GLZSnh:Șd\A4/fL EINy#@dIOvz\ diQѵh9 22"`C=zG5\k7tnut *Z5:Ć`CSx>iCל[@]}xiұK:KsWzޠC٢@X5h\4h^Br7sVAm.sMՀ̈́p %TZ{^GP5 92rL.:`|Kpv- Х^g}V ;| }Mȇl PK-&H۾%N{7XK(@ rMTpu&ٽ8fj)"G,pMh`6VB`l:+MttD4^e e*AGf'ٸ<~, [[b3˪ˮPNzAr :5 d ;'_|4hJ CsYw9n:5Vz xP&:7{r9m#,}J3D&Q.J1>pro,,6- 8Jp 9RnwqVax} B ([t|N4D |孍5xM280drn萇DȚVjjcJ0>nhc6?'mε _ {-U$HߍwPG˽.Zi&rsHV3mE$RT!@6"jyXQA`=t&B#[Ԁ9FKu,7o(;pֵRɔ7YΘ q&SbIȇڍ!uV9HgvH~|vV5L(URVG2V{L|Z0g]-YVKe3@GzAr8;LES,!f=cFB„+qGѢ Sמ3p&K2-Bkuk3_j$m rU  j#T(W&`6*lALX<đC wW;L(P # 6>-FYr0^3$9d}[Gĵ}T 5h쑢(@Pt~X멅?hiX)Uҍ8'Ԝ9s6Վr>2=e7 AG]` 6jJ6Xse5qэdsP6%1{\נ!,k90Yc5:2+Qmρ$]E.y-m,z LTbCZX y=8KW>sРszAr~ kUc4C%r(V1#TpPR aOjt +@X4t#+~f`iMjڴ1pf~ϙ92;tzgY]G@3zAJ&TQ1.K$f da(Q2 \&0sZ pLj\j% 5fcY_q/$#]aBHȤf VC qf{ͮ@<8P9 Ro " +!09>|+ˉ/^s[2uw!+#/7 e^$J=Ӡ)ʾ`tGjj8b3C2y~šwO6mi(8d`QDBAMՀ!+̬ L_nˣYu|YfjU+[ 3Qʣ桃r`|!XT jĵ}W g]0Ȗx84D0q6saR9UW`D&k!t<5XNO°d>' qQ2_ivMPT[JkE.Efw+TEPs DYK&r/bqh巋i)٠]U'5tW9fnmܣ5Ǟtx-(ݹUw[p60bwDB5rUdK990$@*849 ]/˸dJBWR(ڰБ3%>*8?!jfe*Tsse8!eXX+i瑦jlgxh18O yT :y Y%;nCV|cS]kVY3E2qP`P_z7n޺ju߽Fj\9zB&i*BOm 3CL"u͵"Ҵ!">V7:]З\rIf8~8nf|ߏmc<.~/*2Ja_J@˯ @@rohm$ ZOKS#CsJibz|LЧ/yW4DŽ!{'].ΏʤDyj\+ksiWϺ"?|vev-zk5\8|pgXٿKZlbsZmtp䅂DshД,d6Tyi,|M ney kF%(RRB Bc+8V*/~1,Ap8u@ K Zc+SYTcS9S ﹲaP~]9za$%.b.gW-u7%_>JẊ9H[+m0W@iyafW,Ork@^žUYQ'Sico|~2:J-:OV.TJJ,ヴ %?h(ˏ&J#Z'P"E n\.Bjh3[XBBӃt絅|Y+8SθE}.7s SZg'wZT|}re>L2 t&#Ru;!IYetv&D1A$H7`2̖-%Ec+ZtM"xi3ׄyUvVtg&Ipgew*yYw컙^B,MAjy h,1^ 4ad<#Xk%9B\[A.i)KtgpHXySɒ& G?SmYO_Ս5,˹Zi(_cd-ӓ lR&@J=ﯹU>cZl[+GБ^\}]6QjPGZIծl\ƹŮa пylo9rN[(8+mn%7,(封qO 9RX+ɰ{Q) +YӲz G@/Jmzsڱx}OR-Osbj8H&+U _j KRk P Ff\>:[p4/Z 5"97yy3!ir.e :: AkZ Ϳ*H3IYڱOcmwy9ˤ4.vEցqU0ϸW6)]F6ZA~MbՌ<6B{n1wX\[v ۠4q >^ '~x?WDj r2ɣWZVl4ڒ,벥 ǟ+b5{Hp1]f1'l{)C9y5Eԇ͸Pޮa$.z*bVI>RC\Mm&kBTVSLd@J*/1S -ej>ID 5di2 (a1r׀/F|Su$yT2IYtbUm斥P+{2RԳ6Rk$YЫ|k>_4D 1I+E#`9, Qj/RG+eqʜ ؿB%̵֨rqVu!AI{ᅌ95ՙ8wϘW |Beg@GzArXtgQ~ڪK0`? Zۗ=kzp#d T+}Ƃ<+(ua@ 5h+KXr>rꞂֳ ]C&qm|^3`74hQqk[|.+]ARq^(5e;BQOYMҳn~Ry\&O,ďw hh~i}xӛc ˗z״9Rj|LY̢L\lA8zdHAd|G9Z|;ǍU&ļn1% -|듂j1Xfj2?ddj9Бv=@9r7xcv+*s={p)wU|?AQTi,i0O6t3̉$ֈe3QP˲+fjaQZ{TͲE]ChLM4\}@v=@_r%{?8z!6o;b ׿x1X S VYc߁ʼv,/#`NsXxs^^z,~A̮+GGo 0G-F܋V*=Zm}6ѷcdk_۠k1/c YS_,Tţ SBr J=}_r^IB+KoH+獰sbK1q7[hp&x7lku j 5^Ro)0 >=  q՟e $ 漸Q 3$  0IoE&(+/[h h/-/*~1q9'Tj~Ayry8KhPfW `Ĺhl5ܩ`<~ °ݫVʜ|sRQd\T9GK bs-:Pڼ2v!*za=Em4\7@/١m͓k79K"|H 4a{rd\Ϙ3jW^\Z,+o{Рٍ֜6(J!-x'M!QG; 6Νtnk|jrN̫Uk+ ^rG0yd]਷UGfNδO.Ysq-F>Q/PH@ '9Du.N}Xǵ o=PSyFyX[vhA#d=0AAWwhŃNI9B>$%Woݾgt"(L^ DdfyT4h9 & ۪ dZ~jIM JQNir7y$IBܻC*ϺG$̸kv/#sL>/Q!kGєžT@~W&vWkBW\Ϲôrޟ+];1ؓ{>qeHN⳿`*Gmu%ӲK/B%˚zhI.N]߸f\6IX;HkJHIjןW] gsM\$jgjCTCMRMF~]ʞP˾ 6тeImo IXI&ۛ`@H@/HVZzU Z=UlְR|a%r)hm TJQM:ch_r&|rVɻ_Rɭ)?ɓﱜfzQ"(yq8 5TN&nAOCWl3.O>k4*Z+9-VZh5Ta.@$(yDGk ~R&qꥷiə8jym+ U@/p~bUJy!J gGwa!]vQb&?k6rR4_lш쩫 K!jE$i;TRX(jJ̇ Lkλ޹¼Skvm`XG4Y\kffyR J1){npaayVyGLv "(27uqy-4 j3L[p3;Y$M5k2j)Is0^Zg(Akr_aUT҅ŧǪ4/[q.zat2BѨ5̬)W5%4J50j?ip)Vz08Y!i@U΄y1Ěq-Jݹ^a>e^3Gn5v/[ D"vA*EP.# OFkx>?'V˪LJ0 ,5g'*<}L, GTʺUY ^MvXa".%zA5qSX @m0KژBEhcqR)9GM&4#&D7ħ~T*-RԶ4 eO@2y,yVq*($zgFoQfGyP\.vehh9^g"]_w$sz.X(Y pһn}੧b?|@>]H!*K;;Hg0Bh1xLaT9xiB@ᇇ`eOWfÇkY~Q'?ypXwPoT_ ַwLJ",^mTd5%U0G-,06QA1BIZIk\?8gzˮGn+;QUyjcOW4OQ/`(Uò{ԱҎ_MG7ޘݻ`EmY!DQ2YhXafZ۠QZI͕#ퟭ3m Hn%1g9˟*l=%̔D9C嘟9{웠oK+G2"+˒Zol|s_җ_eF#8pرcgku1;4gy~xhh666p 7 /O<}c_X 4._Op1^7Mn/'?xwSO[o 666p]waiia8s''5}NOd2^ndW^~g .G?3'>U‰'p]w1^/%& 馧~w}7a/򗿌. .wމ?><^o&N)Dsn]?Iآ'O/+;p={_Fx]{o~j-^]wZ|;7 tQo5O|0N :t(N n^?8z!|j>?^կ~{/ΟF]t~W~W]toi -O?w]K.[[[\{q뭷ꫯƇ>!|ś3B zA@?^x=>Ϝq4\}էmdѣ>-kr ^םVx{ރs9ß韞9-W]uç?3+׿u˿ >1x{ރ;g}{?.O=okkkgKh:Ki$h:Kih%K_馛w N*9z(>񏫿{ߋ3-@hz,w;+n&r->;pG>z뭸 3@i^d\7O8w^<#x衇p'>}X[[W\|+?l 4P?^DDx;ށ~7p^WgfY<˿K/"~'O=@ҠAO|سgnf|~9眃M<;c#o}[YWNW7QJ:?2!puv5xj ''&--BT݀E 8@"b7A tjj%M||%qp wsp)I<3 v9[YWОzg޵qY@uAHho feo f!n@\C{n<r tu)I6Bh{K0&M[YWq]m}'jm$=.nډ) ȅUDhr+-! $=.no]AEp#&RRP\h4ꒋZ QujU7` "7HX3 VGT݀E _  j U7 vQu~8hjN:dBh5Hh{D ]T݀ fph5Hh{D ]T݀}gd7b`2vd.Bh5Hh{D ]T݀}J^= 4Z QujU7`_QQ@uph bA $=.nڣiQW㏳j j U7 vQuqȀZ5Z QujU7`?홙@v 7\TW =PGT݀E O@p.5@8zvc)Bh5Hh{D ]T݀GFB*V-U2WZ QujU7`? يlDuoh5Hh{D ]T݀GF.h/UƨAB#n@\=+ 8u rẃٜ5jWh?spJF9 MժͨZ QujU7`7qB-Z6עBh5Hh{D ]T݀}o~a \MeZBH mqv"`~g1^:?h5Hh{D ]T݀ @ &I?h5Hh{D ]T݀/oy>Pj-"!!Æ C- 폍O<ѣGcΜ9^SGT݀E ^ bX@J0ЁXdIF/RRRPrBAB#n@\ldnr%D>OO.Wۦ:!!!8x -[ ;AB#n@\l=1s &7u~}4 h'k%lݾ˗/cժUXn֮] #w-rm۶aݷg"g߹sF#/WHCڗ f).PL=;~8֭[ӧ]; ":ömϢq 7VX\TZW_}?$8~ |y6ZzMn){" o2\Xf[>֮];E[U7 vQu.ÈGy%8 mq41\9̵3 Qqpur埰k"VGT݀E N}@v6t;&:7ʹvF"Uwwh&BhWi߾CTSN}Z$=.nvEХJf)@6@$QujU7`qq@L P.Pnyv3h; mqvɽѵ+hAw 'Tl`! $=.n6%ݭh \ݼ~}[ VGT݀E X_{v6s'<$gx u<* @P mqÇd}{3MTmW U7 vQu׮ h\5jWkߺݺ[*ͮFzm["VGT݀E XW+@d$P:P6h$eG]i U7 vQuվz5o_~hDGD{Z QujU7`]+Wш¦L5$=.nzϟNpp6"kP C mqUxsoDFUUnf ! $=.nz hc \r}:*׵Bh5Hh{D ]T݀u>u :c8? j5퍐Z QujU7`f`mP[ůio4jW17o׮@-O@`@;jW嵟8\4oT32.@&yCM^@AB#n@\nȽY h& 4t4jWetoRÁiZ+Z v-_y' Z-K1-rHw@Rxk>~8֭[ӧp(ىT9r$ШQhej4|pz7iĈ{K"oo֩Cjw!H{K0 Qu]TDk?wɉϏ}=̝K;꽪e"0tPǴ 0|-Zy% o>ؾ=3~D ]T݀'L`/Gziμvv6_ 8% w7fR;,;#jGT݀E +7sgvUcsjvHJ YwmݺɓKgaÀ;N<+{"n<&Ooo=DG#)."+J_ D `%aNw/ko_퉬 gK}''6{ n@Gu븝ȑڻCQl_! J£G8`96JF!@Rgc6{!n@/nࠝ;Ϗ{@ N o\8v;'kӁfUkuEq XQuqy ￱Ϛ;UdG ! dhhՊgǎYWL o'M\\=|6:Jq X9Lמ_-8iRٵ q.XPB}T,UQZo0'ʖsQÇ+&OmʕvߧӍ˗'R[U7`wv+p7A K@f&Рm96)xf R) п?iuf;wR`Ӵ_|̍ Z`Fx7A at4oRfl#"'L HGnܨ(z*5xmn[Ф p"ClU7`>;p#޺\v!J8BH7Hh@{{vBh$#s˖Z.zVػHNH=X5`E -\\8Zt8:eD ?\SVr~A֯ l lw:8BhA³gyk@@T^ >̮vjJ2;}6ª9kZ5vU]Ӫw͓eD =+ ;91foׯʻ "$46.ڹsʋ2{yӆyY٣&SZ*18|5._ZLD (Yik@.gbWR! .$tٲnڵykGm4x" #<UBIX-`5cE9 h]LD 0 uzxpbk D)RhQZ! t a\n-7IFpPLacUPߟV,|7ٱ_ ^{ ʕf_F`32A;7ujAK7HdcՎpu6(h".$4Žp] tS.nӆ}͆hx,5PJj䭠S_%f_F`?@/p<6<͋SaXT Ԩ$3B)cA_MQ7筍V X-_[n:\jfF6Quŵew1/PB! t :^YQ&RbG ސV<` *O>i8e6Qu߿ AƧSϊ6Qu˥/l+Wiib@ڏ{@ 1` Pom}m $8`fٗ5&n _ʕo2X18УV% PU6P28$l ~nuKhU͹O  XrJrہ|7BQmXke89$NF5p$9eBQBI.BBAB9 `G ސCрhL-D ))ixU?.M櫯ݣVb}i  h??].6`GNP†Zр%geqwlU7|uyĉ)Vh3/d} foHiuA\5R%3h xQi(\"RU+XsAY&1Qmf뎌>PΔiڔKsO9 | حrN^о1mkvWThiuA›7H˙=v5z?%$NLL@dXe e9D 0r$&M/ zucy0o߳'?YC`3hdhg S3z O? ?O?t.Hx*ojո2ZoǜD ZՕ+m9oϿ;ڄ'Qmtoƍ_ʗ>rppxz5/q#_/()Jw2л7/W|v*~w޲u,X@[l{҈#hذa4yb :(32ŋj޼bx/QrfXָj2\xp' ѣD]-){nvFD|<>۷ L_zP)(-+z惶8zOOO򲗗(n)ED7EJmHKK+죏%.ҥyK'|b"epH ,U+FD=bvB>`WѤI}Ұ!} ؉o#4N= tu;[sn݂\bq#gO?-(s둑 Ӷˁ@5 mڴAVc0`YIMM pbEG5/I>hK ]"9Ln9dgse-ܷI]H){>6vG\OZYh;ㅹo%#"_v:+3Oh t₅ "55??gZn#uU8# qMNscm22B Ϣ׭YZ ϊh"8pp]^–|)^ݺ:=*) HLD7߇ur޻Yݴ(U٣Ţiݻ1sL]ũSnJB 4? (Ta셄X>TmQ5iiSeHx$* J4#GF2\R{ti駜ot) s%g#hsЯn?:hz` zժUXh+k-,f*$V΅OibI˖@ƂWfeᄈ;N"'x irN@uo"{O)-&εaPG)3`\hm֚A7k*"Dybh{Ӧi5˫$/CWB׮11ٳ䓦Øz\}p#tP飇FAۈBVJΠ+U[Gj<)@gY>ĵkdpƎeQ~< ~922;rmHKUg?8]]ɻKy+pi.Hazc}@Ppi4HIlmȰ|h@[L mDa2X _Ѥ=Cn.dz^q V#,,ُ~ڦ'ƎŞM_+NRse>io2@` ~tq܀.NN6mO^=X#phFyNN@QOP(g]/ܼrبCCtP鉠fMc ʇNj DF>kPZ-Qݺ<\TRR${I3!pP[)WKDDٹt!jW}^+{F 0~.)7f } uoAúGA i*2ܳgZm~F ?TÇy_4{JXkre"ggNj-#4Pꖃþ}V =i Z[&rxfK"***%Kxkpu O'ܞk+OԘ[M6>c=-l޻YH@K+?sCMd`]4`53b&^zza8~血,"??ӛv;^~qkF< tSOSJ(2/>h̘Ǻ~lCdGMCTiNIMI]R@rNp ;N7$Iu^\&D'烈(՝8PL\_U.݁ᠡ ΅F5 |7)lrpC*za+U]]7tBe)KHntӫ f=s͍|yYʗgׯp`z:FEjy3!n]]oJ""8Aoo}[>?sҥd.p/PYU UEDGf祝v:qO|K/$t?4Ν 9oZ-}B8oE]/}>;*Қ(;7>.p\&O!>P'N;QjV*PH'%ɩ9 */'zXs1^LATr>W^r*#J{ԭS0-zqt'YJnw,uL3LN=niZzo{:|q §,^l|Yi?6)ZN\),~\*Srr^pPZSZVښ-HN An{WAr3__9SJ B8ֽ¨Zhq* IݻbI8B~S76QzWWZ-} B8}.(|yLz}ǧky̓~Kl{_lF_bO_T_*~ %SrEٸhdo>6Z/XSHJL;DXݽ괞Yš5fJ 33{WܩذzRu0@8ktZZ QFO>j1bF7xy&y3ѣm༼=q{HJO‡m>ɹС@μ HqJA$7e?ya㹍8{,SOYb:dҥKiUaȑGDDw囹yydSL{  -'e o@j<&pv×{,'òek4%fѫ=1~\elxeܝ1~hh"rgDcV@t'+7!C'/%UU-[oL}fϠ^ˡ0./8Zh슼5^nzKgxs8x#6j z$2HJϴ^=E4ȟgGQ+n݋=@!..3"HYwDl ֭ڵk111evaOG^8v2^>4Z 0aWEk9Nq]=}9Xo({bkDEE!- X"nnix啒! oNX՜U i[Eb-]dl N30#GOFAI}Nwdddbn7n Ki_߾10}:)܂N?彖Jf> #"j!Ǵj\\mٳO|yN9|x;h4_?uax`CHMMИ1c裏> Ж-[H7ߤzsla3b J\lmR5܈ʖ5Y |=M}wu+/ l)~TùrND7I&d1YȔSa^zVo t+[-;x1edf(ɛ'|Qs,\^{n< dBѢ _5+WUcՎ2p \Ώ/9pTiCOC6om} .C1@L,?vV[FxVtÅĒ5ckQsm츼 *6ד@ohKmqY p?Ed#Xvb,ѽ~=?MN4sx\0$mXA8VK3$pPoG7k&UP읳ַu҅%_+< LO&k9SJd@>{+oB8ߞT/.)-.J TIz` ђj|',YBDys˛pPwDD..F@ WK$jΩI7^抴Z?W ]p'O0rD^_y)L(33abq0`B8h ֿQ] Ai:V;yh/^ƻ; IDAT%Ou0lḫ3m6T\x`#K_ 06wl, 4T]H;;_M7X".W^0\r4/mGѹZό4Px]4C/f~fw#~,;mZn @J/%-n_O``x#xHӳҷ\|}yL.?<~&4KVL`ʻv۩P*@\*E g/YlUҪӫoLOgrҿ7)1&KD^=#VLgև?|HC[ڄ Eg)-+sč4>D&}i[kedRjvUi,ބpP* D8&p2{/]ͦA~11Ck+Psmӈ&Mzv:՚[D΅jP4І> J[/l1itIVU&o`F[zz= Fjb_0{N#vq[:ı(?y$̲eFLOg Wg42 Œ*{/k1*}e{ #U"!y-$>!EA5 `ݨԇ TSZO#MΝ#(҄zx>Iu곫T?긬#}Syi,f)]|z&FZ_Ug jiʾ)/ ɤg׾pPen Vʉ]&rͺu[qM>v&\C>S|trۍ^kAx{77N$[RVJJV}b`]f2AAf۶>jI&F?ߢo\Xϕ+KZM6Q`6ԟ"KG}\ON':/rAZnbO0RO[8Y=Zv}F5YЄ27 dfڨ:8:HX={8סC|YRӂv8p Jlj"#ya֭eIЏvA9M+M"’xsV9 d4O-oYhS+B*W"f!F$ZƘc AHݨd<^}(1':@8ܹ7Xh\s?|.cBh 8|0C xś5dڎ'*рys/ȓ;Sd~='O9<K,1i؂E)_~iݢ /솟zTRkpq$'ssuoo.̘1~SlY=%/okilY׋T =Fѥu#>`@dݏ33-inS`L3~v哌F&]n>nQ& Zwc}B8hҞIֻQ] X˖qϾ}R,\fwA݁{7JI1x@Nzyɾ~x}'I\h灊ciqA@Q7f͸z1e׹(pݾ?Pz~+k_AvnciL” aQ8u:UOJB gii B-FjGfi޸q8crb7KKh99YG2KNT7.w`XҤ'͖#i@&믲ܙ9bQ B8hW~%۽#?A3vm^̎3h($7q54H8̘Az`*~?ULy]xx?X:~wyABe@KA”o)~DpGΏU }?[hIyǨQ@ -P ckPvۂxV^@!HZF/-:ayp8aȺ!|~5"`H.=0WwRߚ~fcvhҤ 2i}}}pÝ; NR7س-[rf׺uQ6SA>8jւtXX-0k䗐%{K ࣏xn~Syk"aaaQ\m鋽{pҞ=i$t] `0F53}_ݨB>ngg#P2lAH\K_(w7:]^^\bnܐBҝʾr̙6o4<}=fVI|խ2aS|ǨlYDDX ƄpP;Pj"P4ЃUsc lɃ'$=VKԦ sw+ӭW6"T)ze15wH=8J;1h7xQE'%)>[8U{+,{&r_ 魷, EsJcq @ ز%Zӧ[Hh4D{|G?۶ت_ _CDAAݣG pآϮ#n]5DIJF̒`6iii@ǯP\`Th݅Iݩ,A@/TxY. o&CV)0IIKgyB;`+&E *:11-[r`\Kt,䐨_W%6[VE\\ݢ1.a*W.>OH&\C՚[fA  33hwu_]osk|p A_QEQp]0T XNKKW!Z-/Ā||ە1s|y!!?r=iؑlZ.Z|3O›o..5'>>Xcj>츼}k!Lܝq#>q{ T&'́EE6Bh}FB^l !Ez'([h\~)^RSi&k{ -^=.ywq;LCa@D߾wE1hUaڴ)#G!+K۴1|l }vD݈3+Jv.v^ {zO>rUސ>p?LWϢ/_22,K)bz֬ 9\X]ĻlYGKE*N{H?7S\ o9N(SÇsƏ14 Vnbj穸r !~,rP٧2*Zc6jA avVArs$$X6Nm=9ۤNޱ#o5Z ={è)dD\ݵ+a&OZ N'TU;bXalzU[8jP)4& &xgy-4ibx`ZnA t!풛ws瀨(N,>\ݺgpaܓDl_{ܦOo?LkbBHՃ2*<Zps`vzu b i֠6p!}nʗbbMQv66j彶?jPA[=H@^9\ ޹EUq ^JH eRLdtJ+ȼ c8e-F[Qgl(&aQ`J*=>~f]ٳݗw}y#@;nh~Jh_f⠽G`@.&}+ 9#ϧrY|9<X ޅ4yޫ8k SGK.ŵkP[[ tܹ1zhk׵I4U5Vg@Еv},;!F}JCQ@RXH_F9i~I4Zr~""Si!OX6E´OVyy9l61uT8 ŭ[i7$ .$IXM!,-=kt35:iW¶HsW_u#8֦Mx}1^h]$ A!11رcѫш۷/ʴe_b?'63$ٓ8@n "3Zp(@;i?nm޾M3gt?]$ AGFFСC?Zh4}:@ta}AwCmg(x\yRCFF^h>}j8Z8h@ff 1 ԄjB}=`Ҋ+M7Ot΅vm|FqSLśE:vM @_EBl @Qg&Gy9MEkn4?t3?n| 4zZL+~YH І39\ITXNq,@l@N3g"2@o.m^mwMKiFt3 nۼq! {I0g"2@o- +5~Kt+ hߞj2mKooU᧟R9s.o脳v` 3 )VWӏ/ B'S?9 vG ˗)8Nm3fЗNRRS)mh~.脳v` 3 i;<1n,xis//!N8k 0g޺Eqwo 0O 4z@nc?߿HI!N8k 0Ϟ 9nI`kj4&ꨛcs}{0扏#BqEeAhj$Zguu5 =͖ WtYH Іkj(4ЁFW<֍y}#hMm}t)M57h#+:]$XhCMBH*+iС.˜'AA4Np+4ӡ[7 84yRݻi@W;wR͛'p.,&!мbc=75͡!]'L~hn.];~||r$Kn/p"] T_E'CMB9ت B@0D5 >tCLL j|jiӀeZ6\ 7~压k;W|v` 5 `zD /#h̓q( s@_fg@Go|!M+\JnDnB @#bI}TSDjgK >lB']|GR~bW1;˙6 y2jt6"] T_Ep0(F7nx6 m60GEѬg<ݺ3 /vEs,hktU@f&bg"2@niOyhDt4OL[5lTF( 8µFxk ph){C͓H :vXq7l,F?kWksp .,&!@U3ɂt|nMND+*"dknv` 7 G>-׏Q;ٴ]޽%O>X$q#dknv` 7 2Əh}|%ѧՁvIh(@6[||6*ҩ\5U7[H Цhok[ts2n6I;YC5ERSխڹxk M1 U+5Ozص xEUrkBP՚ͽU7[HAbXgOպ͛S'Jx@h$6?2 \s .,)&!@yYϚ;F5&LF< y2cڹxk P7vNZr9s^<૝nv`M3 ZTT m{TP@)^z9WnvEBzXoټQr:\ڹxk SG .q%s[n1}t\|j5Jk&NL3ftX\U7W;W_6l SSS1f/󑑑%K ==|^~()iQS;OJnvE І8ʐp,!!fpӧΟ?p @~>_RaV૝nv0$@GFFСCn+{xx8.^zr8_UU-Dnv^m6[ȹu:lE)4[YYYx'oCQ`ڵHIIAII jjj}vDDD!Q"HL+ .Dnn.ݎ#44{/6nhD̝;G} +b? +W4o֯_6:p/_vڵ YCrq۷nBrJ%`6Z5՜uvv6bcc^VWWƍضmbbbpI%iŋDǎP7[zHnn.̖3ݻwbAzz:~-#>-8q"v łol9M9ڛ_5U3wކ`̞=MRWǍN:aBVV^us8"%%w)IDAT6Iw8:tI!Q+ sZثW/XV3ƥh&Cqq1yf>|III&)t+?P-ӧO!#tXx1Μ9GbҤI&)t>l""Q ))) 3*Tׯ,X]K.شi=b1o<ϟի1deifŊv^4V9hxgΝ?E}]1(v;cK>sY111h׮RSS͖YH$LBD"/!D" В;cǎaժU(//̙3VJ$ZrG= HKKD#2@KXo=$lZrGc=XdۤI$:$DPZ"HEhD"%DPdH$AZ"HEhD"%DPdH$AZ"HEhD"%DPdH$A?OۚBݣIENDB`mpmath-1.1.0/doc/source/plots/bi.py000066400000000000000000000003171340375245600171630ustar00rootroot00000000000000# Airy function Bi(x), Bi'(x) and int_0^x Bi(t) dt on the real line f = airybi f_diff = lambda z: airybi(z, derivative=1) f_int = lambda z: airybi(z, derivative=-1) plot([f, f_diff, f_int], [-10,2], [-1,2]) mpmath-1.1.0/doc/source/plots/bi_c.png000066400000000000000000002034161340375245600176260ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxM-Y{""ssN ClmRK /mZz cfX 1P3`pn nwsM暲ꜳ^ "2#縪+ʧk+3ٹ~_x'DU c9x‘Od9ci 1sx̀c9xCcs13c9И=s 9c74f@1s1z9 s1oh̀c9xCcs13c9И=s 9c74f@1s1z9 s1oh̀c9xCcs13c9И=s 9c74oo?GG?Sc9>e1+W!]q{{>9S~E|+_WWkT)1?c~w___:?8X\__܊";?<Ǐ`s}cj3X`o;?hAT'oy;e\l)iQR@뷔ǒVt՘(EX e^! h^^Ctht>BuTNNNDGZV-iY@hQ:GTOh<_"+E =cGϳŋ&8XGĈNJG+K5Bcb1x1yW+"i `p\!X ` QDAL^;|ŅЯ__+_/| O4_W׾7 =!;z7/W6sW`X8lQMK}]#:@[jPkL432IT ?ڣDaQ==#i4["lCC}@wiѣ/_57~}/W^ʇ<{W8mJ鮠V'JwSD6'B=/=_G{w;>_{~y J,;LEVx!iwZ@ȳ6\Z KpwIM{; e{JPBo. bdk[ N =2 *A+oܧu%Cߞҵ0io<[G pqk9~@wApkģ |IJ=+ g6BGWj:_>1#[bVjl;&'-A[l2t,4kX΄aR3r@{ "A_G=6\^h҄QhO<|ˬh 4X Ƃs8;[BN[9xb7ܸ =bw'Ĝ 1ho7HtY,Hu64d gZSπ d|O[;W“) V,7: .2֠ʼqӉ·USϑ֦4,J9C#`LR *a!Y ʼn?2['6^Z@hyDOwh+B?a7!nwq²!R >hώ;Cy.=K6%; 2]C%q-"曘G|k>4o[` 3ļ5oaoO f]fH?.-{Iu)'kkX44f 5Ӎ3 @k%GW?1cǹWsRK)K>{yxg><1Σ#bU*@zir~\xy}π}11-VngzYbM(i3Op >Kw34XbiL:e-! ݏ %5Zџ$X)П(<;i6ţp>7PV(}*2~526-Jߗݑ~7>:4o4Ir'#E\2\h*W%8`}ht']zw;\T~Jwl9&ųųV={<׍ڳn< ҭGT{E=x0V8S.E-7'}1/qc+=n-E!`w LR}iyKҞ_ANE:;UdG8LR(4CGgP>!U]hISTJ:hrIBēNy酰^` AsM<)oG5Ӟ;s{Az'GrHf5{l{k/1s3 )Y*$P))RTXjW-/4 O+\GOSX`wh;bP5H9t #-V>望6ʀaz\)qIggcV ם)6(ؠA&t:^꓎4՝r[zM%)=N/9rK<%zl>ØZPMchM%&Ah,1|(b#eG'Sjuz|HKL.EV2;?.`FXIutJp"i-!M}@EhKvП$>K{uCvb腏NՖՐ.=5$OY ^S6]M|d[CXi;4 * BkQ{Ρ:%;kCԶ#˾C;|4 ˒u^/N҂3rOϋ ܩϽzv1V\jOi%RZجSX`yVb8Ȟ^>@豜rfek.0.1-攔M!]Rc>_;Fbim#6:\s]П8^#-^rZ֛Bok\|<HlmwH}u;)% g*ZǷmƬs% UY.VZ&uM]1ܒ&b"Zl2`s%J7a2s1P;@XhOp2am bXɊZ-z9'x^.^{Q/!ަ cKL7 99XYŵ:ő7òÁQx#xt:(X9a8a֘fY.>O˘\ ]oE'C}J mE GL-֏|>1C_\N^>oX^W^vÖo`C]~2Iy%}t !B;7[9kJQ VVGK)EC먩ivܚFrzFQik1`c`f|P6A4`Q asEh W7@>x+Ǻ%)p.wy.NMoY>q\-/MRw)XvXtX01 ؆ƮeTtQ!%5 fEg'Šl=kmVù"5pf?*^ bOcB0iI26-z̋.N I9RأAUh Π]Q9U>>:dX_]6-A.So ]5}}Ñf<}\0 zEψn/ IDATLDڈـ4Y!-Ofo;W IIrpn0xDvd@KUY`#4 j3tE/u)&4L 1f@"_:[ŷ->W[pւ><9{ˤ2{ J:9euumsLF5XNjHPX5E-ZK̍m:,Q}5tJ" 仂جG k6ad uueV m^v˷UyDpOmCv“7ſn1/ߦ( "Nٞ`gCVVtl'H`M΄6pIu<ȁ-#%o-"-"MqIA?PWH R=~zQ Wďs<x/_o»_~xg`:9KYJ&j!N!SyPQ8iEv' %KRu4n@y4uk70VJ:OXe#vQ!ѹGX~hšMX!NIZ?p^GX+75Q4|t=1vV P.^c!D&V`N m5bMCƹ-g0D3:j4lx<=Ac3v q8zҥ`ŗ JGEcgט1M)oAe^ R J†{wBxq.OI]*q,paeIb!>'cc碮 ݅rcXƖJEgHf@rD,a!$Pc-ӆHӥ\^z/Ի¿?g3_Պ??[ (~|,MQ黊<NE5"5&F*㤮6YQm$2E8j21DӦYQ(Mqg%&#.ɓ CH}+Oh816HYKLh1AϠ \kh._¾:=G"(dAÒ5+S }CAmSvGg'N9y 7f|I'(ı~R|uSA&P`Qԃ-!f@_8뫫RˏU@FϦǪ`8GBG #pܵ&7φ6$EY~zI 6 by4DI'%3DӠR4`G4&y%oNBs+Zp*QCE/`|%o4M}^KE/"ڤ`;G01,EdO55}[WN3q`اKS$X~ a2eCmf$H˰(>_H;DbuD0` "䖣L@- !f@xL#zRޢPScڢ3Ҽ{ؾj_{|eUyɍ~8kںNl9MiLxVѪyPe]?:6oY@*ݑ"UK'82 C .\r6^ȍ8{ORwUmyހ:B#ÿҰCCGgZ޶lS|VERg0{Ap<KSZi, ] |ꢙ^I RPA;e@ɐ3zn:!f@qe2 vU#ˡ-q% 3rP5 8ͥ\ٶ#R[j%Ӵ_X{Gjk q̏U]I) 8"mХpϮt6ZIkH<9@8y O\+\hq\`u@>g=I 5|76,p88zc[-ƮYwYIHg%m`KOja.u k94и24إ.  {$ʀ@{,RWܙ6$XXslqLc'Rdjy|33Y"tinCT!jyy)袠 GnE:B$RK?>kp8!ppsK.ݚ^'8 Ҧ="3upSd8*|ڔ,FRkU 8vpsWTUxƩaMuj=y;ABbTYYߠ+g6aN͐joB҅_oKF\ޟ `-!)35cYIy@ZIpVQ=9-lU!FIFd6 R͞]3XEm.X'(e,L.ޣaanI]?kn%.i֧rm G<^"w ki6 18xoXNN8Č븱l^czmRԒ9 KR 5k&XG@-2[X"=1̀>Bf9ueL/ s4?ssȨ>"Kse͙6fk򤩬LRI7r*fJ 4ٷZzTk(ho' >P!: 91CM7`pp{ﳢ.\k_z[&m"X/Z>++븰YlGW %7y'z>/RII3&ߦ fX##jz:=~>0cLjG :Mw+[ԀJ9ЍH-(˦10X=K%-Yُ  TiPg\/>oՑQŔz粵lTLΊ (jzۆ`GDa@O֞>:>+&^MV5z}6:U\*ńElcnп{ԃIt%)i2 .,ri0W` -hz,]I9dU}ȊZ.̚YLboj\S6A0tr>eJR.}0YUk'v˕c3?nYj*ExyTZjHuvr~(,R84W`1dUԜZf7I5mNoє1e3e\T4EPяNhf,.-J:Tt_)0*5:$Q[E=GK>Cp[z`=:^hϷ>- \ZEI̙ vfN{ i.Jʖp2YQ`7ư1Ԧ6+ij-4w+HI$ɐ.]VC'W,П(&Ӌo`U+9 J>Š_Kd:gEzt-cV^FH贿6hVYZ|^@ 1YMBpRלBiDI ͐|ah@GOGsm}xج< u}-!Qa} %"rF/xG(pV{ A;-\X턣M ALٞiy#.폣Vem8ƃ4h(="xbrǣ0eJ5)S :~|sC8o90Mc'A=_IcѳZґ@\eoyN'Ez\(T깼|TQٓ.^- seu2paE} h&.t`spJZ{Ntt j`~@$Y0Ө '}x a|! nqlxnc?g>k- h`Hw嬞NRAGu$:+EY8IvǤwhYW_azXKj1.VƮ1@Z>2ºX Ne3&ŔC%"( \`sԍ FᴂTo>F1yf0%`|F/YI/z?W1]2;(h^u9l|m{Pё4`yXBJ:!iϑ@>W L.&^yƣq- Q7DVD]PfRhy|'Ƽs, H @`B\a/cAmv Ҧ@(1G{C]O SVņ&fsYM7× ,#KR\D)b\:"$ 6CTk h5=[,Q(6 < _GG~y30`s bnrY\c{`Rm>嚔NtEQ:+5)G#!\Cc乂p} "6?w!"M1f@(6#ԝc~w TТ3+2+xaZb-*R\ -? VК5>TdFnab1: & N-M&jtRݙV GhI >^{N5r$psP6M`iz!-EY]ƃۢޡ2q=ncX~sw^y 0O 'Xrm1f^6!QxJ5)h 1Muݎ#עf6Ե1Bz` )_CQ[ ]4~)s1cFԃNs3ZA&ˇiJ"iAg(Fw%U J{jmlSj8pZUp h• 6@Si35hvf=*iMTWl#ɗ.I'Zz&`]@S 4Ym&Hܝ4`/ۂag9Y=aǰMbkv\4^hu4 7cvAI%Ԥ,@#'+)[ SBMנ.փ6\:Cz:Ƙ bteO.Ҹ(h3[כy#:F<#a}2ts߾`·mEcP s٧pY5J:ҽ:-m 4luhtE-C}U&+i+^itQ<G<'JEP|cnj8y~CG"a$ SWʡ\k^hBZS]ʏ6ٖ'qXSέу.>8FHbtLktKqT҃N& Ml 賒sEUʩO]rB4v劚>HǞA`{z./K1n@t '݀Xe!l XKsAR刕Vi]@>]$EXb-В%CZRO3pH:d 6"42I SXDAW&)@HW3?vި.D=)3,wV%c ٶkz"`*EA`oh R50YQ-!YOk-z|a_QhbC[ 3lwt^ >Uc'@gU]GGXlUdw{j9O6U`c6Ym$":qL78A0Na f4Woз`,a_Nv(J!} >`daq,u`uHn!}RYt!/}Wd,,(C!Rb%55"?)^㑘1#Y%#n`_-Em~Z(LǐaԨ @HzFcR*Q&y:O)(hUSV8qaجK`<`HHE-Q6M JS-G ɏ> J:kV)U/5`w$8'P{mO@Ϟ }Vчi /6a(C w,J$`MRѹMDEQ!+>Yg#; j%HXr2ZK"^^{vvXӹեbncR*ۓOb#KX:br/y6RSxr`IkYci0*ZQ+鴖 z7 nLM[F`$ )dj )g¢ cnjկ̻(Jzi E  ӇA^\Q ~EL MJQϠV+]kg+kb4uψln!A;B x 4y~VR y59,\p⺵ ݎ@:*]6~N1,ҹܥUEc >ī2p h:Nuf0dFTY,hVMHo Ei펵n@]&EQغ엥WW~ӧo4}o[\?{-Q21wܞ jjoСx^WW1ɹџ<996G؄ܕB5FoGtV]tͫGKm]ޒ,Wԃ/r[ihukBސ0HҮB9垬=Yhs4t8* Ay</ yVMn(]G"p lu+IJo5NŬ0kJ7Ht8 UMkJُL>~W/ןn<}/˦ *T%+0'V3͑5``0H/IK e+"QRtաF;oUtn!'à*, "}F7m =yѰK>o<μ1-E= p..PuG#ӑlHllɺtINWt͓ûN;Bl |!#ABBD \ Ƨ*V WeG.!JzjfhPϧk]ݬ !"})cTy\!]IXfxK H3.:Y3D˲ miq8015!k%9!n?`bsDE;EMwN.\m9&ڰ׉oW@R f3Z@3NEEkES-> XvC$]]v= Ig8|#48pzD?W,a! t]s1"'k.(je ^}` qhWѣ*$r,ߚLqWjt[hOv{"^~53<7j}zgp*P2 qXa76wb IQBFIKzFs~֔Q3e@)­gxK*O\EкXÔ/uK4'ʙxEtwlt@c9Gb gع(AGD{Furh-* l.6eP-6z!;@}9[Za#'N+ oA{wngLE8+Z d=YDQ]APAFIL'~\1~s|A:pmt% #<BUA,{`[@mo@^~X)0$EU+w9p=*a8\tksd_$PL|"Hl $kùѹ GBNׄcRUg&:̳ %Ƞ<dG+N]9 $ Op\MluT%-V,d/w& nF:Q2AU[(WvBS.nf0߲<|[޷{@]=^<@X3bq H?/R  vWl've4h4SZΌ7Q|gAf Lg#ݏm,H95[@73j-ie]A̽tH:ZɯS6mC{戥hn0 $W{cL*rhE+,yexfqy+hW˥*H#Y$kY!M LȻlH \^ԩ9 9 rk*띚)0gn,hۖ2amED%Љٟa]4Y}>hUY bgmk00xKR :W8.㡃x6a RY^pLLEOXin}zK6 ,Jˇ~]誃WMw+k,*z[$iQyٶ2/Vc!۔s*s>W8k> { .tkt$i'G^7y%&#E@3Abi2'snl [C[w猎FZ3 vNݿ yWS,/hϙ_Om7\ 3~vv] qlwzdvc,NJXsM̠Y+tu[ft/yGɍEJ''BЄ6k[_Az=]ù??4M[տWWht#9Fɡ uz4:T/wX+Z큶PHiڞR,nu íPR7YKYJ޵Х;w̦4t4awOs- ]Tюpfb [,)R@3#q?tOu{]lYdrarpA6[~cPŇ T])gTIj"aݭͱt5 b>nZ:>o}ߐ[;n.6\ao0EĒ$(YfsJ:iB:Eݰ~/g7 IDATOz9RA(b/L>畂oLġ3a%4 +֥쀮6R~tѣ)n'Jm:7?]V]V{JK,%27L+-ʱUђv)Y;;+TM9I3HFsB~Tyݻ5W@ApYD0P@ی{$HQ6"{{IR:1Puj 0<)5zEQG eUK`7킬[i׌%?1l[_ó?5o~f6olh*kYz@&k }{0 0GP tn7@VE.uVХTrPV8+[loI**h?KG^49%,L u3 Dž7+{#>y8)>u`3p*`؛ ;dK7~tޖ!F"0" HpY^ޭ,,h_˗W gO_!g#/_c>wP͙ FQU ٨[}yp VrKU.*Y6n~Pjoa4y$G ~ܲ7jK9օ(=*-s)iw6ЦWXht ֲ9NV􏕴 2O/9 "5"W90%m*hpvZ!aܭT ԫ0we햜WM6H-HW ~.kH/_g?g?y?{OO?Eq&d,Hb-E6[Х&ZiDr@ϦΌ\=/ fp)WKc8t9a ^̈́pdjԲV]([U.JוZ!]QZ]˒-٭rT"Ha++%>yM|! cr]!Lީ;py$pt _(OWؔ`]+F$YXR嶪j 0mަ;H-ԗk&1[kdv/ZQ 꺇a/9VbWDb:ɚ1i](\*&ma]I3Ҩ`^BZzƒC2PϭޔhvH+6TΗj`f7Kw yP4e=  ax 5腇uxcR鄾mQy&rd2쐶y|66e'#DSDWey SdQ5y?7+`gۡ@* !Z&-ߢ7HעIF6ňP;ңІeN g]"9BɁjE[2Wj lnEq+۵]gD7z.tmUp$%sEّ MF:-UkswU0 )0f^-A𨷚)л(l:883ٹ"Pmp.mAlz ZCD Qu{ 9q -u_Ϛ]mU$.NjC[ 7$yJA%_zf2{X4H]9ĎYW@y4M' hN$NK弚*SPk3twUlnA-80E!`'=і4H`BjDXgD vxh UE4 ~VXv|ϐ0+{^~~ّ֧(D`rj,2v=Ŧh 6(A=nB)t(s}yl}]:+hbq(?rB0M^b7RPK);V"It+^&Ժͧe cW}2n=ZMl!V؊_]=#( ϔrvHi)*_(iJuhfzb)%bZicZEu27#)m'yɑp s"9عA8Ekm~E65xSلA7^gQo[0mHY9B!$dQ,RO$o ~[]JEAGs37N]6ǍK%1'2 kHbN5QJ<jg`9EC.P^Z-ez`oUv lp :D>/9z8FtiJm,[d,.zBRi,We8m-j7g68uQZbVAŧl ;ur$-lTHQ].p766gpL:R:w]0@oҳz6=0zeu Ee/`k'Ek%MUқQBIX5=ú(usk7_5ר~ :#e͏OfOM,t$vOSZX/{ײj'4@=f(tm^ hr@nvR0+!/nvEBV!w! MɍF5^w({!,I!^HBA%ptH$0VZjVI*ZEI>?3MCBY\zwzV|WyW}KhXz֍w]k8c(a +VUA[acqx'JT{#a{hjsUtM lteS_1ڔ7Qy.k8H $hPֵznV4zRCrIn)r;.x7kp,ov@q3.JgV{#4pf 骤Cfx6^m^v6^G}܎޿w[˝Gs<%G!jʦ[xоB2[2uloLXsڢ38 sZ(f, 2(.Kx03j䲨Iks"w=hgY$BzZV>?@@W[H 0f d -WW9HjC.m'2yXLA]-1G@8#c'h/9Z[ %}3dWrDSb[ Z2Kr8zoSZ:,?iAohC){+UtD9`ͨBICU :!vqyvSӠ ތNOj8Z4k[^ +gR0徙M?Y^ia"dYxK%]^Zs]\y^?-{}u1-3sx{/?S?ŧ>y*yZ 8A(+K(ɣ7ΨpdiAOqs!lLU;FkaD)'T́ Nk+-aN!-5wM㜥p|t9p9 xfz4Y}A(W)م-[ܶ10R.4-K*` r;aVwK`A=C|w]g/Cٟekkޟ8gzUʢWȨB'YP'<`J+& VA٠sǠ~"GWFE+Z&%RϯI!`΅-i'DX/Ywwwh1 3}.6 859ᩐ.(ҵwlTrǼm,bRUw5 4FU6㵾S?Y]^qwШZ?e|h #?#O_?i0/>87s A^@8X0#H0 ep32OID 6X~)z ռ,dĝ3!{LJO)~~뿍Ϛ)'IӞv =]υpTKθ0OH<Bt]m.\E{v6| %q#cp~GO >Bh0UNt$KL5n |C.{}>.Z)AJ:MXN ӑS`.`zx"ħrT[(leV [X)}kkPu۹.(Wg KG k# $`^ms Y|^]Wuyy ~TLJ1F~g~w??ۣU^Ј捝Omi$pN߂B|W/e'U_xĆI+%g&}uD&4_@1:Jl.ҧ0|3SPS0XXF_T&_bDxN`=ckK=|П_vl-jʹipR J9- @䆞UO~s SxMG{S;jvABiD = qJ'( mgbAO*d2g&NzQ?HӾ#}lE}]W^SrR`@ 螹Thk!usx>|_υᛂ Ṛ>WE~sgEjsT7T,|{ܱJaߧUHOOS?S|3~g?}}/ſ?Ÿ?_#[8f +ēF5O%¢xe k_apo7WH}|2y2.š6 r5yatw967㷡X6#~D>@x@ۅu-0`I u};7w[Q׷K=.? C ?g ??˯ꯒsW^O? S_f@+; =wK\}7-0SBsﲕ #*79Fkǿ8(ᓟǏR{ulA"  ps\3}'qosq8iבN|nqd4XC`+!byxkLyvD0D@碚SqgyK8\Gwq/^o0>{F:E5̩緆;~^^zx{?yw}y9{ŰOo+ܽ-&K݂sy t;>'>{~'?Iկ_*'ЛAo|DJG3=zubg1FMFvpJ᷹7H8l_ {n:8 <xGk;]*""r@8!2]IfvdNdȅ+O<Nʁ.? `.A۔Υ^svYw껿>|(FRr=Ljk H߾̠>KRM]l˱w,WXWxѧM|_@%buq5[9Ϡ 茶\nB-j`ø|V"ڼS|//ӧOZ@_eD__ܟW~WxWL=r} e:GCxl\N IDAT#,9\ގ7z߸*A/sG\X2⩚mϒy7sZ6.#*;W>cZ׷TJ<hDW^Oc5yvs>C _n]/H0)zi |+нXvn]^%ICHFAw yxS ).s-D  {@!8 B, |+hم줧 -wR7xՏ-p!p:I8g8)rD١pf#k@xu b,ؘ/@c!>Y lD <"G,-JI~Rao,C4GfHB.(5 "X D"k'p&@ k%Ja+n#ыlԾsnW@oV=/KYE᳔ֿS{hrQ[CܪS[c5/'䟬?~N7) $:J?{#˖i~ko3gDsn>ȢP& [bVIHwJĄ1& FlԌ'-A[՝Y]P =xl<5ʮy7g"FXBxlrF K*'O$t )>-$CbE`WfzD:&$l`""N/N~OΕƘM|٧{:qH+qO } |h|9ЩVmO5~{F:VН?p,]Y;ڄv%gV{f{LNH7T䥠ەP2KH+Av&^r8j>3њJ!~š򟏊Xy@E t 5u\ue;42J;!tQ_hS0l>}J?g<_uhO'y)vКpe@;Ub0+aMۇl 'fEZQo/=Щ6eyc &zɩf~ʅwJEx}P8l8 Xˌ9 փοAs gag+]6w1iW>|;OYf9PGAVf.πqA=QS߉+ o/LLAqCvRjs6y},Ԝ%wP39 5u<(WV G製+쑧N.<_ZĕهW8J́VrZj?~JPydyr姨XXt^ڙJmHvV=F( g8kUyLPS@]Nۼ fB}^Z6!ɟ>/ ^qPH4+?l:bN=5PBeԌ*-*N 2Pfu7}IV~DԽnu&CZT`Ω*mŒlrO~*w1! t~"C9Y`V +J罴d ;>{ ʤƉr.ۗBX@90~~bs!6[!U7xڒ|3}uWtZ6ʕ iS>``9{YelX28n-V{mWҹi3(ګ6}?5N}|[&E''ɶ)(槿={;|_diFipE , BXF2eŘ"Uط*㳐`V݂Qέ\`^0}[Fuu 5l1slZ~V76gnWYg@ cqtYhP ( ~-\ѵ`eo箠 ] Zf݃t tjY*THg׻57Q|>Fd?gr @YtO'hI *Kc'Sa>xR;6˜1HKW3˺z8#歳䬮&;M g~#D}ޮ9}g"}m3?pE ЮCkqhэ+hCj%h4G(zBܜwOE3o RPWА]N ]Qc<ǩNԉ'UMO{;\hU=yJ:Z_5ً0 tJKvquE}e'I9p$o8iSV=<S`,XhϪzΛ g)اP>-^llx<We}4?ӯ? \ucOjBWEOCgwm$ebP/,)$sZCQ''Vvc)ד : :.!yM#"22fe z$yZr CSɹEG"}Ρ&ީN6[.)"ܞG֗1$f="g g~~~bO@8rTg\3Zfz\0xP{D+hL*JN~6 ]e38TDZC:4BJ9(;X'Xqm^yCڡx@UՕ;++I$v̊P~( N6JistaN>J:I2;n)M.8ٶ{vBϷgȬ 88j Jrȓ4÷>̭Ϝ Ϭ|+w]~~0šz=P@%w^RECsVf!a8&q+ő˼CIjQ)i._d'̃'?$tճYOsA0v6X/VI=r݁d(%jv@*:"o`W5)uL1=rԑ=#W=C J.9ٚz֍%F[Rd]r(;98`r>0ώl!TlfH@'awT 0ʹK积y:>7}7 gsRmI.R9U)]mhNbibIfݒᬳi!EAS=|d~Az]X)!10gaUu YI/EXX3ryh w# G'S &x Ƒ^ t" /r`I4ieRI HD)Q9XsZ0O<sc8\=cqGָC~Z*?-@pbYWUo=//?#~~ov_[ɢVp(B8 5\c06VQ39ʐ~S[y7U/;D*z .B:6>-TIUh"sVЖ-h#* "qo0LdP~բɼdx/7U\MV d9۫+7Z,Scs?GTX HIE5z͍Ѿm lQF DzkvkiD9Z8vFqy!mYT;|ʃ?_s=>c>c~~k_+Co@cQʼ]A/)*BΫ, L2s)rl9r4YQ46/o]38$'к {>BVGzE5R퍵T?z)J'5x(fmh|nD.Pl ub:bS4%5o?w[~be .Ծ^*]A:ޕ4-4n"K 'TlOA24N^" " :PWPJSi:NZ\sl;8 l+D=;gρӏDu3O7KA^nZ382x'^BAN)ꄆ.̬diVKm|1S1<=:Ee̶O<$7Ҩc;B $e):39M$d: ҏUM##"90xq ] Ttr@d[Az7eG}`JHװ~hM }܍a40;;炆 IDAT(Alk4{c*pVk" YAٶ cI eΣ*A &-[h)6X ΀U;5x `葦!`oi 3Ϳ}R(,겈oʍ15Gq?Ք?z74I j+d=FRVbzH#!ѩz~9uH kEWl]d=אVB\+ qAi"'ۺqlNdre\ؓNԳm`@UXJ`E盰*,n@k@O qe u ɫiO+lOsf9uBi'y29VN΀%~R~W{C, 4WТtDp.;>ɔS)V= h\s9z`ޝx颢1EXh`-5zV-B M Nֈ(!ٖ iY=~>ۭ"׊T<]Ê3)π \ 7O0:6I儢АGIqbokmNhҬTU h{pǖbok#샮fFʁA4G1iĆ \Ax`yԴ4AAwooA7 [E."F哣|u M[i9Iv˱'Ɏn͋{j xP Q6ĸR{xhs'rRc6CڀUJbh ?*ȧ63?pTQ|rI7 .vYE _Zդ؁"R`iT5Hm$#겹v@;zгA4VyVJ;V ـn+Tk^k8EpHCZƒ)f=ɲz {KMEfo%H*l$՞ hb# %Ve%z>MfF\%'PΓU4`ΪHgf]rrvj gOy_g@rP -rra<Ţ^Rf1dMT0/PRCrz? Z胥I, cQaֽ-NA36@- mR]=Kn'jMr;ERM9O;k%Z@4H&\\l phTq :* [6$gm{e_b[w\2* Rԉ+ \ZsD8$d$ڃGE欜N I$Ur4OZ;{٦na9Nz}[?|v \rc-A!gpfѹY>;wmA)KSCfodyrZN]#A%0Z SMcU/@i37j^R uSkq!^My,;{@ /Qu \slƠ ʭ{[DP.6% ex9r>zK`t0GxK&.EAD.!d~ߎe[cl\25<@"-:Ey~5`JŅM{[/m).NЏ@Y9yulxn;k" ڇ#!j9!;wYɘ+ b]@;֚Q |Od@梞*]m*B~j6|\ 2?8-sCN25rQF"ת`#n\=߈rzlQ. ؓ)[ 䴺DMM#;z*!|I/ |!$^K \ĥ.db9Ypֽ)hukCT_'!B\|", ,д@ʸNdY.ճx ]Жn\Q%c/:59.{dHk{Ynowj=7-N o$" BU{ΓWs#7߷Y6}!.58A9L2zΊy#v` \aw p#6o_+3HG%z [D7(y6UOMR?%SՊZ,‘Rʗ_ Tx!Dx }@<x4̮Q'YDŽLngH@VhBL5<4h}+ʹ^@y߀s&C#8[>p/= ,DNd8{ չ0KR"w4%-}|p(KULfl,%l&22JOg)ՂK;,>Vnk4- }v 9<,^ ktvnlqEeAQ$tH ~U4` bR' I\EU2 1q1N@p!z޻z>N;7sVϞL\@vH@IhxFZ^m&+Ijb*gxH-._-.U~kP4Ȭ07Y?gHu.A"tb@P$nVb z#MkU3yw;ڜ2AE(EqޜyZi`LcJt1LIH>sxa %og]DWR.(,>3`U¹qNh>Yg@#V7JQ!1BڇUcjngH ;:W 5Ŭ\ zZ67*^r'O//[~JqP+¾4R@s P8y \ABӥ-_AҪT:琄 GueyZlBԴih/vs;TTH?k1(-| =B@[y>5`"o/:SXvkQMP{2Q|i.YF>{B9f7t28gٲ69-E߫U;M{)v:刈0A':J(Ɣ<:mx8hGds\ӆУנ׊^  6"o#&xÂ炟 /C>y TFO4 IVİΔ2+/`D%.tayڠqEJ ) ۄCRʘT<0X[xn itOm;ҴhjX[aCn8 zmEp/΀ۿ|[VO4;i~UТsuvkٛژUsa3zƸjs~Y FzfLE輕hl(NGPa5S*gaizF9j5kC~n}||-pouI0{ >%Ȏ]9^5K@ =@S3[_$Yi[]$i|`@F!bD}]Rg6kX!¶%( if5K"+u:vEe EyYo ҼS..;Jx:NT 94Q, ?˿AOX3?ck;˱vkV1?PCv8+ʭY?DnskWKnAbn4`]L U:Q몷PW }Rz #6{D=0{NH,#jM:`/c)LhW{9j@X6FVkI:L^˞x ^XN6QTᅪZd"#$GoJlo,uIW%;f 0&x cA9Da v.TBHӶ԰u3y+I208Ix["輽W$vҨ;>MB3?p,goRJ p 㡇 IDATLrQJ8 ;rRHEeBxb싄NlѡRԇjBѶր`R0Ɣ$kڐlo8e)Lp^`UIF N50.;)mFxgYI_ ˝VFPTR\A+4jK wLrrP侀f@YXR]NVwbnr? LXBwi5-RIFIk!l % %R ̌FN&:5jyB'b=!׮9unkT{z>8#y]g@#VܠMMkk[rl6[RczYng27N.cDl)޳Usi+iQsΡ o=!A%Yt(Jct8UWD:eXEKcql=-=ظQF,­ۨ\pTyB%q%Yp r@brO)ĂĆQ|"#^#w,InJ^K%\IN \@*a+fmd{ca40;a$~p8D:=JFPl[sVij^p(eE25[BzCZ$Gt0Y L$½&~ )P*M=(LkH>yL/x%+6 [W)x`bO==b$< t Xx`lOTA9XMx gi"ϕ_GL9ڑ@uhjlZXAus¹!yy{.D4Yc֬EfH e v>28K6.y >rˡ܋%jYdB44!!}>d Y0szpj$YްuՃ/wz')4z'ȝ8Xa&U*W [&Q5ojƒ0&F(Ko5um#/ ^)0T Wfmĭ2&B$=A 38IG D :Y9$A*GQ`HR^Bȍ.xi}dꏄ#@7S}XTs+"+:V+RzucC9Gmr;%גnTG{urwAZU!%hd[PjҾ)T {NBNzkC^\=k溉NAQKYƐ8H3 Gv%"V,0-Y=Cmȑsxhu8a5)`M6zPeX;*Kvq(uk HKz FV0߿!|K6vW"*K6D\ML@⁉G"$ݓdG҃{#;`I`Cǚ5J960t) I \|y/o{Xs+Y`pup"kvz|Yag$/{ֱT(ļ4?%"R37P}6Hg܇lmhtyxLjuPO ȀMnJ, m}&"Az.ZMG3v[hZ VaF':}@:&$i}5$8H@;°''d aCQtdׯ"р*!W "/#LJi}$;xO=>x$#[=#]kd+وJ+&޻v1kuݻ-Zs&(/9A䘈 FLk(LbkbŘM(bpSRzk`zt@v:7G;.(f}#.R]=P ])֌prSp1 zd cQÚXťK<{LaעrF21eYr2eu4hpґh%!H3 hiG8:0XoΖ!|V\κNaOnA7E1agzD;[JLBf9aR В`Ս&yC諧 #TcJ58{Cg:võ zЇ* Q Dxd "ri=2haFsEec4b#Ls)V} 뚳!9* 2~9d)˜=Mh*Yti SpW+<jzycU[J.x#_Zl3F)ۚJ([} |M0es QPbxy6bna eaGwEױB7s6ݹ #dert&hWk^@с"C[X (##\.`dru`N CMsO2).3I`)XðIƦ:u,5j&E#(iQc5Ɍ-Ķa9 Ac9Χ.WTtW X{~^OyUѥĉD.W~Q\u RrB=ׁzG#qj)`EJGItdЉ=ǣz$oś,0Zz iVr6m|j "I9\h=.LTA #SapzA'HkYG&p!Y׳g-G%QY;m' Q&A}jF FNJݒ9k*aXRaS2@-kssdd`!jB‘ mVd9w<R 9jz44)JY.qxl[c,QX7.U)Vv8%T/Tcmꌧ*r:8ۺUjH*;HhJIv[0 mZNtgObmD,|*H5dN:Hx ccУP1JР#4#] X,탴a㇞#WmONQtųA±adžbYsln1SL=:3c< fb]ڨFi`9E5Ӗg_zE^ChiGdZ䍳eR{%9Ğ(kme-sרy sj64 >nj : 9Tۇe$Y(SX#8"#SI*8qPǜRސ9ihvHzJT8˞۶NT=AðccmςGbB#kI҈bY˚3c(O 2b;\ƲNPNs}Tf&\.`VM1lc] C‘ fb -ɊeFYC¯@HJƅa`3WQrf$ M\C%(Wp]lgC6$҂* CM+r ZWLjWHX䍚\מkh^Τ:ǩƜ F9wtYwFc&<ʮ*xQT9{AQ>qYQDzG2xG( jX6p K>uaqԢ m! P%l .d}z`z"6blt9d#0fY'>:s<$2EYiL4t#FZsI ;QKƷk$uSL t'I#17lNIF%8=<}f{Z sԜ1.2iGpz2L(ZjڈplT!AShQONQ=EIk=A8Ai+3H/s_CG̻ʉଁ=\ U.r ql"ll.7=°OSG^Sp1lGycP8rjCtܖZxf#ypC}Iڮ13b˃ RTdʁ9W9H)RhԞV?'m)$iuY+6tY8CԵRxەakhNjtNrεJ2 )(4yxptqphCw@8!hMŜ;@GbA&)ix `=l]j༦Z| 혶C<xsE+\z.IJ5Cn:] s*'dܠBE!s\G ghO r\ NlȞGVdυ 54Iw+M✦rGt*ZdR a,r\<_:yGnn*\Laj4igglLbɢsQ$}e8/0ecbz1(7R Ւ\Gl7-dxr@-$‚ YmC9.] Y:Bl1Ю} iP=e+쫲/ʞ*Ue RL1:o7:DVz 8P)C㸨n&7q&s#;HZlǰ޳ynv- 71=q]!:^U [+r)% kJ:#009/ܐƩDP0dѠ !%x-`(S)*LY {?Or`huDBr0-GXc5/C|LS5vh9xX,~t|al]8b H# 1\Q!hmf q6PH̼azW0$y#DXڂmiKh|ۂfKߚn:EĥK{x_1pԟ(5]]e9IRSb)9HxA^] {^Ԉ.ebRNyOտ'݆熠9jAs%2LE< , Qv\;" KL0oYxSDfvcE;JQ) cX#Qs H =2]^ףı!Vǂ/98a>Qt+CiMp &`O3vt0 uZ;Qn3]&V:aj3ͅ.VR͔#dVՐ ׮Ε zj{~y߼+^ :wy'{/{/~ٍt(]\ݕ ֯Z\7ΰjG^Ğkwh/%,{mJ=ʲ`VK,K !fA[HjN0 0~x*i#.ۡl%66hh5319E[8(i@HaO}Td:@%$uT6n= { o}A-aM~xy r>߁ ~ffA~mAvu]-LLj+%{Wŋ!\T8 mqJNI#e˻5Lu,h[nᓟk?0_җ_rDymi37StuJ+X+ĕL^XwyRW^(j\ڮRbλRV}+R,E\VW N0rÁ6CԁU >y ݆Ȝg5P-,mK5LYS|WYB! p,={">RɤjaL Ov(}  +ٵEvsW\?[YwK_^E /k!o&s`H\fmfHzLeQ穅WN;enb}3A+c;iKɠP IDAT}&x!|=t9^,:`KWί5#o{{x[7ٟXQV;<,W^(.Sia8ccj:n5鰕ƹK칾AMwƄ:vddT?U-(xin)8`yc=4t9Ygdk44 *kY-H 0C@OI7Q?~W,',zْY7j[Dy ɹ9!N;T J'  m!&RlvR#cL0usq)y_&{*+4+x Tե.e+L V+E?~ߞy>FW|Qi2%8U9zM]EYJu:s:ΖU}"dPs,ZDI{8z \`ւd X݊ mq sD#/Z -kYh2gVSUNNU9E9AaXHh+aܿjx?@=H+V9*e\"܈a XpȈO'Ly ߎƛM2r- (N"@kН]ͱ"-!*@00ZJ/t{uhNfpxu8_14 aYv)^ @;qդ`uY^̞W7:ge廩. ?LT%s}rYA=Xɫeؽ>3fƢE3;??s J;(pP-ClJ ̹%HvcGH5IT,-4>*kAZq =Yd/ bv{*lqu\r EiY#82] .N]Ca6p)'5pGp{0tֺ_S|_Țo`VS5ҩb\5jŐck)꒜ $pڲzG$Q.nTzxxK|V>+k񡥼׭k)9IE+Tb;A Z*]mӔ \k=X" ϩ#sfe)Gz_`ip-ejlGgq.=Tz9CE=Ag dW/ rEi V"*֙Egn : nıxȼXHrp`#F88Fڄ|>TP0k!h9C8s E3a$Bd [JpV%1gETwi>Z4L%[򤄠J񱎤lPrveb4|ZQ+.6`PVImi<ˑ1 >l2f|Xgh!0 x4Ju ҆"C2Ɩfc {9CM?yW]+ )U .c[L=s<>݆.*`t'LgJj2P07 ]%Z[Pl)v]pJl,Ԑ8Laˋ xuxI9|:BK,m,m$5LzeC-[xaG }@B NG{ 76JB48va {N8,( VО@kG0[!C7Ƕ <Ӹ㒤0IE @#m,(ĴTh'1kHOlHGàWg%-kge|HyB5̙%X[מ5&VCԪYw5eQO=Xs^4H/% oh,>0Bl0^l4F4/gz*=Pt_PišʎQel_AsgRⴏgA+oGS GF,vGi_rQ0(n f`fE{11V'8`#sv1CT(WKFVO[|E7ok5P[C>C\aU-a,IqFI.,R]J2KuxEiJ}hn-8[k]@Z qP,].:4CGAc ơA0J>&5U  ^e ~bu9AtB1􃀣0!Ui rn8-о^(.nG)f]9=ÙScNp20#s.B;=#g>^#“{Uӕ%pN#YsZ j,"84:#M@,guk_*?zY{vڵX] qR&B؛ztHTXT% (E(Z(F8RtdYdY*95Qj08rDrD[ .ة T'DL Xi;g޲{~A+;CeT/#2b'H6Eά8a._̔ݞai r_0-vm nK)slgFaN0tc,SSth@ =5SOGBL[=z3۰0E8,kgX0YXhZ@:`sMn0W6*s9B]rwhЊDH= ,8T "~j/#\d* kPfSf{\ٱi!lgܶןS91NOprc#΅LPCY =G`I8.2}b sfH{ŪEk#qԣg TO .X$^}\~O~Z=@z])1T*ҭgL uPV҅!ϐdHS9u'S RGdXHf]˖ #j csVmcL)rzBmD c^Li>J^ӂAv>(mhY/Ci0"t H;L;7ϓ!|1fc0-Eg'89qLX9 A{2%S#KΆXzzxG f9 #t%>k< @Ns=Km ֵ+yyUmd&]$!J&.gG_>6E/WFv,1A2s -Z<_A{1sX roV'cEO#EONl-/t8U)a G+h6{th'*nk`]8\ G ߄ tڛ!9w|# 1z''bu0iMaKZlbC-jg!la4ts\1`2Զg̪^CnhY?9h_UXeW!zIX_ωвr(swIzz]TJN#խzjO,0:g`gHWhP,[07t$ر=daHBWҏ˚BON# We"ZXϐ b{|c.<4q1E7shPd  hg{dEНp3kSiI*<XC U@ @WǗRwA^X򝈷gR1j#}Kmل Y8RpJ;W[sNRb,ǣAڙ4- YiG6ZZ7T[A 5{+!@ ]U̞;~1#4;DC+! u{C=+'w7CvmjkANvDx 9qXC9h#m[%8 5lfJ,l_ m 1F."]TH9?zai|KRHU4}jԀz)?XWkK?zv@<\s42=k$Z 룗"T K5'L ] gAm`yXV0@[FdJGk8T詧3DOAQM+C# X62tÖC73}ϕHxh&hUW8|-*6jޒT{exI(3%&,C +&DMg2T$zjЉ`(m Yha)tԑJp>B00=Ȱ@Yѡ"C>fF1]0jUk2zQ^h-7" 0\TNȒ iL¢tl ɇWpC|78޷⼡0BTq){ut>HHzitӧRF8K"'YquW3+*Q5Ϟ>o4Ls(u>4F@6aS5Y̒{K'C8&"ؒ k56A{(v8 Rgz /}9CR 2ge)Ayy/cuXYVK H s( Ӯb 8vq^B:.H)k層?;SI9LbrZV!mŞVtP ,ã?F)Vk^]0caƸeϮzP⹤cx.pon#:h?3NP_1&nEssVp 'ֱE 8pdS:;tR4CEo@k#x !m[ްXs&2g1BŴ$xDY2 SJ@ l˫qq!c5D!P%)YTl1/\aGtybiH-z\ Yp -a^.J'ٳec`D i/6HϢ=0[Srg+%s7H!ceыp NpG&10 np"UW{p;)00s\Y o8 [uĭ}3M(XB8/IL Gpj=+~Ooe={ʹϳ1\U Ckg%J=9XgкDxTw$iCDum!0:H,>Rm _DYrŊK0a|[ th%HKk:6d{ =2L[Ƴ3v%0It A @:jK hX:G Ǻ)/VCNpX5iD|5_^UV  {ZHŚeyʮ!z:@ekUKT,b72dxBH+RFJpk)'j`- r$b{7q}^g7Ns0&9jкы Q%8bxk\mLmp`zV!ٗ'HL7DwIڰ>fI;>:|ghg2''!_x^W@XbOa7ŗk|X@Wk=вzevW3F\"8뒼W_ kYZ[H'}fR)ڷ ~ɔ[_8߿EЛQ yqGz t0E0Ae ,Vr./ٸaIژZH=(hdρ9並 uk༅_ pwty}#dYfss?"%+ǂںi_:b/B-:˩F^*?|%%8ϭ2wC K=+q)Pq$Y9**Mx>ț7b~׿>}yvOseR/Q,mK+hm'K ֶ d9]^-eJ`Ρ;T#v %vK[X\[BNB]IXD<6P펅 *UƢ9VHCU$ϒ16Vd3 ^#8o:e]V%O?u]?H?w}7gqR.?s?w͏WW|_Z5=^W||^x' ,exN;3{w{wo oxoƇ?aO>Ɠo|#oxwy^/ţ>ʫ^*^#p7?ǩw߽Ts-ⳟ,;;;|}{{{X<??̻.~|[n땯|%??>9TM[GOr˙[L }e>?̗%mj˿Kyϧ>)~~ '>]wm㼸馛x衇1z!nkriʹdO}xs%^s뭷^ctMLS ׮>{~7ykx׻% iw=y}kyk;Q~|~zx̛&666 ozٟΫ_j|fJ~x5;d2Moz[[[E\c'馛x?c5;wK4DM4&IDM4h&tߵ|o}+FgyG?xoy[fc63 u{wy'v|;3o=wodk^/;hGM|׆77~|s(;;;կ~b%nfЇ>|>{WOFM\5:&kCDxk_;Nopw\ʝ~A~'Nn nD|C󶷽wگL&>.lƗe~臚 &A7?:>Os%7y?wq/zы&u4 Wn^6s:DM4A7DMT@ENxkRARE|ҿ~.U <}85ࡐ8p Bd/)))(:蚚^xΞ=ŋ0`111L2o{:^~Nxy"Buªwa /|>T &6@/L>81wZ.=_F*AS<:1=IGz^6lx wKBtzGN Tj\NxgRSq> r3zo 81G?e8!~;_C%02k#bB{:{c2Or}DC  :Co޼t:cg5? $  9&IJCC/ *Jɓ' jrAa T*W^lg?RA.AAkA; k"sЖp!g:{Pp  qo1pGcFMϪ> 8g0ՙRfP ! 7w}Vٵk#Gl2j(v waܸq8b 0h{; _)mAAA^]so8{)PWP'HpQDdsW~GJJ6#(//,K.5ŋׯPPP J(U[J.,,X+lF`cFgBr85_uL aЉAhi-[SS5AZ' ӣϫ\y ػt٩fԩ8qѣG?ӭ[vǵeݻo>&Mę3g;ϗrيĒo ..A廴?ɋuDZJZQ"ٵs5Fo9YYY]A/.2;/]V̘1Ç3l0v؁Ec۳[nwiii? )X,&|FU 2aPȪhQtc@^M9y%P):gE=I>xcGhB5dO6_@0*I1k,0`vB,7ofʔ)={Gydϲe1ߜ cBR9z?W,U.렃lLs4Qo$j3kA†^h8$ɋ]g15(1ڵ}go]Yn=z`˖-{,%Rk0mË/޽ЩS/ª¸RuNZl.*5J迢_R R$8H|G`jpN[ͅH!D!ev`2( o۶m 9993g???AV wv=HHa L( Z leYYA!D!tH(ܛp/ tU'<"_Jcc=o_n;p=|)Tĥ?^y.G/$**ʦyK߾}Yj&y摙i}oV$^vgí;o3̓䐳,Ǯd2S\\3z:仳NNZ2|}}$?:ⳤ:{YVa4:'Dw<ƺjKH!־\)9m>`޽ۗve]{=ƌCRR]kP)Pg^V6|r*s8}8|}ZK:hFl!RXXȽ#1)42>QyRy-ɓ+}8ӓ/~m.\`:oF$LOa`abh"cS&2y=j?5QގXU6X27)^d=dt{wLz)Sϯl0< }==v֭uuu<.k)?+Nc&<RSa$nPfc0]f' ^^b=iϑR6aj0q1뱴!uZC4GR_PgL;/$ O?-ɜ#ݻuI&g"#̙UUs'[4<2CهԅUѣ*qI!+,,pj܏rѥL{;H:JDzQ=8W^ye˖VK.^^^|,Y2)T\V$˃  $D܈aMg7P^KI6%KȵjqImިPPP2uWs&*|Qx%c|MxGjᣪ%HaѣGcQXXȟ' V\\R$ܿɓ0uӬOYRsRJt&%`0#9%9SxƙKkKHh-#a r ?辴;A m^J8w}Zwߕ ʕ+9z$s:  AǏ|X]*,#9GҍQC9;JrqIݡ0;h@ee+;ʛbeO:~O8kI*]'AXd ^{MHF* 1㪸HXY s9gOO X||l=;JESVZ"evj$pt_V~T*?w7 )AcvE=x%׌vY`{槟~⧟~l^G"aJ "VktG.EyDZ}w-.cM#n!9t~-YKkMERt \i-xz6ԐL:5%7K|x{K_*]4 oKQHvXߜӧ[oͮ)S S8Sx~HH6 P%uG޸ݻ)JLW޺@cemi' ĹG]zi&Ξ=ѣ뮻$Zesܹs[9r;wtnGX{χZxزEذs@ s:""{HK:R:t@QQQJ(ZW h-%ľv#̳y[o믿./V_ Q+VH cCg2HPn)Έ?`|lkˉK:谰0"""0 jRtep\(N\ d5卞qCE@ t< }9s#F0aWy92}tJrr27o|~QHwX:w( . 3q4(I\p Fzt?:hhЛ (jN ~~D>ChxAx7yg.*Yjd+F$4;XLoђަ8h&]Z5nt73}M/t}+])W%;J}vN:Ő!C{=t09Ylc ǎy폳3@Wn :bCztc:PyrA38G FRK3-k.N8dhv3f C ̙3ݻWHSE/# #Clxt8$$vgOUX%,B>e=& {ձ**UG=uؒg ?=#ЃP\ ^{!䴋J 2*8峢…bGKaFvk3Ա)muib\$qGb0ZMq2h239u#wy.G;Ǭt{Q tcǎȑ#3sLOn̞=XvMJ[ނ>+/èQjDFBb",Ync}{yq'u.|_Ir/"u:>guغJ(PփCw D_z ?/Y;.pge1ߜ cNJ%tG;-7z]jRn';pQT$lAύS7Rgp܁_c3NxXޣV )+F#LbaU][oE实͵]TPtGRRRbG04kqaC%~z΋;;MqaDA}^=KonS__ϣ>J@@h"Odn"2zK1oy翧P=܃s- UKA"U6opQ-5RDB3{bE $ u:aaÆɓ'INNvj1h:]ʳ@iZR#.s; Hhi|ʃug`ll-FCVHף^yFŕwP"-vQT Ie%̝+==v+W11_˽;ERL1"^oo]^e?E`I%eeelݺ`~"Xilq 8.> ^^^YFq6II!Cjnp'NrC:Gh1G~JjlD\AE4E4\ Jsm(Dy5f6l@}}=w>>>ľKE\GβKXXgϦ)kh lvXߜӧ[oMקݛ܈˨7ǻ7ƁA%Y$TTDDDPTT~c}fs[k|{#w%7@Y"իxE;.J ۴I}xxP[ [ P3kT{2֖^:E7EY$1a4)-m׆oޠgvB UǫK ufk 9r=z0b])Q32vXw9wq#$;ƌ?`xepPn[z~+RN_˵-埕,:hHpuqQgRDom7hgEVpB@Yba6ٻW,;zwNpu _m[pG2` :wV_zբwAgmg}\l̍@k}dPNY%&1C3hgexxx_S__&&6y'} :y UWuq;2G^;H%A{=x;c.jzCi9PHo>;v,qqq7(vdm6LM` xUe@[`L̑}]ζ ~;پ}"(9|F 㐐eYܣ+>ǐCHh}55`BA[BNN\dgg7ÇϚE\$A6w_SV?]}@-n޼jf͚VmZs,G(v{y aB\Ht)l(|u+mq׎sGÕ+WrJ6V /^gÆ lٲӧOpҥƼܹs@ Otig,I{GԵyZ`Acӊ҈\IFU޿𛶋yk֬qZRSa(Vb`d$'][^;|0SYɌn3KՑEbU˗"99-[PQQP p ԰h" {Ϸ~hk׮=|0 IDATxBhˋHrr{\z?eĿ7㻎h鉧)w hdPHMM ~~-srrҥ ;wʕ+5ͮh ggclvi` 22rU#Ύ0v,5_|_n =7cssR)TĀDLL W^gG᫯y=~~~č3qMStԉ|FU'v1>D.|C׷L4E0w\VXw}ǓO>)MF_୷į_|yqE4٤rX&[P@DDSN,k*6sQ^[{J aw)ƍ8 И0W+XJ\t>ު>1>D>*Vt\]aơPHhfԨQDGGo>JCQn^Wlt4kVJ->?(XA`BWu7l6p Il8,(PC)*O!4Y;U g϶i|Ar1նZ)jAظq7XFj< 2%ZAhLo]Y g֭=/pX cѧ)Z,e 6 &]mslb)lL݈Ɨ{hkMt^Ač"=9hϡԜ?>q:)~lO5єEgX3a0ΙUUs'D(&)ms~Qg&.xuf?q8%5`k={nNs4VoLSnz/?ȑ#/w'SK%WDA[nbyyb>O:ٱx,UM,ް@n~yC[ɸQ$ .=6v,=B{p(g6{d8Zٹs'iӦIRRsYK#U fXXɓ0uUS(&mq2#.8qc-S}n0n U*;w*nUו{)~hyxGyS<^*w}(#b<~<âEpt~RmCa_Zejt"hA!<<+͸Q$i` n[ʃOM=G ?ܹ&M$ټj/5K`4W Lj#|2ǎkJ;W9{z_ʕ`QMZ$um)է;R\" .o A% bUs!bFnp0֊n"VlHmr#lJDWo p-\A(f4j x _ʏqORR9999yeM:a4v]/͝;^SNv6,4 j~]n>Aϼ|8YYYN(.LD61s g2,j"˽NPyK~;vrfzz_zft 39B̙3Ӈ^$f/]^\kdm2.+`F# ˖lTMaU˭÷/7Qs%Pբj%k?Cw-ݺ;9QMQP]Mp_}V՝u t```+t- FѕTWW}}'cO6+G?v]^h[+V 1225gͯ'Nˉbm҄/O}IGn{_O_ƶTQYYIUUˤ7EtK"!HTgP* Ěh ɅOii)cǎ 6L{5%lF|_AQ()NaBxq#ҥq#\;CFg0|v3d-Up@.[ AZʣ&Bdž2~{wځZFOS۲+t:x!xajg9ͱyf9V(W$Gwߞksrr%D%tk"7aaa\zզeccUxFx콙}fK9_|ަuˍ\MiaYh bb5k &ŋAeIGbf 6QwC[)))!** ?g5v w5Dš:jO*8Etk"!79/yQU_ӫ_n~ѳa(ȅΧ4lX^L "nDy -kQTlٲI!R6P^[D~o\A%Tm݉І U'uXןCGi 3!tzy{EAl~ߓ'aTɦ`ԨQrI54ӓfOU #hњH @ffUsV{-aPAs콼ת{ȍOQQ&**AI:D=-q.?EĈyxχE!jIp=9$&%q,etZPn6x4q;hҖH+Wn|[=79@1LG2) [ J]V[[N2TVܹbSlr%ȴ"VH2] ۼEt["9AWXn}n3g)o#,êȉRM 󿭗Ib2D G6޽;#--tIVHW3k kp|s3~w@ QTV8Lu& ķGOJDoooZE6Elz~l+6\yh%=Gc*V ;膆󉊊rhs)p^-4dj|i_Ŀ-^C6s)-c홵)WHo鴠 /}쒝 c5ͻw+o6t‘#G>))J [k?f˪?M`Nyyyr pQݖH 8h.~t#EI%FoߎFacrAHz܇j+= Ç 'Nh֡jr֭[%" ?X2|Uo=!nK$Š#Q ?ܶ=AWdjH%9r"ƎKppU-J (PW15a]L&1qP\,7'G^r䡝-4FD`xp:*Co\U um`]-t:(GPT<;T9]~\)a'·SqQ٥ f̀W___Q\ +3~;!!!OTUIb"_DD ֲ@n0kyiM|J 3pp6LNe9oB%44r9RN%9Ylc ǎyr.*<==:u*ٳG9)bb{O0 TBƿm]D$"h[f|4>,`dqI!;w .0`tOq4Ac@uR5*_o._|#F@F1HHpjR<3EBsϡQ[ z ٥iO$4;"#4CFְ ;=~\5z1ƕ…bGKaFs ''Oӓ۷XD"]ߜ\(ɜFఖv@ܧǕpIݞHKǎhlpQSUxzǯ#:0=@ym9'}n<"㼎xvxs1Y@ v|FU 2a;@JKK9|9K$ħx|k.dddҕAgff_l2/Śڥ=4GCCC3:Lz?#K,()a𓗗ѣGʱ}t~3Q Qjf;|sr2+6m{G2c @43D:C*dujsM*`~YbaaaӇ$,X@jjTkKųD(7ܔ~1T+ِl^g۶mHyqgT*VaEk0mË/Ν:9{cvu ץ@W}[4?LT3VedrmؕwY*@԰pB wS|I4 F+W6gIP8jԨ"ܔ_p?>wiWOo& PMkoB!kW0ki5111 0dΝ;-b\~VE>C^dVFhնveŜd-vE~~~|7_G[ƍO)++k.OϞ=Yb]v)uҞHVFЭ䮬et ƙ3쾴[9᧺3f W.pep9+6:rAlF4ED~-3*d[]=;)SVV3E!)|IF̙cXN'<O?-Kg}&d.\(<¢En`v箬w-/ $ +rZ%|v3 h=ECC*xyy ^}?/ 1:N8H;s$駟aժU^E,޾X/;7I/I~K PVVfќGbn`j6?Eׅ >>>dSN $ UUR/O7腈G %$5t:ۜPbbSLxEAIHa';gҝ:صk3gδy[?+֒W'#/ԔH:w!D!7LbJsv8z)V^Mzz:ϼ 8qBؾu, A_RXؼy`|ְUqꍆ9s ^vp"ER]DW߁ƍVeϞ=zpHRj ,PPIn/\PP^wYAwFʕ+yw8<*j}-bH 4*#CQi)[WpF6l`޼yOjXZntmPi%×Qk'id0Lo1h:"w!BͬdeܕԩS`۶mL܀; +*YvtTJh(l _' IDATj|jymXͫG# ~PV[ƪU lk!i>ete%̝+==v+W|>X epqntזЭ}`KÌoRfgHRPn&8:ZFc_od𓓓ɓ'֭ |))0dlݺ"tj(=|)k +%M{sX"aMC K,ERynO ߤ.- [JqT9z6cnUԍZǜ9s#YÆAz:L.n0}AVͽ]{r` ~[@vv6x{{˲GRPRGuu5eeeT%t91c=3gbSQQAbb"aaavs:0f | +`e__]4Z uF]+NJm۬'Hjrr{&:*1՚j,L&KE5G(#hFR?Y(g׮]4440m44υ{ҹGapĉ6M.QEQi;yh9DB ߒob/#xlpR F5xx؎mOnrkŦ7L&1qP\ =~6Ot5mr Jǎ9pC$\e "f![uЖp](̤j0Rxsܛ YhK~|||YPee0c*ڵlxWms]b?̶dgV>}:F;wZ6:hKEBs%72DFŌ"0Ҿ|~K}QQQĉM$%g{ñc0oDS7K@GRVCٞ2ILlIsH-n>g팉uFF٦ᷰI\A[*֠===kNA FF9PKť7V#!#ClxtHXݒ])7jL0___vE]]Ec AoW%%鍶5"a=PT?k,]3hҊ$D17GRTL>][^  t)l֨dt'և=eR,4&M}Y4FJpŝ$'3(rwv7efILJN.t(pKF$!66,Jϔw"FoS('99lNǎ%\ Fsd$$&’% ÆҨzƕӐV AobY OQ`j_5)+++)))!..%J%WoH9 9 p;q+>kb99ƎϣGvx$Z -е7u]T*nj)H9s #gT5J#A#P{~+gpQmHлwovZFF4-~ꠍFx5qvy9X,chkvi|<S+ʺر#Ç';;SN{"I0ʿ݂o{J^wb?m;@E5"!\Ďa|񤗤:IlO:STS[oV+6kFzػyabYJ,=ALR;C.4mHrr*s= j<ИnA .]DV$N&r,.Q[߲+nKqXzc&<RSa$nc~[AxxSYݸ2rHBCC駟l:[EŠ =.jƿe2w1LdIH"؋RXCUjhR*vD%{&3{~\3Md}_{s<{99D3Ǣx㊍  \SNUy"OQ?!$یG O8A} r8 co4otڈD˜B ,AҠo¿AOuT%;wEEE߿?D"#Ϟ}؂Gh$oH3,4&E$(U!Wi&UpF$,}Z yM6`w;o3LB1~ވ`S"#^ d聦M-x}FFݸ2`Um".\by1uZ1T%F[t`_,1⻠ aU*<׾Ze08r|>BBB a& b Ҁɓ Tε|f< u]*un\qvvFPPrssq…JV$LKkd=k2.]k8mh#*vEڵs΁T!W/z^s5<{ ݺu;1g[[`V`&0m1QC0FB[ALrdv\Qx6sr7.O1l٨ ?͛77{A4CaZ(Nm[-9,tƒ7X_B+QcΝl~s\nnNqK78wpFb3U۷GBB޽[6sB0_EhlZA^RH(ϑC,' *>l!Zx@xR8U#,/ ? sZlFnPi)0}:U[*eah+xrۿItJ4?__L{cA Rr/VoA[ E7 ,ʒ`eygiyE 'O=ٜS +*ˮ9ϑ}<>bJsК ai6Mo`ocZj rMA[WP1@m`M]𣷃>{M:wf keߖ3w\Yc6mHKK+wL9u{.=^m1D#YY59'F큵5:s"aY?5{eȗxMY'++ .\7:t cde3f>>~ @]sޓw#m{ַqEUwmY-dHRg(xĶ%² 5W ++;v `Сe.D"`.`ZN`ZZz)a7ܸRU9Yva>ŨxȪ4 !¡Cgff";;1ASaZ3<'^w3w|Tm|z`ZPr]!8(ׯwwwB.)_B~^Tuf<Εt0W* s0vHvpm8sBB䞶/9^L| <> \cZ:BaÆЂ]b&2K ¦VW$mB&YUk#O9T8S}x#38;ٙ-xKT*x<gX"e'kȓajxk&O"OKc ߿A$JHbYE۶m7o4m7E=zy{'>:[X6mpa&:x,Ъ[訦K" ph|EZW UVwʹt}ݰ3Z 傔4K^^R]H_LSaE5>9 6܈bw#6l`))l˗~<^9P=zT='JF} 7v MoƟA[ 5U *A#0 ėaceqްOQWǗ}E²] s2 6)(Vɺ+p% :<}$<VeA$VbiӦ y)]?h=D6",yq8vΝ/3pڴ.N !7]E'o]: .\'չ`÷![Ro,!ϒí[:QH^AAڢUVFJuV*kP Jz|*bbb.]^TСpЯS'sl6 !ku0 w5oan|> a~zL;> b66y< kL&CBBׯhs :/SNرcQRRRXv0m4L>uՉb%R79`vhU“±xbp[[vva!Nw[P" =_[/X*}<8N<<@@,Vf<-Ϳw0hժ3fsIIIƍ;BOO V'JI:epж[v:9v X0HXz׃-2vgQIXAAApppWyf⯌kvu5z;j߾L3+&qЉ.c Thzyl޼ +w:A@W߮^Pf0pu:p:0xM )8 HIxzV"9l=m QqAV*m$K$: 'N(#9YEPXX^-/,,޽{qa8p.HP[8w#UkӦ AWwE'~w8 2쳐0=}Z  Hۖ[oYwg] ,>"µ= o{hu*P[nܸÇ㧟~B~~͍1L $31o?~HY=r!,o¿Ab^"n62eŋ1{6 [!P ]JRtլCUU%* =AHfq*;w)sqq@HMe7 >?^f6r0H®'mR~ܔkOap`ݠu8p ;~Uzp."V頫 a *Aӧ[R?ɓXMփ@h< df620HX~KE6%x`}@=zUt*C 84,PI.1ZC qO5ׯgsO,@zf&.\t͚5cNw.cȝ!{7J<^nysNd-7ozs^=kׯ_V꠫IXS W<<<,6ٳlhsg~߾ؚ DÇ#&&<Nvs;d`~ 2GTRdFypm'ݪĨks=zle[xaܸqNNNhܸ1LAW%jBUTb`6ѿ?̘?OyU[ rl ҊLleaW`>|H$-I24!( [S]_]\a} B(Ҹx]vҍiU~DblxjK"С…H] !0xxx{ʋa'o|,I&dE 1E²M-mM$4 L<<Y,|'X~D"A.]X,ZL.&xi*ğ+uЕl9JJ! oDz8 <~| 0ztBQFA|;b}@{ &11H~_EI&gUNGs ?~ @w} BcCJB_;n-DBm38TXwkW 1-xt*틨j?߽(99⯷'>ÜƳ݂1HX3{3Pczѷocޙyb׈]pG}2r!K- SHmYEӦMk׮[қ`$GV((4jʔL X#\\qAP1ԈB$T!pkwaW& B1@aYehնTsҹsg4l^K IDAT.]£GLfgvq گJ%]5V+ )vZmllЩS'"66 iţG@n ?Ν;V_ w˘vaL Q#rN i{~yKfĢO@|*S SU+c(P `&N7 66ܹ3l^V+ )vZE .g;ƛo`o`{V_Gǎ[XUbFCmQm3VDB|[>,ixG&hOğ5pwaUxhǎ&5L0% ̻z kT"aYW9 Ǫdr0[Pߥ~痝@tqqqvQ?ׄ9h EP!<[fh_4sqЙw?U&)7E#@̺9<> oH\RoeZTZa{!Oyax5^✘J,,I,A<õgE+ >Ν;B*"*\\\k!%%ŸhvWٳ@Vk&r{@ Q*D [s!5Y_hSe=6\83r"GG>BlF,5D{nM88.x|S?Fjj*ڴigggCgqX~Q$ei-+R9 rJ [e6Y Μ9L 8V`a|;ށZX}yV6X#Jxh*D(K %J컳 j55ԩS @ff&Ξ=kp;:1 ohU:EBծ-mah7S6 8jگ.h.pǼ3^Ҥ oy@$œOj@ $a_Bd#QPulN9tZ\x-EBtnAűw|}H`ڴjS誢͋hiJRbߣ6Y  xc5MM{C ~;x䭷ނ:T͜!PSÙUz>UˎU:E’%:U4h3@@;@~2JСC())#P"mŰm'bJ{;߁La9U 737?02g鿛S"o#$sKDesÇβ-F\-:Ell,P~Y*/ Vˊ%^ӭ[7tD.ݪ]XȦӝ8qփnbځkF7pEL8< 1:hK$,\?},[;"䣓o u9Q}/mԵiQQQ W&X.+ė_xCqgπ>}~؍(KSof" m82jw; -^ߞkغ3u ]X]w{G _tUIPPO4sH3 G>M^`HXDMuoٳ' ,,L#"Hׯ|ڵ `̘1u䅓cO6V^Zku5"1HXpiO~^0_ NvN84<t+jNƌa{n/˳0;.lluG\WteEBC*7o___\rED9(HKc ]mvشi`՞ԣ)> {{|v3{@, seU0<|0>>1l84yˎd„ ~ _ȋ3H]dž7333qU]S0%Vˊt< ":u wacζl͛{'VEXXѽ{wk՞oW 0X\xl$F’hQ~#e3È{l;зa_nN^{5t 8w^:Y k:u D`[3Vˊ*M8qcc7`56.]> 6eÆ O>s !m ^ R~}47 o#h͂[{(dJ~ | 64'+)k} ԩCR(BAiSU X!Q,{(y">IJI|>?~yy$G|* rww'[[[*((yMPK*W*P)"_@W3wJK٭R)، #i&0 ɓ'C(x!Ű}ctHOF`dK_XXHXp#)(@V)`qMs" 1yr6}6Oĵkא=z7bZ%2\JO5ׯgsO,Q7oǔ)S4Ɛbo>}؜?YiM%ei OFѭ" ds<ña]5)Sc(--j3ȏȇC }ה XV% bW Y6u.:ܙ-W:< 2~~~]ch1L#ݷa_J{#(͠0$E Be A{c2)Aݠ7vߩq$mdNt:tH㱉 v_' 砭 H^AvݲeKv YY~&h#0`뀣"q0fEmZjK Rf}qCql1nϻ^zJt6*sXu( AJE-JIhCpP'-D"`.`ZΠ۷o#22M4A_-V1gocCaH<~^zqe *vVCmw#\Fb@8)+ol4~qƈ۷k<ąWyUTXV]JSAut\Fk_FW֯_6mZĸ) mݿ1$&׶^HK2 %eIOڡp5E4>iӦ{Y;!'A޵W|Ϟ=J{"V頋$6.@׮蟞;;ɐYƯTprrĉb{F{CR^zsfl,U$E?z@Hlg$L6}'۶mCjj-A7I333qIxzz_~zeXvuu4Q R%%6IV)SP(o`/_1cܴL3f÷_oqÓ'GDD`"aԓ(LL8W=Hߕn{k3'kƌ3 ɰbŊ*KYi!p}ٻw/J%{=^ê!+ܨBG2I 1ݟr_ڵc7xyED˗ uY{h@JJ BrrrL~RASM% i&r^4胣ԑ Z@#WKb"]#$hvN233ёB!V8^WLS]8-2:u"m4ۨbgcǀԹ=ر#4i˗/#>>^_kdŊd>}:˱4h:Pw-~ EoBYdvN<<<0}JW&ǁ2hּ,qqqF`` x dzVA+ 38J!@^0w.xW ܹSoӧشi1g00tzݰJA4ߤvԄB|-8^v E=u9s6m³gH{5G5}%7TX...Agf}8;~(6;ф yƌ:a}W³N>}:Rz-K!a^mm.T+ Ya z„ tE 'Fe˗||xsVDxI.]hqP($GGGbϖB4BvBAע'mEp2$Z^ Wʖdkt]q\1EEbz2 Vedd#Sjj* EbἇX,&ԵkW)\ dg4F"6@``vS-_[=09 :uys fܼ!s͋D.31p@I0<ߘCmQmwhV[gC8s fsO?R"X6DEh`3U+ Y z1$nu[ ƎeWͶD6iQP.S 3߿OvvvHۜ쿳jMHQOmI5Yۄ 6_籞n}Jb)-J G#–SnxƾvWShX$). عe{Nh!<`|VYlN6Waԩ(--ŢEx"#;- F\vma SLn)EaC?#>'!!l1R1?<_(r=6Oz۩Ϝ8K1^0r[SgkDz +\Aoڟ^C\￉ٕs~DzwKJJˋx<ݻwOqʲm6@[R3]a=wrޙ jWӦ'QzCkB({gUBea ŎeG$^xΉPAW\38C mnw#ooo*)1^xuX *[obʋ̫R9sX }5B}G@'N{Lrww'tEdztsބPBAG9mAxm$GY;cbunfC0JnuӍy>eee= \n%aswCL YŃO:f77c v߂rss#@@W\yahLb0,q\Yl%ބPݷv/(p10ּHr_ݷvPP֘dhfCgcҵ#)JNh;'q$.7Lɓ 3FhF:/6)-yv6@D B5k֌$^3W^MLJrВ)A-ZM2=P(+Q"RGZdY2 CxHb))w~R% ʜ!fƗH$ԴiS@6m2:9h}z2+!ZH `IDFa1 C>3 #@@B^jPۊͯkӂ?/G.s٧fM:2,MuI$I 1ݛx4En fs/^իWI(@ silYf 6X^W8m;ݛ\'1uDn ;JX)%p+;8lت߰=H(6ϼ0 CD1 3P[wpJms6.z_T kZ9)Z@M՝KWQ Ν#Vi&S9h0(iiDsnؐ(&d6ڵPڵ)22󣢢N:f͚e g7T:j-gNribJ9'g'?Զ.CY3ء)tk O,QRD '1oTUs̙3 խ[._\ݻuאp ~)RZZZcV>FIclmі2fM:"ry o߾*ݽ{7 B@ӦM3ZmqMT.7S͝ 4g?%&ii^$g??4^[Vtҙ'IRC|<0 BN {ޣC͉XAOV?Q;_S5g\NӦM#dooO{ܽ{k!MamB9̾8qb]RRK.ŋovTD|>ҥDJ5/'4j(:pI$H$}vu>Ok׮5jСCF\І+h_!O嵨h扙5f+t JMܒ\u6Ł($sƳ$N֘4LG/u Տ[pe䧘y4-zDbbzPDʋ#iJ:x sTtbߍ:Zd֬Y~&tB۷o'DB _ĺu0 oۄrdNbbbƍØ1cB9,:'00?dߥglǴ7aP +ɇ'qY/n8|ky7[UCd#BѦnm4jVcbn㋧"em #nG77,߱/:_Vtx9s&4i> QQQ„  TsN :T*#ژˀ>˗/GݺuտdxwpDEE̙3XhxVPy@WWWn5E%pRnN#??l ƚ٢0osNtsaXd VZ 77K9*`L>gΜADDDgzjܹsX~zu*_"//زe D Hk;w@ uhiH$4i\\\.0 >c@TbӦMftT5'III|c֬Y.EEEؼy3mQH$֯_?X4=hؿ?V^1v ;±3f`ǎ<<|x sԩRSSQXXhL 1Qm,]BK.9"&oк}k={\bpLSNvQm,]hgeGr0fiК$!.^hpL1Qm,]_yy8"^4finnnk ҥK dWFEKD~~~Sk51C҉YBwDa!ꢍk"t/?dȆD& Z_ܾJ.]`gg/2> Qm,Yx"な*<kWkcYIBL={"//FXz6D]dMRRR'6rT1K=I,=S.X&Ɵ&a}{ Qm,YAꁒ8r}'{#G4ۓ؃`鉟uƒ5t||n0S=I?u!ꢍ%k Lw0S=IpwwǕ+WPUUe%'~BEKդ 111pUlH$6hKM Qm,UK.A | 箘Aߙ$uIII&mMsa!ꢍ%jRPP7o[ NhXKctWҠu% q˗/7g8&&~6:zxd#<<^y̙3}Qs8m!ꢍ%jNf1Aشilقr ruwWu5&ko>;C q<27UJ^R?wCEK\9Q 5i0(y:t5e%eaS~ݻ6mϟI rȽ|l޽&)u>e241tla~/qݹsn:^&HH؁?vvvXfpΦ g?yd 8HJJB;lF t ݥ] ]uhQ1\_uVz&ۃ=z4lڴ9^ x5YBKLQm,MSNzvYÜӋ1#`b cW+&kuڪ5 U9g+31H+NsRaKKQm,EEa~(UJL;iiwfi, rǭƣ,XO}uR4ޛ,d8??|;[#GwwҠ,7`ߧ'', ^*O*3g#D%%~6IrC48cĖ [Эu7cW/Ҡk+7x UBnn.78#bI ꢍ%h3iHCPx0)ޘAVnV\!>CPZ=NmIЖi(.뚐D axĽv}/` ͽI,(8{ LfYt]I8p D9>!2:z⧱hs/k*pzhSYt]IѬ(a;nnX?_ِ{=XD]W5a(+A.]T9b}$&RSx} Jѿ"66 -ċ^DZq4Jq{9D]4)*S~7`n(--ŀ ՉIG>bO? x}@͙3g Ha m?ǜ{Vǽi .+Ĝ?lY|e@+yx0qO?a„ o Ro k#C;z7/oF^M4QmM> wS~ӥK`VVVM'R.婛19{C0ID]1wMNu4QQ9ApR0]wAT!cP) QgΑhkoN?=a$4$ H0l0(J M >>yi'><>BmVaBEsKK{}8-zl)O[JÞ|DҠ뻒v @0^8<0ZڵĊxfcc40}"ꢍ9iz|ZlqR;C C%Zdͷ[}7wҠ$=Ǵ?`#ƒ /f_b414.ژ&$p<}0.c[z?#R'mx} ggo1Knhz gggk}; w:BBgsc@E$6z@}1]#~[uQT=5 ss'pvv߄0Knhd2 zM9ƮC~jbnBE /z>0a V.}…@6J69gϞEyy9z!ANҠ$Pa -Ēw덺osanBEk | @N.={70 wX+%X0ziRAn^Ԡ$neҋ1rH5́9%~QmIv6 K. < òGeBr> A[;И$!leccPTzՉH$8n#rr1j( F+Va.4&]ѣR> L L H$-Ũq=:6Br*?R=~qJ'O֬ A7&Ivvv4hpʕzN&ai$.g^ƸPTQԨ &~6դؽ8fZBB7իEEs.g^ƨΣ}vȤQU Nh9p<::yyy4hlmm ޚ4$ 54fll05C| "%Oz eUeTDŽuFTT L1mlo_] #5ذ6R벪2L5)3VMս{`$!P i9GG=omD9&dRu;1QD]ы& xQSO>7}ڰ32͛#+ E зM_=o88j]EQE ̃]';OrqN} "ʍNaa!FBѨ623sCOk"+GDĬP*`WHw򝶶ĉdIITT]O` =YYS)6ܪq\P͍,**j[#rzIBhѢF"| ꊀ1 _f$D]i&$p4x1о=0|8i lۦ)?@= 3f`~tmѽʐ[&ݭfvΞ= 6 NNN_fYtcƌ8|phۢ-p\;aO(U&TdnD]&$pz[.k֨Ǒ}T=].- 8x9h@^HR`fLރNphۢmI:P^m}{^KA7%IǠs;y./F7i1Qmj$>X [%|ܺ?̛.@*%fퟅ_/-;hܮTfV"}K:d2x:/Iσu>#\|O7%I~~~h۶-ÑWWFxd#yI]c[a%m~i"JKQ_2nUTU_ vv󵃭-:ZmvZQ͉uQSC7vn~lS|OJ oK߻.Uhz;Xq.77B^aݮ];lٲcǎq+ 5H$3?1eʔ&ѵ#^£K;'novB΁ MdN2ȜdH%TP%(=|d.C]2-#$21lќ|ڔO>ѭjS㓇Bc]uEЬ thᮯS+!+ ڽ J˜1c̺Q&mеqk6 r za4͠tLU6HŮ˻p% ;+a dՙt\Ά$-vT9Y *<Pn Ch{62l*`[rf1L)FoY- pB~wDI'@j/Idfʺ0児l `ee[['u{WnЮ]XYwQb[.[.zNPwz?鸨؋V:[;Tx);: 1Mf0n̘15? ]L%z! !EJ_[1$b!gSMkc>8@=r9y)AkCYw0w7N?A@V1տuFhM_ qlcsM|w> 0|3AS S?Z{\ne lPEhKVbKV駟6FB<>Fm+Xx1:'xk׮  ӷ6o0Exy~l*KF SzsV{}CqLȇ籛p)gkt= .z6N P}=Nu7@q6xTjsoxٹ-ll@*Je } YYW})))gm?2el\*1otڅ1êP膫}tXJO*X%O<1\IhsIBΠ6H~V{%5":t^;ϟ[-@3AҎ?@ IDAT𫯾K{QޛzCWפ/3jXS9O?[ޢzٳgv)UΛoL3Bl_҄&RӧF4K.e`` N]ȑ#|7ؽ{wVVV>}:O>ݤlTT=G:9U/ qv&_xhu#Ч[n%.X@omBTps e n'L_xnHlJJt2&*{2=B0+_a2ޢzƅnjr *+۵kGlا˗%K.]MY"!~ܸhظ! D΄?8<*_.\"ghPVTz ۶mkl:(q7oozkW_IBLKK#vA/PT\z|),˻k/,Is&GjI†R1eS C=C?Ȯ c_~%KKXԅ>u)..ҥKikkKl߾=rkg~~զ _M&'6dݴYnC?jӗ(kj*FKcЋ-;5k8sL^|m[|-cFJ?R/᪓R%$bPYazI@}QWη}VSh=g>=cڸq'NHH$|XQ{$'W4޽?'PTW?(DMg65 %STYb G?}<+Ia͚5zKԞ\;g-99LjtTuq52D=L`k%Q9/9s~OCc:;;W݌ rrذܵ+t)mɦkR#&RxsC-u^o׮]ۤ{b $g׭[v'99Yx\50AK(Gl0iwR3$T*ttt$0@|Ϗ<_=>ܕZкܸqC%sӦM?GyyȑTZm>>ogϪ@S4)(/Ձ_y0Vӧe)L#UUծR% oݺUuŢ o9{l/zk"j`aaazo[*;D611g4EEE4iP&?fe.4YYV'5Y0Bg}&$;'MXTD 9aim]mʞEɓsfBb^"{mE=hдڨ*)SCL:u8lذ&We.\ѣ9~x3Iaݺu7xCm߉JbX!go338B͓jݻ7sw]TP_Ÿq!y,ִasrivԉاeK&V+9w.yzi&It_N#ձ.J9~::o˽Ģ ^bii)SRR8ydkSRR(HM{4*޼F9<0RQ/fxllP 5sr?2=#E:I_&v|8044 e7GKګ6DeV!ҚRpʹҸۨsgl4. y89oVSc3p1@kkknٲ014jRƒ jUgj܎J!g~{'Nyp'c/mƸ8޼y|7x̙&m6l i?yMtA%z0$aUUx w}6KbJ EIU*W]T*2,|5mjS&Ǐ'w D;a\z&>qؖa?ҝ[@?xE7nܨ8nb zʕܹs'|MܰaCqP"S*m۶z"nN>v~#A^Ac&Nd3 8zd7 t;SL+ێm۶MXвvZclu;>XıfyoWۻoBYFEEŅj$W9>,/\{_L}2A ;$a6oL>}Ԇ8L֠뢹D Q1p]ʫJemNn#we=6{eo\r0Nԙ-MF"#"7P'4leEKnۦNAn`.: _Mj\CHHE|UT{eWwƹ+s*`'N :݈ $ԠRثWzm>t+.4m990S1=ST*.Y#G;B^H~zƔ%GWO." KO]byjۮ/QQQBYf5jbR~':A ɜUN(++<7\C)cxiaesSč7gϞ]59r99 f(3G ]YxJ*EoVe Fn_@7ߨ48Au4 4qyz ~S,Oiٴc-XXMA4h=ܙօ  s~$vK4nYZIx% Gl!EBͿ /V64طo_fff$sKs?o گiߢ3L| R96.QNdSػ!h$hп$_0_8fէmMVryr:~H_#r谡BP,,$o'xB=BcmےNĔK|Ft6UH!dzӅ|G ݺw W!LO6Ѡ1K:8-ђhaF}?.\'矯uZdJ$'L>s0.h/[O)dQ-{@GBLY3Jݛz8%FlV,@Xd"pɌLyJ⧟~J_U{5E\u9]y}&K(H"#%bu^ n$""W^y^VBn pwj0rFҀ;-Ex3C ƽפU*/·?h=_egׯuVVVܵkWci?1VmI_6}oRɡC UhzIBeR(O0//hXjn#Gɉ;ܽsg 0\1yF0\r|E/W)+L2I]aK7hZ5.9ޫ-}+]9[nT*D"?p\ɸuLMJw;6lwW6c6DH&HR/ yʕ+M3)~i朜L^MXsU_矓 RV1 &cv?2?D=Vmd j2޾&(CB&rO%!2LL/c*er; VچhRXȁ.5MJJe2YѠ@sXV! 1j*`~L_UUU\`P.־(#ܰ6)wJ.]JF׾=1/?fӱ^f'y?٠ e7 ;.P1,?OP`c&%5Ç 5.]ڤaJ̽0ІJO@v2/ $O>x!qD*9R)' u+kב?;wGHHZha$::|B7{ė7oBV\ xi) 4{))!!GrariIDATv۶/xA/^[wGKgll,w#6;Wre\ȸsiWW:gMBil)e R9N‹/zm_@fϞ/A7W]E=:}ީk+++1fr5 u!HǬɓzll_ƏWq}Tp2$"R"q+2.\Qu]k Zv[xSx8z vpu#:{$QBIe + Wdd"8)E)H.LFb~"rSՆx!ҷ^UQ@O鸵ʯ%jCϴm'wƜ9sPZZcՂU:fݙH<w@G[)'1h NAƍ?~c?Yц+ȉ.+\bq 5V{[gS?4/fr\*2 g"4{S)U7|z`$aE )08q0l6Fz 'N@}v :iAvv ._X@7l߶ =ޒaL(,B<EPxP~B ظeJJTP** j iJ‚ p⣏>ŋ:iӦ!==ÇѺuko07R9eee:u*P"pѢE /s:b٧ ["ښ/6f9RV?x댙 .0$O;%n,7m00FtQykL%TU՜JX@OOO~M.˷~[X:w\lC1ivfiІ" fEzERT矅Dm۶g}Ƭ:vNI!׮%&*Օ@T9s01QD JEEɥO8eJ$`-oŋ ZUV wnݺI57AC$ֵ&os'iii:uIn:?9TlHL']\a(8uT꼏)-1%D]ѥI||<͛G3ٳgs׮]pGB\: RseJJY ZJĊ ;3.I%$k#>> .=;Y8Æ ƍk(."b(RSSl2>J:?jՊs5:޽VU{>)AB&Dg yYJ!̠ƑQ4p%FEsyHdp⌅@F-miӖscZGZhIk/nolޮ2׭SӃ^aC=ꤔcrwWuV+#"'N_>222`UisZ&زe lقf7n܀n~DDD`ɘnkYYc09"b&jP@e ' ?eO>3b`}&\DD Jlu[CX#9B_8rfEy*`!˽s15(YIns[om-PP z>ydgl7wii)%A=TM›߄م6߇zQ @?;?~X_g6113Qz(ݎmW p-p~ 9Y?K}E76~䘋AI?XpA.#*ذkر>] 13QgЃj޾ ||q$T !Əs15(y}&IIνÇX  BC1v(w\DD JAK=P}7_VtѣQF9#?()6~䘋*t:{oemj~}#&J}joF#gP{$~OÍ9"b&j0mNNNzm55-zavM3G/˗ ]-_96XoPc."fS貲2[f qEܺu[V\/Vpck듇0 13QfG^k7nԺ?>۽[;~iS4MyZMC>Ծjs}I/&LXn:4׬ΫƿolLQ2\L!3qD444HNBoy`"b&jPIZ %"ߎY䘋A}7MƏs15(Y{QwuCPXiV09"b&jP@v '಻0 m2&\DD J6 9t=Sb."f% `?Gxbc."f% `7? HZKP`6#\DD J6 5MOnl13QzMB%lǘߍADF0xl13QzMºO{B'<+]aG,ij uG jdh6~䘋A=& Yى9/2?rELԠdH952Ξ6~|a."f% KC}A=,įӬƏs15(Y$l.nFW}b dln9"b&jP@ߩI8ҮƏs15(YIzac8+#\DD J_k6iqKe 6~䘋6mbAkk+8K~Izc-ol\DD <Ǟ={XTTT9IvE#c]돩 ?rEL`tYYrrrYSNozddd9Ipv&a9׹(\DD A}>1e|G;w.Ξ=kZ[[qQĉ~3u)tLcE{M3.^B0iL5z"عs'<K/5.  1f&B w\[`."f"n::tix!3aܹqYt. qKFdq񅹈d&aq>Əs15(Y7 ==h<Ո ,U䘋A'ao ȑwF7v嘋A'aI#yy0_AݻIi>o,@S{VabG,нtVv"jfBC c."f% t&!Əs15(Y{7 ܃9"b&jP@w7 QG<+#\DD J&a<{9"b&jP@w7 ןWotcG,mmmjꂽĎPDM2zJƏs15(Ym6N5As7GY)#\DD JF^^'Əs15(Yccbt A=/?rELԠdvV9v(vD>6~䘋AR#\DD J萛!@Əs15@kk`{̆!ʼK}133CcM[ϝ; 1 ,\ސZ/\DDlƖ!''Xvv6JKK}v|׸f4z \DD M.jDz+((ٳg1fbϞ=Xp)S@ߴX#ngELzvs]]._lz@xb:ui t^xΝCII ۱c\ݎ]vyϮGW^y---hmm=6m4̘1Vyyy?N'֯_(୷x<lذpػw3_cɒ%3gz!ԿuV\|}wl6 ìY`E~~3Fyy9v;SO(\.4C:v-[|477{-))I{nL, l6RRR }o bx?YpڵXz5[CC7r={6ǏGqqqϟkꫯ0o?#ocu!KOKT[snA(3XI 4!`PdSܾm'"qB"*T&1Wcl+1 EJ$? "M#t:P@t c=U0(wsiIP_NTlC{KƐC`;*:_@aa!^|E >Ŀo]6Tj*XU0(wsܷH RNAZ8 u@hXXT"VsP}Ӻ=.زe \]]|/䄆ׯ˶FcV7mo_ƒ Ah;Xfer dpTӞZ~~~toߎ7v5aaa=]r7nnmbXzXbAkI=~ܑ ,N)z@3B899A"{?_"Ȥxb!D.|۴n׮]W\Ґt Gns.unW+r)ǹϩ=6!!5kP[[ބ`POU@,㭷±cbȐ!񁝝v L|<ضm[OUG9%j|E9O/H}.Cq 0Ӝ۴GTmJws!'Ip$JJ"@{AΧw(uW8+92<{xC1ԡdK -^F . A»ٗiH[-qV_\ܚnx;@WS}_ !0U  xm0DEy?OѴ$ϴj$4mn_Fef잁̪L;֨oǞ[{p:48lЙ3|ߩFZ+Es)466L9vb.59 QYYU0(Ln]/[F#*S8:(>>cxXʦJ3 __+jr?EkI+< 7Ե|c}/ fm_MsM8%.Iuɨ'ƈ7PTEY(]w~)CZG{&q#wFSF*THt$6ONxvȨ4WS1+ u2늴F|!C 0g 5V5I惄>W8~1gF2,,ѝ4חFYw~IﺒQ$x =kXvv^Ć [LR ik XYad{F|rQP\mт 't{i׆&)|д5,m{cCD|r8Z9bS&dTf]N`n2<{@`&@ٮ2%?$6o~8``xw̻ʥX~z9'e}G) u`?!֖p Vtu4b Mmڀ70cͭ9#@-7$&]wEr!߇Șx>&)|дѶ}+ά@a]!|SpZ[ [goл<JВٮ=TC0w1GJH*$ALR iMʒo`MA`ZbW.4Uֽw2 yOQ%Z lOYh Mց&BȈ N tvKqc^e}W}ZK[;Vc*nh>Hhڰm8{nxu+^@>^;i HhڰiTp ј1jEʽwJ @`!Gƭw9;{oNI 4$4m4b: օsjP!mB{ *^E^. ҐXyYϴ>KP_pP@ X \:^481s1Rksk̋a~ʸk !o_Jw ND9&)н2H,] @x8pEˁ'?a=(W̋ؗOž<&9VzV:s*TyMR{]wϞ df>l٢Uqr@$&`Xax(!#֊2w<} WB|u+D[._nspx ٲ$ ؽptO=˪{1}wF#31™3ZO/]\2;뗧.I0m4\->q}u#G~m>f홥sf&,=,}F2)LT{EP*~hj>Uf B\EߋD9<HԪ@#q]F._ֻMpF~Cs'[g?(OS$W nƌ-SkձA {-L'BZ:r)̄fƮR7Elߒ{r>j||c Y`o1@ `<c9w&)=$ˁ?3 x1ulLspꊰ8[;!/P2glp!Zp/]}|=*U+NV^u~**0f!z k;z\bA¿nߦY&;_?4vRhuA*/wz@)S Kp& NIHVU^] ; ;|:SIV "hPSSˑ={­[ Dag1=$$X{r%K={kiVcb1lm{d3й} B >YWMÞ[{p<8fduw%'KPu ց !Ki#ܺu ׮]k^.c077L&æMcAt:(Gu+c_VL @.9ƙDijT$'៬}/iܿG0oӕ*1UVWW=cii gg?''.fB|4# mn[QPKLH@>azTe<*8wBBBl2|8wƏ߾ǂ۶^X,m!k.ۣoSq~ybfFz,]RQӂa58u@!CeerT8A@Mj*jϝCutt7a/n}T t2urriG32`=0'D :!3ojihLW#6QXXoo. t_F5Ğd,dJ=JR8i|w!B!Iۗ464tO$- y%*  sޔ2+@V~cƐF_^^e%%ҒBȫ<9`<//BNN! ,^䡇"'O&C%#V͍DEEaÆٳgE|WdժU?'{>M@ٴ LRuH({[*XZv/}r򒓓IW+@>uUV/]f'NF BHo'"췲"_.3gM@766ŋ???/7#G\N^{,Zq ,|J@?!62`/8x<=:c)O?ZwwB֯'d83 ˹?_Feϯ=IBBBB#D*U^ .]Yr9!iiiٳd߾}dXN̼F#@$17$Z# $Æ #ӧO''K,!+W$=ٳgH||<%DΦ&McfF2|8vnE&'עXĒʣBiG<<=!˼\p`Ȩͣt!,ؿ`gГOҊ\??b(z-3g$zSC5B**ۗͥKj$ҒggBt"_~IO61O|cP\L5v~@HH?sy#XϺo\x2$D&S\.'uuu$##?'~!Yh={6>|8#Z9 dܸqdΜ9d…dٲedɒ%ddܹsۤrpp^"t~>xNO۲_H,bIx"իh6}rB^x~k\rt k]=I{V,k!D"ZA//zwF"!d By].i[Ws[GwzϫZfL weoj?]|~ڐՅ b ̆T4Vt(FO|2Hȑ"@\lذ|ddΜ9dԨQ$ ڲ\@F4i?>?-9r-u#rZ. Ņ:0ʸir9!C}'0KR9v"T"k-jԨ;wqtVuzrCׅ)+Ҫ>h •BMvo/D+vxkff(22!1cWVaer lb|gZvv_M7?`9+?gϒ4 %[n%| yWȣ>JƌC=kKŅDDD'z,]^lݺ=zD"RTTͺmm%ۻsϷR/X@}E!γ!V~kײ7o;Q"$ܟݔ)|h?fbeTU]1rH 7Ko߱BR+/#q>PޖJK !?디nϣMǍ\---$5=B0! 5kofns!=tۗtF>t111k@V 8# 졟ӱ72 DFF23372dZ# Ss# tp$foI|%'# HGwwf$&bE̝_6|mǠ|+>{6E&O:45u+e23W ɓ(X*p%nƤI P Ԡ؝sNᰇt18ky{0J IDAT&)ڌڻ~>x?֏;oՍGv6HBT L}}nsã"3=kJKig҅ Ǩ@<@|1c .@@9!FnT< S"RG05X5&Ə}@@3S1 ͻEUu:_||荛e7QR{l,tsE /BB7y2wT9L,C_}J 5O7 /m_Z銻;Zr۹wl,.nݢ3!j3QH/$tM?57N>z6|+;;k77 < JKOnSVBP\\E֮a@` 8шBhh(aoOz#L6x] FWoiC)v G+G,Y@ɔ@[-'+gc1v2]|}4䞁T.Ŕ) ]iohVrn'觉Zπ 4 aCuKGl6ϟ$agq@_̝ ???>|/_ƕ+W P]]077v!; mݽ^^4)ii6F*k_8 "ȑt֤$``hYifn0}"MzQ;8ku",7I2+Ƽ˾}&Q)Pp0_$ - [pbW>~~m\ _ &or B! L&-__\pqe+++thxxxh=U;TǂTƉCTa/bo KF,s é cPpAgJ٩hCS՚8 3T $$ZA/A&O =y@+Bg=`ֵb(<z󁫅W#Gj_g 0}rRǗr9N={ &7 ᥶=ZNC<+o_j :t˗/<''' Tddd>,6l؀444 >>۶mo)SSkqtw2V97vG>_A~~~Ndo(CD@c#ru ;=W @*fti!HK ږ..?y2 JQufebXd$=MH!'O׋nYpqA\qZmk%&R_р}X)^L҂f$|~]Se.{C"8z(;.0qDèʂ[@U#$Ll-CRUv^9WLHBG.00gu 0cH9e71x` vF:E?٦)2|8ȳgi· .Z ^ [g}}{u[KĘ0I% 1{gDQ>:@&LԂ$˩@[Yiy ̳]9VI^% O?G+&LիW#11x? 115558}4V͜-="Hi[74P#N#2|ah]ui>gGGYXHs|u@]B!um{ΐ}KKF >--(XS~ut`y@k>Xw7FxЭ,JifF$ZS0=Op++- OOGHk2n"*X"pi;/^z%߿R3fڵkll߾/2 sf6\\MT\iO[ ׯkW:(޾B ;BܴPgh` jGɵʧk>4c!HG?U:Fh/+{y6Mrx kk* 6c\F0ڇ2>A\p0x'1I gt/A\G"$&&bΝؽ{7JKK۷c>}:Əvv)!`&}ҍnYFQgr %tu(Ǝ^i>;nݢ bO>{$a03l__:ZWĽ,|1Ȅb҈i߈T#T iA? Bs\*RVA~>fgDZSP/n=xs}sAAvڅ;wPSGŴiy`W׷cƺdtṴ7G4絽}ӭBaCISG+GDGF #*..:++CD4yR}:MO> cw)z ǎȄ޴j ?ǀH8Cw ^ظ` fvK͛t0ڸ+w  k b ! D,46^ APihi8C#-H 0IV$oAA:w @ADEEXv;Yfƻヒ[nA$᭷ނ.]e)Cr*ж9 5JZ[*cݵuʥxy˰T>`FX4h[3Wypicp) 2@zZrYJ 0WL ZR}ryۃA] ro4Lo7۷1j(8p/ 4ih:Aͺȸ9 [1n#,,ڰTC-**hlx`X ꨯSiIآ8`j  Z7>9ggeT;݁U+XF야&2t!]mQ QL'3&)ЪMImۆǣ=?|n# GL w3SW^WB I*?duL¥{A NO zv FVuN-^KKpF%r;ylxTuut~PM a 7n .йϪLDB |Bc*HFׯ_^xR}mÇuy5|S )i"DJ +irjr0-h롼̘sCj!7:90{f :v`᷅hNx7xRT6H(*A*b GDXȁ(PPW`hUABR%лvk+++=zK, .:ǎ6ATH //SMK 'ErAɩR|v3>f}|f!,@je޸MW@kw)qFj*Դrq. 8nnԷTUg 2 f8ҕ4Ğfp$!*i`LR r*ׇ&Zь@k9̚W2 o=n+}@H9dU샄R߰4`< `OJy ss\5붴4<䓐dضmf1X'`~# _yu5tݟa2`-+z;:VPbUk*d hA›e A aa:sXjW_`,H구χX,ʕ+3tlLN22軿I79Dq`n0n}De$q~Z2L:@##{N8Z9bR\4/.#iodB ZO]gD ZZ ;nCْº Ah;; S( ?X3f /_uo,%3sr ̛>V"2 @B-gHNAPCeBpo00nx8; gbu5uh_,QZ 3~hpv6 M`$LHT.2`) > ;*-~`gn_J՗z;=*bO?4^~e{"22vn) *ϝ;իW g b!=aAMLgq.@A؝M)@8TXNp6ZБtF(5j.0¸8}5t˵(Zê@̓Wޠ\2j-E{t$QY+*0n}'Gz߾}3g~GTWW?Ѐ~u;NYP1^*⥗^!ׯGByyB Vk11-hQBu45[P 4U)Film{*$ {"9"mcCŀQ:u9N$!,NɚVT"GKӃMx{ӀjsTU6A›崐h\ 6He=*Ѕߗ.]۱qn. XL-_ߎ)#w܉4<] mSGԎRfgAobbb:r^ts0Ε@EE1A,rdXXC<Tb @\1]O2St4jx葑͂Md1@{7>>>kˉkkP'''H$]a޽8p$'"20^+W>C'jj* tO-GE 8~\~\}WQQ B뗘sy OO1_Q]8,drpw./C\^qHDmAC\?X 뗜tTXZy- @~E>ޞwHM xlX)@C|U~+;6"Zݸ @p6ʓ ( -~t m.QAZ;@Bs5`͚55{BI$=Dcc#y+B-[F6nH9BΞ=K-ZD^|E駟v;nΜ9]u+!!Ga̜9S  "D&XϥKiwkBHII!$!u.'-1a7Z e'BkZW_,YB2}:7RǞ=rKvTQA7EEqwg|`Ȧcѣ^PZXMZﴒ^I,bIپ2αy3! C)))jW >۶DڔiӴ+ۿ7F,XA.kkk]v)6~x) ;Qg4O?U^ᇕ9a!nzp /׶/0umǰ_H4~y l0ml]7ܯ^!HWZKZ'rqֶ\wES0-@ ;iL) $C<7nb9`ivABi&`U9T,7:cT;HDo@q7I?)¼c 5j`̖hɋ'K/5Lf& %JPWlm6D(dr{pi 2T ncC54?* 扫p?)gr@+ \HM{3C}=pH{P N{ 1Qu|2pe)Oݏ1 ۿAT`QP@¤TNA 2  @,,j\BY nLiD曙 +f:,8 LXE)H΂:~Kz&'uEu29LR;$ɨѷ/#Brr2 AǎIfd=pw"#>ZK0\mRl?'X3u ̅^1lIN!V:iTSpvvB6k^n -o#ț_Ꮊ+"B HW{hI,3y мmd:QW]h(c T{!"mYZWWkGk)Җ4:L1\][lASmg横BB_Z{A‚_IeYhHlx''B{GF YKHB9#< wWAZC}|`;&;7I t a{Cݻw O=[[Ç4uӧkuNc1z c#ʬ y5yXyv%fzJa(d.\dV酒N蛐+ +BɁ.\Ep@/@g:2Jp[.& rP\ZiA D@CkkI=@w2!PQQ|*اOӦvvZӘC1aa:gr&`Ehhm1W0mj];PRzLcoOD; "~@0)RR IDATd?u}.@@fwv~H"CNg8LR;  :=}; Z7Z=29?3Nd@[8>zB$nrF$#"ZN/ f1fWJYq1 nuڔՄۏ Μ=Ӳ!PUwQOO7$SP@SRCd6.htRK qq쌙2b`>xaiL K F$l}o6!>-4??ј\H鍓!j_PgAs8JJP%)nO)SBzKkHIozk7RBqu@]1:#R v-h9HC"iży`mBLV91%q%%1P:5- W[KWWtqBDDɁL9L_hJ8E .۹LҀdDL.mVPw NF5 40>Lwٝ3l.sY橩IɁtK Fz]hǍ8yOXVV .4W)OPu PPt*kYڌtwWc tprDdȉ-+` 郞@*P(T=<N`"c X!sDa\T`@-Ƃ݈? njN9}=RG7p@h;r?CCz:pT# h@ȾKȫ$ Rk(EQ7vg:b99b]TD-}&Pņfi3655xg;;4ZНu8S1SVV9ݼ`&0CBImf~7fvf+ 6g֌ͶlA;MT:t3e7I 4$}(ߙ ƲbtŽ!*ax|>s-jb[׎3:u2rDG}|S^z]PT>/#{y>}4NcTOw$D@;f-h//N:)(Hr`a i%0qD;_Fa^Xt@srh+[`h3<=cvP b[׎3#RҐB3mc$͍^V.KKCGv\m> qܤ)7WÃ~"NUicA3S01$a)gr@3T ;v9H@Bm:$yf3웻^ڧnSny95jn];`ԠWsւ CuJD~o W b:i"NU%'\h07v}Px}/8rsse]ΝN!@JJ2r >wln~wO>yaQn-lS*\4K)8qZִFRVWGt9H_DiH$jRЄ7Y{@f |'VECݝ;t(0X@! Hbrz %K?aaaDX`nsr\]]QV9gϦ/pJ!n-sin8fjzbicA(K@H]#k! ܞ{&9W"0٘rEɣBz(]Kdrn߂:^Ǝ t39 6`ظq#^u.WWWW tazKjWC:b<;[_z42CYGms-voGo|$8-E lj@24?  Qgaؙ1 JD]?էq=:QE|;b=$]\bj}]&i=cp",\l\Z \Eoacc~_NHO1c~썍 7 rP&UYu 1n8>qeֹ$0H6n*2m.6.wGze:Ba )*OÍ7М G0_,s&ǜ9Zg˂7|>7FRRs /3,X dZU4ɑ9%&SLh-\%E뺱@4Rq4jD"qsM |}  Bw5# k"T3Б0`ashl<&w4)˚HhVSb&^޽{O?>D.11:7[j}|AohVD9 I*bSª=cףW !88TDڍ$LOZo:gr$$$J@2pIQ#xRE+*zrHU[-9ϯ*^zSm *Hr$ܒ@n3!㛕L沯3s}q{/~[0#a[)+ĉCWh -[оm?)GI.rJB&L %8R,p H0$HCAphXAxMO87oFnnȿ@b(-u굟|֝ԝ*Zg6*yÇub޶y>4 |񫀒3@S)p{1[  yGڗm6t w 6%&lff&.A啕 % Y'Hg ȬuK*+$7D; :mB&MFMG Oh2 LZڿ"ed{M&hN1|i׼~ VUUw5W⭂(r~0=D#Z$9Gl _tfV"sL.u\܋P$Y-EךCIfВVuEd2̎/_5kx:\lZ wλGbsN ߗc ڽ}j 'h\.v!KC$ޒ9q3romM0+jj!T~]tn_,h+:GrVF əE3wI۶ _OiAb#4S[Ć{y V5rΩF A/?w$93fQs<p0?Klh4EtF4RnHAHZBpoO3}#i.Z1^yyc8~8#13EK7}:.]"2'GhYkA%hՊ7"!!IIIغu+nGdd$l6^}1^0 |ֽ!Jm(f ըAe{%>Mc"(-]s­U!]HYP y'@t`(DOC&ހ x$.5 'ǜ=%H*7&#~~m8ɱɨ9D K#7g dm9V7rhPH6;T:'10Xj`f~h60; [ ^mvl{aa Zpvc{LCD~~t1i1X<# ҖvoNCIF v7FּjMs!Ww^G\93QP@]W{HBHڎZ ن2?@JЭ#梥SNEkk+)3V^^ZZZƜ{,V4f'cl`ȏ FC3`vϏ9sȖ"غttn1:tЍ :tL ̀!€DC"`H@Btc]T7L+Fςa_:~}}kD=[rXk٘ -U<r 0~C0kFڎVap:xDYUϘ̠P-!;sg &eaBPUf[3d#>9՘oL͝IPUtx^Uq0=;\VjtZRȸ᫦SNE\\}5qW^ "Mĉ;'ӡP.ՕAnT^8w/^qob0DܺP]**|ԅ+LXbOJiglS~477ԩS薔Z=cԛV{/&MxL>999Xj>````zzt[aw@;^(nAA h94Iá* v~qSӆj - fG TQɀT$hom: 11pLСniZq ۔@ zdr ZH#  jjQWG 2#YKDB="A{k[>s%E`R( tYvNV ӓcBy!z-Ĉ}>LЊ#TDB@P T-R!p|<phOM6Fi蠔o:zW{p]vHTS v^^IƆnVB4IС" A=+]t8>R<l:h`m%=f7\FpГ;y)F=D @dRIIȈϠae%IPhH{eK=arƧ!$zgG DBxNrm$FpұLC켮C :bЕLKI |5DF~o(L+Pשu @J"af&cb[e@P'4A7:R0|K a*}(H.%E8Y!r[nŌB1ЂCJ"NG/{o/p2$M  !vnd?8@,h@qնbp?Cu pHUWxqFbz8$h:0AP EBDԆAẃl-joJmBamSz"88,C_b W^ 8Ak CJ"!Ď#'6FinhӤIȚNҰБCJ"!BE(T11`;R IDAT.EBAz =ms̅: Ä?wvRsFL $j@Nb@E!(vfGm ?+Mt(wKQ*hKaZB/(y{IEBk*9->: IfL\2$q0q,@z.K"AzNMt'54PG*Uъ,L8 EB߳ -mk=TKQ3Ș2 R| ~Oi$ E @|B۶[cׄ%ð)x;XQ" (VCTU b*eȁ& :EBX-Dh|_D)! !:.z# %Bnm+k̯Ja6RqA9\D·n& :Eˆrip`9"4vlPQ3Ê3gR MBVRO\sFg@pDp;w 0/6%*:Å+VmQ*eUWh]Ŷǰj*UʐMt(rB:.H ~XH(RTnGrX2jBr"8ut|XZЕ$iA_ ߛ+,\2@"!POhb70?h~hZ"!m>a%$ ZPfL9oE5 HFEm"e\ 30nZZhm.)ʦȚ]hCQ$ M"h?oB- 0\<;8AmstzL'd JM򳔤0FDˣZLjPݡ[64IС(?G0\<drTE-Po4Tfu6sZXXGݙK!ށ^x 򑐐 Sf&  KHf^TD^$AH(G&N#kr2ՍJ f3lˣ8 ed@P}+&%w3?qy%h㼠(UyZPuo%P SR-X_/bTϞIj@ЂL()Mhj]WȉShut׋Vɂu3QU ROhSv]rM!P}r  Cn{`KNF!|.BlՖ3 AhCU$%4Y,7w[%)X'NBZ"aMhwQPEEUDb_zM)DkT gg\D&tLG# 4IС*} MCƼT8F0o "a_EdM&{@ hm/ڜ.kSG(䡇qq68 MlU-hFU:"8.?x'`w-..ƃ>M69/TEB@%4y14DML|9":dvӺP2m~եz:},;-t#'/uȊySAK-#QZDoHlkK* ѻF Uݍm۶ᦛn{{BB:vP eڗQ $Ҩ@ErPּy~":DCwms#s!hY 73hH;j.]O"U9u4Pvo"F\.x 8\yyyhiiq9g޽x088={"d} M>fEED*G нPߑHVKs_b-sW$t 3N`ӫH)l6+'8S% U)F @]v;4BHOOG[P|oo/yܹ>fz~`3ZaHTǪؾpnn.J0ޏ?}ii~逜7qQ|S>u /L_CFs[FwΜ93g`^ e]4?_ބ: 7畕/T,#GT` SV${' I$˪O̸Y%0u_.|wԌNk'z0k,F&**))O߬N1Z4f"! EMhX?c0q"s ho7<:Z)ǏSV$#ѷK@m9w&>EB;sOY {z(mCO!hߴiԙUD'\^5r3q$B$P y M^#88zfd["\KkeEB^baE +=O]`(cL` ogp/*.*3 }[|d\lUf zI噄(6MаlڪQ3f踮Ψ躣 m3 t\L$zqQr͐kh$tMi Z=pZEEŘ9hCy&!@æTzϤ,m6CK h3т sb-Â:ppTSxL˚A#/ROiZud11iDi hC]$“g>-$h%}׌FG+t]WL/9Ky_6*7qR qHOwm}js 0#"FHѧ, Mt"IhlL#= E'&;[tV#8} UzGJ %%?x 78͢[&RKLZbP^!楏Nim(MnĪao9k24IС.ړ_PՈxz{ ]QA/zeVVL ?rN"U$bDZzq!`2EZGKJ a3Һ%&R4ǩSC)udRVFE.,OivkC"!0JRȓ{ \@mP{."¨@!U$={5ŀEŴ㴤;)סCY>U-1* ;J,jP^Ng@"!@Di!ɞ V[(11@~ gΐ1U Q$d`dNmo_Xy5Z=]ڧ["NW&h"!0*rw MCC&Q2&P[(aA%>%h sʿ١vEB8WLsg'ѹ{kTw+1OiZiL k0Ak Z ~hw;.\(Пh4T1/Bjﺧ\ӦhE%(ϢE>]:^,hml۲hagv3>NJL&W\ᲛhA$$ʽh1@^2Y#"$]"#'ׂW7`m_$<A߸p.`ף.?_#%K<Ҿt-]v+%Z,MZ& Z "! ݅&}+S?to>m*Q$=)v.1ӂBgC/Px옶B@U$ M"88C+@Ѝ& 999xOxSLj6= GDW=Ot٣uX1CBqgv>%Ї*:kͽh !==< B SSE.V$etIIH-4 zR~SLjZ@a[WtR vObcڧAoh(( ZCЊHH48 1ǏSǢE"'uJ iEGKrjIFW{N ɷzhH(P XtsQr0F<*E8B#o C/ 0AkZ Qn !pbD Ύ;bQ[K^/\3\f3&K_]} )#u:mQ1"@cͲlttEW!l|>Aś@xh_n.nf!hBJZfVvB@8u1D,H?s5S.0X퓶^mm1"@cd 9?\#T!}:=]r'rPwDh"(+z.a8 1 ~.c2 \u祄۩NWX'" 3P|@'Q?"駴]LyC(?[ iț83%C+osbGO~ & Z+"!@{ IK99fT?;Wʺ oT7GOY32į'SL|q}0kӍ9sO?%-RlZv a,^<&3<ΔK d˿ֱ(s5MDBv<b>>+%N]uuSNOBj|%q*gHKӏED8ֲ\b:#NBgΐg+!AT  qeѻVVFK, t5X>D\تBLJ 1*C%O\#믗QVeICvOڮX!ةS W: >O{pA] ̔~h 8p@||B[?ĉ鴷Kw/EBXAEU% tAM3bfG ^"hB`Th2["0ILmAj{_ wpj=NT9v`.\w!b\>I֒H?dBy9%@JB,4q7b!4-M%ab2DX#m۷SXAHXHo#6F#mm6>T>z.]*E$IW4JZ 9ĸ9JJJkĵSSiJ{)dfeQܫL8 MbrN*9(UplH۸{CkӕcǀC< +LPY}5 ?Ant@RJFș!MDBH#hoZ?sp7hCD[TVtyTwoppkNAM&AϞC9C¿/L~n_T8Q94$.H cg``TݻiE(AkM$(hiT`E0.#(/3Yh2zv젿Of/76ubu:) q˧w^{]s5y#j^7woh h&rp1|lF E<M A3M7)PB}^e% `""/n4GYAr|$eDxML@Kw j:j`lDvB㽊f go)l8u ^tv;YБq) MEBV񏾏{ bd9՚ ( M6}DG#doxڮ[H5AA&iԂs 2gBǽ ׭,b 31ud˗SE{#/''NP7K!yKRI֢HGΙCOK`0(<,[󷿭XU܅jkGQ]p-}=̝KcoatDDG됯˷9x]/ӄ9i6}gQit$ ooW_=|@E c۷{>OvRmivbU$4~;m_y9}DŴa@q?pCviFk Y6c;yGöݰQ(\wsOV?ݥtHsoу;::ȶHLi$h-דR3~k0c& ˣ/I~$Mٚ=[>IhZyYs}1Ū!z=}*_~=L{>ǟ쳴ݸQ^Q~,Y7çHP[n:F>I1AՔƓvk;'X96l*cc?wKT/S{i**[]Ggdlx8 U^vƢKJb_g?w tiUcz=c))/a س{U1>7""Wbec6)Z _70,ba+Iח1l+x{v.ˣ֎'Q[ϸ6Կ;cv;uJ6o0ACl͚518~ӟj7Q 1OVأ\ 7PAv>lM7?@س˜2 jx7oyo]]dUV*Z Wt:{/1U5-,Ilئ° \ફ2#KZ&f2v֮e z$bjnhh`Vro2ƈ-䖖v2kkkc7nt}jW9 e6lbWoRaw'Pq2}YT^q_YO>,wݥJE/1lK?9r_fϦA|X!w|Rc c쪫h߯~%q2/3f0V_/Z' aDG3K1fXLS=;{Fֵޭxa غ։>WRΞeH~j8h$ "!hvr8>P}j#6okj?=@uz>vؙ˷˺[4;E}MBy\JK% MVg ZJ)R}&ܡCq'U+: fne@5۶d#5k39R7Q$q lͳ4IZI(~gk)uY/|;" j8وR4\l5;0`Yka4>'蜟9xt#]c.Ixn_u/"&2}/6ø{] g1 vE`…(** v5TCww}8rMtah*jƍ$lݺ5UR9x cҥX~}$xgPQQÇ < bcczj[.UmٲǏǔ)SooXhQ({oaL>k׮Wν}!4E.֬YulԩS]-Š둘dee: ;;q9/4ZJ{~v|r,_b 444g޾˗ܳAbٲe\+.--Eii).]+Wb޽8s ψz PWWz ӟ\#ؾ};V^>h\>?7(PzvnnnFNNNkbbb@Ң` ==gΜl F=/", yq^|EXrBiʂ[p/Iƕ $O>wqGV+6oތ*a"IENDB`mpmath-1.1.0/doc/source/plots/coulombf.py000066400000000000000000000004161340375245600203770ustar00rootroot00000000000000# Regular Coulomb wave functions -- equivalent to figure 14.3 in A&S F1 = lambda x: coulombf(0,0,x) F2 = lambda x: coulombf(0,1,x) F3 = lambda x: coulombf(0,5,x) F4 = lambda x: coulombf(0,10,x) F5 = lambda x: coulombf(0,x/2,x) plot([F1,F2,F3,F4,F5], [0,25], [-1.2,1.6]) mpmath-1.1.0/doc/source/plots/coulombf_c.png000066400000000000000000001157311340375245600210440ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxK,U̵]vU56cR]t%[4 ` @$42/Y20 j\ S62%}WRU{)yZsTc1cȵĮc;se9?x'b-xb .[l1l[l1 [lhlb-xFc[l3b-[l-bg46@o[<z- [lhlb-xFc[l3b-[l-bg46@o[<z- [lhlb-xFc[l3b-[l-bg46@o[<z-ݿvo-^ficym1WP,i*5S}ouWQy T^W]Vh~G^FMaS8պsJ*ZX&18Ԕ56miM({qcԣ/wA ցhX Z]nߗŗ|P 6}t+3}09I&1zIY`OizD]?*I_RaJC$evŨ*ne](H v.S]4P,-R/<&JS,S}E,;uTղS4g, ]0h[o %͙ flp7V|u3ŋ  zs V:zy鵯D10{ON|˫"g]+~>qu-ijYk|ٝUXn=[P@@IV.Zn|>z{CA?;+ =$@nQnmHEg/E%d*6{Cab:Q][|a hYA_8I!S} UinrCް:k9^i-^>Fh  xŮ{ë頤۽{o$7}禤Vouٶ 5r<-m6Dٰ;" `m^,7(WCp7BͪZg/N]1S<7w=)-%;f{:{#@9yeSe{_9Va"ƛ-$6@?0(h]z!Z-fmƨMJKDVO$;a#Ϥ+@6/Yeacr6 Ĩ 3K΃☝A5Rm^(rqpl=Z4&`(m}c`'~'4!aPiE Qʪo{Ir?~:%٭o-d#wQ3*` m&[ܧ灐O8@8+i*bJ|œ'O|Ļn\=zmxŧmw백>Qh -_O ;tRBBDn׊,_v3WSapPuZ+R&h)i5:'zSzz3+G[plq< U7I9Sk3J-/==Pf~{-jl^P~7`޽WxQNP@9Vިwf=F K3ֆ34#*m҆P.tGp'21n\YIg8࿟p5KEvAHt`5Dc<3Z,l쌱u_૰ n V|N}I99E]! =PĺBOY#v2ml~x0kzZUx7![S`er ) ?{3jlvH^⬩(aYLz8i]1yιczlC1;Oybݻc5/n:~j/ :.{rZ]QCJAkv:Λ_- ~- )jdym!<|cC!%n[׋Ec'r"v`-<Dž?ډbEX; xdJr+ $]um*j)ZNR4Vȝ=Ag[{0+u@ 4슕rf:9ՌW$dXJUM! 육ʹ~[tyi*/$0X ̡qp qʝWd%`kkcE >s]&A4PW7X_WUtqZ^ܺŭ]N)f}#(sCByAho!PE/^sCJVј1V+ =OMEdco yE {:C7{cP ;E|Fmx]}cS)[HT핆%m| Ymngk$ J'iē+Е@Ѵ [3禞3sGShQ-upi,ʚ窚y*u7 壃sXgmxnsA:4"j=bS @oC%eOEF8D9QWՠػ0&K#M>lT0Zhgd h1~sY#P 6L%=guGN>4;Lޗnz$ 47Z buY Li|6FQJFG+΄#<"b#µ S+K)klqhФb^M{y+'`wn~ABS A=ZP5=qq=ʒ#sU ,;TY UA;N)fqPIxAP\! p3A ,h!#nZ44*τ IDATa Wʤ=cSEP[3bdgVQ1j{t^4u'Zca8~M2PXZRljOA5 8\|=;s~s5VcP!.kC8bIRT

0(E[~t6M@a uBALa`hy+ i&` gyg0Qsz 7SA=gj}d]DU< mFokm I|#am>&A$@+d3쌬{8HuwRV`"T6@?  jG0, ^2 3usYga=Č6Q%fj:<ߍ!2UV Wට .7UmT21sI@2gCmK+osxvhln3XPcn9nI0i*]/[B 8;CM8F2@=gZ^Ax^-Fk"(d{g|Jo`α"{Tt;znjy';K4bu9ح/Igoȏ%a j`*#[Gg̪`5ߊqp+',Q1 06}t΅V#Xn?C@+Ύ"M1cCW9|yhAˮYT#b\ ^q=w+d^U26p(ߣq Ѻ?; 4u<6[ɗphۺL [c2[qT idy &vCtPdv8uP005$zx[ǔlgAVnd_Ӈf6@?E8=rFPŬJ6=Υ˖ڻ[gTQ_KȺ_9ƾ{]yCX*&,ց`cUڸz'geԓNS ;"`KOHצZ³m>S7Bp);x5@g^4-)Ŷ!Tgq\F5@ (=tMokfQPP6X+c{G<@4[MOz?7t4듯 =pu4ovb$MߥT\ӇoJ~:&znqpF;Cv $Dm]ϟjf@{F"t0U@`VLEMmb`GMIf`;0g@MoO}S8Nxߍɟ-7lu"cV@(i q= wn%b^WZIEkP1VqP:x|)*9}nÊV0am^@MU=XLZSll`@tž=jlVFueߙ;Li]``!=ֻGvǝw?~}CЀ{\ s"-rju02 f9( kDmA# YXr8b*0 W- 85-NJOaRR"V.\@ 2wjzOievT lmtugp뢯v:ZXS9[hl#~((% R9WܼsC e)N4N90$~I.n<)m_V+2A0DaN \6K㶪h::F7C=\H^NMBi~5Sͧ)dҠXC}6~~[˛8|._+2ctULZ~ +U#~9Kݶ/Т4ْ]t1}1uك]oB2VX 8 |od&l 'SUA3 S 骚#o++ky* ys$~~&^_"'?__Ň>!0~~ @c\k+Ia{8ew 8zv¤PgsWX7\ i?ۓRzGNi31PxʷMM,ؐs. NסAyϲ cTL\P}{5Pvzsx+xw5;/bl^?ܭg8XįOY c:>n(8G-~bmtD63ˇFq /]L-n?7rb-L- g ݱP(g>42BLQ= ګ0zdoBv8S^4 kTN h[rrK.u%_|ΜkLsChoFrH}iuP΋Bhy[p9jzIԲ(7j[pA=- 4>Ri}i89PJ7F3Pm4(NZ/BX~D0w8sZcQȱ"-K#d/{[@1kN5:[-֘*/ mW_:Z0ۃ}G<S|**dOy쌛2DuàW硢&&3v+52o|v @ AhG`Nfr֋Q{uR9)w@8}?F2(%8Cs']zo4|)* n􎢚V&> I@=]Oԍ-46@?8+ۆj@A9|w%{x}We guc֬C֜W>y(P`H h9?9Ŕ2ݺ'@;nsخts1(Wl¸/u_z,A e Vzҵ`s`yzbr~:ybS6d2VHV+r[YMNQ0y;R){ Cp7`otzj#59Ϣlۺ,U),-5Ãy|iY 6y+CS0YLzflՙ[~E a\%aFԥՍk];|_G'xe177/)z7է5{CyBSzևA(6ȐMMWuMFA6|Y6F P8p8HIO E!`,M=>G}V` OX: " ن/Pȴb-=p=˖ ^ vT@3|aCaߩg^\C_t .Akd\hM9H=R|aqҸ˗*yPGv觊} 2#BGZ>WYǕ.k ~ԭkttQ7sJ^ݞl%!=iXyj䠦At~*`%9 +2>Az. : #}G-gk _ $P;8 L56SPR*bJ?$jSe. mq@Br[oD?M9g+ ]U##er屪˝pLϗ5ռ)Ql~Y!yxtl?&ܝJY)A(}>w]JוsTqӷXoNKs& |S ۂĸ$j|ݴࢰ`3+qaŶq11Y 檤PeF?G[}j[o'P8Պ㽰Q51bG ¦8 Jeu 2q_DF,5PPӫ=C`;s☚6OqP&ׁ/Pլs ?7PtU_녪K(C crL`cCK]&iruIʙ, /Cwge4ͮ%Xwbqe\w `?U}K<'`m@KO4Zs?ŲUmgo(zVKFU)j&Q?L7 35c%/&"hpdv ;_[t/ 6^={d G S pifMNlT1RZJZؑ-a@VAl=W zB?tI}gc.4cb  ,sT3 Kܘ\U| TM߸mUIj(TA|@ޓ6G}Dm.[b d'F5:5]/8$8gy0N-6@?8@Ph/"tj煊?ܥC تUiA>A^I{+¥49V ]sffvX( `WGFM^S(t} OZ[] YycLmp4.?H6]}W`IlWfk,3^)} ^MSHs9"몦 Y>`W37 Ϧ髉dwz_Y@̚l PikS5Hwʹyѭ!zXGQxR8y8|l~ppSVU&ZS6`צk0A|y:b)ɩfhj㊣tΖ|$ žw:m*,W¢Qm&u>tJqYdoyoRԪ emRi_Ime,)Yש(Ql;pԴWqU9]\Q6,](_C;r:0WS6GH{ c ^ ճmid8au,N8)ҍeYne4k/fͭF΍R5 IDATdj`x2(O%r1Xe`VP_VB)뼪?W?ګf夔+l+=)AՏ0nBbu6ZC?y=p`"8RϛA\31n44X Rտr^͞W̓[nh**%ktk|hn= =^I{8OI5yBޛ ^AO`La$iQ4Z@} LO[QcLGH!(WG.Ua&(`߱(L^-gci8vaߏA0VϛőcC`깩hۮY*(΀30W^U]M a褠W{}W(n6N -d$cfƄ2+0,gk\7ĂG3 b\r ._Ak^,$W !$aONzEU6zUMAkl~`ZҦ;rmC[c ~ Y&{( |29O3+Kh#Č 4oFiRq Z5&G5AxԔZHr=Cg8%lFyiں^Y.Sa~7o*:S)UI{g'sv*UHA g T0[5zY;ٺ}:uWV su:pFAƭp>lOSaA)Az'ʚ ׆1RPH@?iyz4? ̏ xL+poe}60H&H;Uk闪Zm ;VH&90A]GB σ `fJګhW3gx =g`u#N^AFE,G:Pҳ|&)l\IǪaWyv Q0׉b4I, ӛ vcP~ xL3KAvK5;X.X`bsr^-`ޠ:հ]?˫谏Tۧy]F;ɂփi- 8f𢦉$aTQPUZ^z"p^*ˌNuHN!HԓcD8YMsas5x.c ͋M i;.ԧ##~ jOO([۽Tawa2Z-~~ 7x__|#x׻O *Xt8[6 j):̚48:_!E(Z>aa4v9(iwGXn4Ht\0Sѝ j6Z ùtSڹq;L3c {.9G5ML|Gs`%"K7P)K!tfpxٽ酏?c?oo'> \]]kkof|~X$tH9HNE4 ;kCMsjtreRfjw赠>≫z!lR8'R3#)*W~g  (:cXpzZ C9U9& .xL/"vsP'P@"=1]MV W~&phAsm&p.(q}}G?Y6H>7Z_<y1,@SYpd')BNr L cUɓ*N3q  霓5G!R׷"g ;|Bjh1,ĂKCE? <7@(Dx/QϏ@:1fwihWT0S=X^b51V gY A![6Sȟ}]:ŝkG5 I΁ps hx{ރ7~7S?S &Z! 4Sjq10QR >#E : 0p`Hlީ\"v ~ b[n?URީhw4ھkwt}TeܙsDŽ;'`7/l<׀^|3900{AWV<<92qS!HJμPN8rǨ 7>Z6CD/$ O34& d)RŁǞg<n' 7|[[%Lx ^UbJJ`b}(0 M?n6|jkoOypy+ zd;Ba[h<׀?ԧ>ϣapf Y&GiP }tm䮯~]謢ixl ],G,8 pzBu[jcaNUz ZMܟ_Sz hm]n#qkwcG PpG\ M%<e |/[ROAroӶ48}yC_Y5G?Ї>>y??W_}o}[s?su`/֣Z׫gDASPftT;򢧺۱X`!Lo0[tAV vP#^xI aW#Cs ~G>m'?|Ʒ}۷ỿC?C˿KlǰA1^=;򅓢=aթ9'wc*ש\ħN7Onq0Su/xBOjIk )?ꤔZ%/$..>d00g_Z@Aa!90M~PMƇgdؽ;*ǽ݈ }F/v<~|韢-{/z׻WW {doi{ur#yuSXve/PawBF9t ɩLkqh@Y0_= {;S|zG}aWZgvy \}Ǐ`•)M<wmϾ/P< |c{?y|=>xoq0mvԇ:Ref0yejݘOyy\akL%݂pIө!V3zm=S@`;i0?q&vca=ŷK4׿N+qtDyř3l\&>'zVh?m~<x4/">𖷼gtw ?v GhcAq`m$cLPNTCup$-o'zޘ@.0+n1XA-9tdj<^1{#humޯ#Dh;X~iLsm#p:^?1A8m-;`=XwL=V秏Z\=~c?\OOOǏ77[ \5ړfJK5sh2gpWHT3n ! \&\Jq.0 Lt0HɃڤcϑaMC^aQvLs ~vLs0 7`GʹǴ{ (q挿c {&"š;`Uk'7^3Piջ\獎^85߳)Ygžֿ\}{~~*[uLNFғ@`A - ==e hdcgQ S?p ̷hΝt;,n@8TPE`Ue?50ꕓ .1 '@IƏyGXv#7'›'"G]^2cc]L >Qzh+ܲAN*f`羟/~{}sÝ9ms }s;\^^?Q RH ] "kS' g:eI2p3Y\v ;D1c®Щ^tJ`Mu?e;J&r&=1T4 43{82za<pMۉ"ٞW0K_a;$ico>?\F*I|1p{}Ndjc}ˉn_Hsaj]Я~gSKUQk0 nHnXuvvֆSjiHs|$8tۄi!\ЄHD&L4c,,zj{LAU+c;[A=:q+|1Q,J^w`8̈́ca7ĸ/@]of3t3cD;f0y {jh^YGx7Ep>t}1:9p0wA@3Gs@s|++5*-c}4y m 窢E vL2=ꡧTQtBz$m(}'(6d~%~?K8 YD/x5.ۅqKD8T8{vCQ.N4 LG"h#1B*LiTúHޫϓzE[h瞟ϐ EM$=nݲh흻̨%;PqprNAaM-;H Mi8C˜ž;fOӺ2d+QXBoAYEC 0OŲʴ#t7ռ'ȣT 48XWL*_8 7oΘ&sPfQUG/%w9~xU}]H9+b$e?m~h(M НOTR+hjֆ#RLFp$Ϧgó.zSI Ծ6 PveH# @'о*c!lD@X>fѾf'4,gLhҖH5MЧA i@ k>6@5cuͯC§).C;u$YVŌe>XflثJPE=:)#E$ՎA"ÄNQPбB)1-7qr +wbpfm3yG(; Qe0QaK.pSc`YCDApӄSfgpfjU՗~)zէ*l73)byo"n fn&HeLŎr-r2k4fn~ՌguOWjhNw`'4 rXRUa\Ω^y=CBxx({`]8r.\N'Te"0S5&`O=N *vq :U-鹜jjWz5#f47R cϟTSw ̺-ۄfq m Z 40n So~NWG"p@ j{0j DꞲ!( x=+(2_<7;{ۘO,?$ pUqt,Dܶ=ܩgXv5w\Rk='GbQ%-&B|SAL*y }Aj"I*.m={~3RRQBp=K-6@?0,Uν@kvptW9z`UsjAtyj8^=gD-y40Sxo_L>-o HY+h_Xx+NeΛVR0#Kz֓zyUOURs!ȩiO lpޅI j~MDMese$詪h{"̈́3<Փdv>.1S#ePqQUwj:oxNW?S{PjUt^X4ɽ! r>'rǎ4MG\+Q*R]f,hphwp&I3P;Ԭ k 6Ŭ_s4cF+f4jwq{3c**aIC(ºPuU Y]C@y<-m:ݚɼuV_Q\WS =[0c;W8SA{JP5;zCb`"om =uN=Rp mŇv*>I$pYAT}}}WzQɍ#Aq5K#!Uѳ)i 77[ڝ3=~KB@m3I5 ~ `eK9 ةg4`o O XK*$olKƇ0N˅!<ހ4 BX^UF =,U8ھA9w^G.vY!jgp&]@37*(ƨ*fڵ{>nqãsm`u8ԗEYI,2PC$~swh|+@?tIAt^fkM[ ˓Y"R=]žT/2ŗEIMIEOFB OvQIزϕ+ ݙӛdY |I&;^Eg*l~' nfkMA?eZCa}-A l\(ئu™&Yx1h߾mo,r03f^i ƧҠBYo7Ԟ6p^;TWE9zn˩n7>[l~hhb%tNn$H4$G$P``סD`υvu|8{#O-GuսϽA'[M)(E A "(R 9L9 `x+EA 1&&~ IDAT~1D@$+/clc8r{ٻߠjU}kժg$\Ժ껻{]w_UKbs!IzzXA -gU=KAeM3esZq itEq|UjüU7@(3eވ~ `pG:CZ>=H e/3AppF]/iWaqT(2<:p κ.@WcrXB%_~qFnRd(ےa/ zŇS?:AZޓEp+i8dY8?t"mC K8ۑnu:I Hyֺna:9-]933ޕE?dW a} NBL2W3n;jSmSP+z |'ԃf.TzZsOEwsUw`fVx(ʊXXoÏ:]S*,#e}2Caځ, lVQ#l)xO |B ꔇjmTO3 t:۠m"(c@liqB㎱7]b,(lS4?$}ejs$7(BGŞ3+h +K-2̓m< nŬwܻgW -TVǒs zҋzz}"LS~:Zy"\7wcG1 V8siTs0]CUL=Lb&>4d!]Se'o{Ft{H<5jqY!ja,'t?=\qj' ``S0#5$5#/OEKR SҘpr]p}[ g;v";~m#i'5} H]OP0^ "!R=8H GsV[2HLx>kx 2ݣ-UA{}1e>ðHu1׆ R;㕒{JQ:Z&EHz&p6Cٱ,o +*A{y,ӽ#2V 3RNU1NPO.2<*gOp)a<{X%Fh!6!揺F[r Kvt2@^l;F_DL*p Ärlg8OrgȌ4]plu&ܸ=i&9 }p.iO zES(q-M[lr$K}\Lr66G𡁷6% Gv؃6S lf17Nu/O1flԬ _y7_,<}svZst'$6Weh~Q%}F53К[4¶F `k{Z ~'z?TiXs+9?%ISpVR]kWYB#(` p"SU @ër{(hҶ+MUԻ=M=0 /|&̲&yR "ql!=pFkL}քeW$0#y - hs!s <1}h 0彖 /R2ȴqS9'7p oLD zZZ߹8; PtX2CJ:t"Ʊ`Z&L.uQYU1ulEb3f G ܪV=O/;7 .A;`hP{oDg)u@uƺК|.oŠV-iLOuOHO931}(YiwD~[49RF]y[0S %E,Hoxp/ׁ4-u@lr'kNjGLR׍ّ~hKW0tD_'ܙ2RVJRnyqjN8 %/3GjD΀ԅ~HhŮzLFۮ6X5[^eu+i7(<tJ;PxzG2Ep!mmѪ=ֈ9=a>2X+7`aXy0`qƌ(9aꧨquHx.n @%mZz[$ E[J;uC=_k-έr^=#]s, MVGfB:evYk`c:p.ɌfبpT\# R$P~) 7nh _ϖκq"69Ͳ so~ss=u.CS¾ 071}h@!>q4o?9[JEU XS ӱLIEw4id`cZ?jGHcU4 8QgT1Ú| Rz8ssUfl'V+c8UȬ}iT45߾Kc>KLMr-ˈeMa}{͙쾷Y+zFC*h16Ŏ:I5K-$JBS3=۷ nlV(7cB[ULP.jZ3flhfXx#hOHև)T445S4A|{C=˗/ڵk>#gPZR3AB&?_cbþNV=hB!dHo1sG7= v`fyXpCҜ)JPԼGʑf̠ũ .k7KS&y8Bs2+ֆ*x, Bk @񖷼<0z)]L|tg^g"az} YҺ݃u𖇯aտ~3hEDeU |.t0ne@ ީ7h jD"wcz}@ۼqQZ(̺@p" 8%8+rZ z]N"ن DiRn&ZM{iWb7~;n/]xXb N|ߏwf޵5LӍx\$i{JT"B\S hTsmFzUIIy:J|褖eh5D.lul`{,FiF_ j}VլiC2w r.g:=72٭g ?(Xt[?-|Iz/1[z8K"A(n_35zP AJmO x[Hw,+H\%zw.`FKr4P1gq/}M* }զpvElu 7XCvG mAf3f+1}h(~ h*}P{v+b_I iW45Tbs 5ԍA44P ZH*zbVpB+DJfHoUA[=sږԳ ,OA=eN-4];zLk@iЇtD`Eݱ:[=VI^1Go{oH}c6lX5oD y@i`!; V;t38,`X V8GiT4fV*u14ėzykq g ?$PiV>#r ؾfW<6ֆzGJ;CzY2:=wϓ4CE'_ve7uhϽ`fDxY_ l`*`Z\̯ՙM0%U7 6F-7VG'@:N$h^>4Ma}'G 4FAż? f1A05GyɾC]f@op7;^,h#N1lm`.n'7RToa-E&[XkZdA/qCPoG0tA tpaקjǙ+TcA>J5= }z-![H7cTn* G/݂du k*KXcb6. f>lWDNA*|9+Y\׉vYdE#;[x gK6 U( ڏ, R ,9 pi'.`ny`hAbFP,?9 c~nǠsЇe6;A-~Jnx{"چnsR%\ZOũL5j/# AWהN@N1勞ȩk'!^᭏ n LDǫ D!9+i?݇fM;0u=Ҩ?dé|nd] \謎[]˅Fb!ȲL7NhJntgD/rgjUTW+>5>4)J+5䪲Fk}lFIoː^t~w̴$)҂ i۪]: ۩nRB:!FApf$~b7G>K4\SnCPdV}?׊tGcA=l gCu NSؤyw^Id0ȀV'THɇyQ3ދ@Eglh1XsۻY0RМO]yPZcЩ-K*ޒi"" !=~qk6 )G=ho |C^AYi~@57+[3r> ޓ6wgUe%޹\f,EdW%nK9N,pjqEGwpCC+GZđvP8 _/",<}4a#@ۊ +hMR)vJM(Yx@. 9I<ɀe YմZ*"G gscs`H[1o*0UZS"~^4A5@'xI]eju.Ͷ]mǺQ2˶hI, o[:a5 ^I:Xe#V]oA)sE)+szޑf#yfI(I5mbT֋XQ}lp/;vsMm3t @ږuwxhfF*cqڇ4E4UQFiq+󢹳}Ӑ'Mbk4t?Q`e(;lslfFy+IGr> ef }xՋ֬8s @%&_C(ۛ,+уzJYmkbMu iҠЇ3'Gu@7jvU=p6G,UEJ-ߺ}Gh4gt,A:4TPne?ֶᅲWᶃ4yʾc ߦ騟P]~"%=ͱ{6@Ў:{TW>պ2O{4Zv$#G`1*:)ios(I3%%POH6wbPl%m:LT/z9@5G Ys fo |HFGV#kgh`RMԞlh8xՐf KQZ m_(MY* F5o %/C9k[,5CAEׇ֬T6TOhQʄkrS.(-xo6G`k @u)A_Pn`-A:%qԬ۬ IQg@tnMg`4(l tdZi>t-1лزS 媢̠6)ضhVpxEa/|6JšiuV;rw`CChQ.a.qYST->CYXYʖ/hru-R7IUH뀕vÂ%BxӲ#H6 /M`NLgcw>@5Kkq;/jJ`ʞ}qv9>[4y91u4saY*q*{UdTt;_4B]Jt QT4}XdsChH dkwiPl:fHIה;}G*=_7kX;rcn(} @EA rL9usQyuVY*Ҩ(o[RY"K}vQbt(LЃZuj4eBlo9N` n E6 mv;Rͩ>t^z%Mv=0OW"VЇnw|@ڴWO)iSxKIDAT̓ރu &[#@W0CceJ@sN3TzfP]@Zm@- %h=ytQшF浪]{z UE3XAYjwx@,dG PE{; DYUϾĈC9c>@skvW༳l]ټ:SWakUMij_>CHQ͑Asy-k9+ iרV͕:O۽/CmOPhAl*Ӫh(Ch`6R!б(upK:pgh(5cƋfЫ^RA8z@A܃SPiw:#Ck#gqO5m-J `E+dL"(\A>KueotmlGf OI1mPv z): FSfʑB6`1?ÈG-ҪҎXI7"%4&춹_r@ZsbdZ=0W$d&z5^ICYe87t (.})9gC̪?Fpϓ*-K5Ay'-ֿ\iVTILVUF$atY8QYArPV~N(C]B+isaQұ5#wʜO8\)["](EBύz7bH͏)jq/M(]PK{1; MY^'S?kJ)~S]gj+Iʺ[do0)uda2\@zJ^40=ei_@@y:uv^IceYƈ# y{xAkCۺQ7Z?R\/ bZ!@+*F2 QX(N0/e;6H{(Sgr,zE~m8;>t~=F\wƍ-m-eAM{TYsk?KrvTpq'A:^Iso ۥFksDt@Aekf{KMhըZ~-MD{W5iOsDW: -AXjgV< Xʻ@Zҁܨj{zLA9M>,⨧M ansy_ܸ~p{_g-Z 4-  PocmR9V[}FOE8Jܛ3EKκ6'N´@v׳="/znivZ!\y?=8StgnnXؽ`Ņwa, W7 <x{ \-wny@ŶիgV΁bE+CZHFW_N)yDF|MHm0>˦,vֲ @YO3tqWH~^VMgN)# SS*µP=G :~}`:w}7੧*pGxӯ/@ݣӀ:R$M}rĠlq$|gfr@j$[踃4H4T"<Zam3;ʺ!8١vƌǎ.K9G!}Ы6EhOQS?7 DVR\99z`B'Apq?Bvf*g=SCՋ3)q߶¹o/7wo:O-1}P6\G~eHTQ&G&-˔E@^ZUPf T&Tn{: Ia:n$[s8B8ˊ6n?U yطWjJ  ?"1s_= ow/1}`&S n]. `Y44?ֆ*D2K(&ne_%MMGv@Y2 t4 z5p1w F묢S']^a/DI`{ۤٴU2>8 7s;,B\67/ )DwoUAOWN1:6C8*Qnt 2޴!L1ZWLeteqWQn: U"/K(:M xvnKKԆH>>C΃:P?*0m\+ˣlHɊשa=4K ^On ip^ Dx_ղRmN's*گ2#Ǧ1Ah#x0Gu-Ҁ PˤCBH҅5Uy൝ h kjr,dx= T;/r/p: #fl{K4z %wB*;FB6 e`abwS i`fabf{xWAK^ֽ%}MC/i3H]09|hU^i3}_mpY p*}pi=Fv wЏCN{b {Ъ[ýѶWuZu@t͌vMWW9E뺏5LT[Dn>1_2: :b2 lLb;`=5ω?ԝBoYIxel:Ĩi̓{13:^/C壦]TL J[)\!ReA]9l]~jvFp^(f Z$4v; /@Tvӥ?Xpe u`L'<5pVլpr coo2frG=N&Ga9MTl/WMS> i @th Ru8 M8tu?SF'{6 tS?w6lG!lcu 1Ey|>0# S|Rm{X}썶" WSEBnm4MDn{=66"5sPU4܊BOr.u6"eӿ"TpO) 9Yh# @ 9P<٭d{Lw\+S޽zIgPvV+h)o.} n.ipGkY,m:_K:mֆpizf +tC0 |¨Vh6A%&|\UѪ7闋Ls[mMmsEV!7n{i{K!QG>t:޳ħ T1T8{i|59~}oIűZ!RH(M.V8&ҭ\Hw\BXvZ퇄+V+9:m3;Wn|kO_Nz˜kMZo7zk<ԼZq;|7/R4ݷs_ P= kyzJ澮IyG SYY޳IYtaa*hu "1աܞ-vqa5ZߪcڎqXm=˶z#胣W^9 T/Jb'Ls] w%-7,,ݏoJKylZw+i{,yS]_&iumoLy?Ʋszf%mI"S7gKޕ}3m 5.(8(?7_klNrж,)C$yf~C_=1}`v^@ED,ʣoY1?zo-l=#X(;Be2i_ O^@ Q'G•tk**mEqMÄ~y0Of5+qn)`kɧ9){l/3B9n}zg-niH=?jİ8 ^ZkjKMK$LH?>uofw72(,:v=J7WM:{.\˧KumXINօtʭIdğ)A`2;B\k%ؿÎY*mkEGG,yWKɟ/x_J+ʪ+oo_#Fqư8n'?'|?yWC˸v>輫eڵkmǛ&|S:*uoo899wމ;* ~7~˿}c]WuN›(/⮻:j썷-xGpzxꩧλJM o'{sa/>(\rooyWi5~a\|{UY'x׮]___>y]WmN›0;jtg|#olĵk}o|c?c?}UƟw<㳟yWio|_yWU#Fq$1bĈ4G1&W__<|^xG>w~wpjq ~|3;N?x|#> ^z%|C=xyňeYWW?g?Yzx^~'vmxߌO|q ykҗtƈy#^!"xއ}cowcv]Y?O4~~ p-G?zq zī">O൯}-|A|Ň?aFG\r>,>gό 7o<җ_|{oq}o??wx;{7<⦎G1&G1&#FIczĈ#n1bĈ4G1&#FIczĈ#n1bĈ4G1&NCIENDB`mpmath-1.1.0/doc/source/plots/coulombf_c.py000066400000000000000000000001441340375245600206770ustar00rootroot00000000000000# Regular Coulomb wave function in the complex plane cplot(lambda z: coulombf(1,1,z), points=50000) mpmath-1.1.0/doc/source/plots/coulombg.png000066400000000000000000001026251340375245600205410ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwx6~Ϫ^,UnmlS !!>/8āj␀).؆`^U%ٖeujѬJ;.]k9̙{B 'p ' =т8N8aD N87N8pN8ᄃIN8 'A;N8(N8pN8ᄃIN8 'A;N8(N8pN8ᄃIN8 'A;N8(N8pN8ᄃIN8 'A;N8(N8pN8ᄃIN8 'A;N8(N8pȓ:t_~%j5i&Vƍ F>h"t 'Ll2|?Gڏ?HHH'NH'p‰ C8o111xOhN8 5qx1m@HH~BCȢ߶>bՔUpt1ٯ %жZDGG;,|mgiHtwwchh!69=/}}}.^8h"2AOIrr2ySO=E>Cw^jɣ>J~ic7{l75m'ɭǻ;"poly Un!Mj"Gp=Tk|K,h 0>|s{#"0 lSRGÝiw~lt0vG[ {]aBn>YvG„8! dg/Ӧ`h&ZNbvlm}=6Ŏ&r[\dx(-[[i3"\JꓩQpPՖwʢ HT*e_?mr[\dZHwtP4Y1Yu~!(( 2H0 DBB r@@\]eIm&U..GЎqa]:\~;wmr=H4OZ>mg\Ȗ|@DEE "V?(1%AwttX:FrLJ%,8AX/z /mǫ_ՙ9]ns>>惾>$n&A "v KP $$  Ehh(BBBt6nkll… MYtHH(AKW(ptH NBnd. QV /9Iva`8J^*8D.ʌ0 Km4dk. #Ȓ9 J_~IBrpXK_B(ۡ#h9GhiiAsscg$W. ]Q\%A r(j]:𯱽l;~!7)ࠎXȖa"@~d,@Lv 8I7((!br~^ wg@p)!SR#-,MrA###hkk677[PHMMEdd$"""ﰰ0_ͨi"#4k.{B!ő K$ 0xhhTC.QZ;)ll悾}}}hhh@}}/Ԅ٪|}}I(C EJ|BS'9?/Y`'!P-qUryhץ+G_شp,#__Kbccy\۵bޝe+:@}v;= E%A v&-IZXQRW=rqjbSNɓe [/[YZ.ϹC-IP{#y.}^=*vawMnV&TUU ;22 " aWz- wb}nS;2dIТ d,9=S.߁lS_֑pUU]*TWWchhX|WWn+zU4ZdD$rz$hNBfFD.99O2205d*MJ|sܾv}Z-uk{lhh($+1ׇRDIh[#Z>kAu $hNB: .o'e'n100`ռuܐD$$$$߮!1G^^!LD T +kA-IcNrpܸq(//G:MUxBBB#^}"{9a̹@j_E&~A-IcǤF$yBAKKtnjj2ÈtM811 Q\,XYnڊMqu $hdMj$⮮.]]]4#-- {O[>7K+ToC^oKfrsG, Z jؽ8sfB 'yۋ"(J(J\x<==c@iiiHNNSO'~;eIruX`z/ek,Zchpnhh+/ܹsY .DZZy6QNBQ>vlB Z :2.((իWMl3g !..N]xKC~}>{/h@+} GshIo&qul3\0-[`ժU }}}2&I8Ikk+ QPP#j¤IlY2 n_]mo!W9]u +'X:;&|hZ\Vh h'!@krP!`yӃ|={VG &M2EGӧOGNNYSv-WF@Z8vBd[NPTx~Z f̘,**Jliނ>#<6I0ⒻlCZhE]@Icӟ|DÄ5zh̙4jtN8Ǐĉ~>SNł tz{)V&O8Dw(! ̉GG#hAUNBHKE/\::kA,?;۷---m Xh,Xn ᎫCRaAzP!t t!+h:ZD+w wrsG۠`u9VDB[oaɒ% '7t~_c/뮻dCu*\6u-Z5D$uuu-U[@ jm 0u ԠmJ+^?ת.pQ|wػwA[XXVZ5k`Ŋ 48ޅ#wY<kxCch%A[$db=p@tuDnn.z-\~˖-Ö-[҂۷cڵ! Q}W$/^ Ո㿈?17o }ʾqJ:Yڠm=<{6M>v N~mۦsssCtN:OtĚ5W_w5YƏa̹@zMw,_\ K &'!Bԩ78 ?^x\t J?  rcsc(/[AԎe;dA[$oDixCK`\'rJYOWO0˘=˃}U;dAu^t /0ydhhh%KpIqqzXn_w_J^&^9t_8V4\ K$$~1m4|P(xqe|w0O%r7NKn9~Lcn;B3hvAmIxI,^+V?hhhヒ)Sh~cK[ 7\ރQӘ˃Rʔ;dI|NBRիWc8~8Ұm6TVV3I6m/y%wg'-G@'BcN7cUH[: 9 +uxhrsG, Iڊ{ӧOǾ}(--[psFc!_ r0smqώ{𻫿(o/?dCоDrsG, ZIXVVٳgc4i{=TTTࡇ(/pM8}8A4?ߌ7 o1$EnFϙ rsG, uTVV'8 :O%hoũS,0i>6mGB`>_9%.Coka  + u͈̅* b!K@QQV^nlڴ [n.TnrurvU;~s7pwq{vbn\kSy/{9mkЎPc"Ƽ>Y7f(^RBގo^{b9^dg@ru{mZ=AƐ˘?ҏ_Lr'rEEw(v\յ{x?_lc 0cõ0o<=wpʢ^ dIP*7o{9:S(8rD'@gI9#}#13j&jkQ^nO鬂Ï96{]xx/}Z'0H9=wǽ/b8^{?qEjȒA`` [9cY>e,yj}}ThFwVxf3RLRD&r9B?Byɱc ? M@He};:n^ʕ 2>><.txfg=#NU'{ݏF{u՛!o /IN/6\@̝KȦM 4q444 &&z--ӟ_2C x`Tj~[ ) ض ;_|ϿƢ FU)֪OR_ͣrX^/~&Id8{X_|UDO?<7ПbN <61hGůt{6@|V~Lm"`v\^ A=zn :,l$ݷرBHyy9'RPP H…geہ$$T+ !央hHԩM#H Ξߗ_lyd#ep<(!@9Ʈy쫪H+!ޤon:.|',Fz3frd9Y{iy} 6VK>2P;_M )/h?A@HS-(('K>dZA=o$xA' )*"D ]Wz]8&ƍI\\yɇ~HKZ-yGO?M{1nKD M/ CÅB22lsFB]#;SAϚ7/]΅DI4Z}~z$B L͍//B\banɽRA6o6l $>n;wswvLyUB** y껧6w=qr:OD 5]5+!o#cB㩧hϊNBhW!YY7ߤhh(!3{//Q ,ڱ6x3y c7q3q8-k׮%۶1MJ"DիiF(//׿/]Jm&$1of<@;޺={&9w.lY@z>P(Q*_{h@w++Ǿ}}?nAzE#54GmNmmK_" ֩tmg!ʅJqu%$0FVj De%!TilΒyI] §şlɮڿA H؋ jk6S*8 Z t)/_u(n) }}E&'j5!T ݾq {wW_ÄmO ~^y{ !QQtWEw__O'46n{]B`3꭫By]IdG3umZG#2[EdUS`3K iAZ$h)p뭷BPdgK4Θ!Ag`mdcz;0ݦՎש.$7 IDATS uNk#2=7lw}a]]_؏>bwes̵ZBRSi }^C_n ޟly6V%$l+O_!Gp4~de!$$ړ T8A/Vw7Ua2_ؕ ߹7Ɉf==o36,r]2r˖yy@q1PP ASveX}9}ym 3; u+}}7?kfx&bcp Ucx0^ $$@p0 Ij1/.**dnݴZyFxame$k` #d1 {2+ۮkg9LV-ͅhVS[+v-їGi-:l/ ތ{_}}e; CeY4[nam|c`nGVYʰMD0>qO{ahkaacI:0u*T 4fk2 )A@}i"sw}7 1T)IKά6>@|spOs|(-22|}0o-~9"BI6][@P79ZЊa:+&|5wcmk--Ҽ{!s> DZf_G, ZMo{H9m\V}G ip fyBlFOx` aP`-zuhwazFMOym1P(;d̵Z04fk{s~=);@ܢ<ȊBJp C?+;B@F:Z-P 2X߱laWO%xQ{O!!0g[>ϧsbe}_o YSjI PS#AKIS_Ypad;4쭷oQ1Q'zY2)ܰrA]ޓ'd hy_`ya2NQmxBYK"yUDjpw.gВ `e2%CcI&GOěEbcYkר9vQw&>ٗ-lK0ckjK_a,p nP(pspa\rCV^4, xMBV gׯ/JС!T*Q25khn/jBNP0uŢEƳv,ͮ]]4t.ygSĚkRׄxZJ cyv V9!TsqNT h,.O\\:>uy嶀`8XuPx hi4=BZ`hkBx8U-~-Jpaxx`dg>_>0+G25392dIktJ;ܸ! 5k }gXۭK7K:LRXءʏ^@thj B|^-Mc~2V͘}B5oU@.'O4B\]sM]תVMĀ?/K\&#NFI+֪q A$hc'!@MLԾ%IRfžAyr kk=[`gKHf=eyt _9R0: S`ԍJų VhDtn'v]91s捣5G1 ^Xdf3gҏɓ_kר(71=Ovk#8Q{>iz{2$:n吉Cm$C2c˼rE̛GO1;OخS v-VܬY. ^;rrlz_N*ʂ§,`IA;e-Dp/_?kIkLv-ooJpmmn(owO˩a<[| i4a)\.8r\ImrjCj dINBTKNMKo9D`'Z-%OOJDb0g=sFAy%ÈC3gCA{cfLt4a?D CMZ-M:٭5o>NN✦ݸA#3ccëU#*?``N5j2֬e;WƍxhTĆ4aatkk)R,KhЏV@oq2gIG, I*⃋ wT{:O._/I(&Qt xPUMɡ.9}ڢ-@B%MXٳ3wu:F8{~'0ƲeP0^NX??֬gVO"U+œ8'ߵ}2,P}ӐY$`cC4HA, IHAۥ1 %E̡dp}X^#̱$C^)Z'cT-g֭Yj66ơG?W-YY Ĺs Ӈ)0t K~^s[>Ш .]#Z謨g_@_4L|0 yw7^שz, IP{t)cv hyr- .Ӈe ;pxSQNaک5P*tN][KY1>؏K\bP=A7Ӭ&g %h)aa4nUwYPB٤wY&ct~x Kr;ȶ,u`YPBf'RhЀsΩS6iNVQp n(%jyyy7X\ZM?"~~܁-}-(i)ARPCY5KNBscCuC8~30T7%+by٣fZ…4qF aZRiai , IHl $[Z[R rw|:.i34v=uu 0r$%8jz.Ze]a [*j,@_Ue`/. ϙ4 /O/4{8 `dJgxtI+{0sv95au9؈ Z(07f.Ճ(j.8C$h}~q`?,,طJ 0r0 ^6tJ l%躺19/-`mzZ%њG!$$ ʢ":CIgcAc|%hkУl9~ꑒ¿%ءY :o}Pؓ]vhY4@R$fT,ۡ% hI:!3OaP͟&[ :51 CaЖ` C9ed5NBH KC͍4וњ&79Ճ.K$%` pkmY]sU]UH NAge9;;C, {?=Ra]]]i0@__84sNB@b; +99y8{e[_S6qLN*SVsǦ֘9Xrxb Nōl~$$x@F[>*8<X6GrX$z2 Ruvhk㗋BUd &J5ǒ)LFgȎFS_jkc1Ѐє8ԏ|_‡~hbs6$$Vz%NX).Vj+PXDj,,4S`Nl /3qxxdɁQz=BUIE C+_7kޘmgٳ; =Ga`A7qeйD+RcY$h! 1s\hO>p;GCO(AO<U[[#k 1Z _}vލu,+**t7Okc\ nmvѣuɱRFF(,o /Ϧ1?Z`ɓi۷r[X 04Djh*Ta8Ws݃ݢeٳt rsm{ۦMm_=JHO>L3tZ%W+peE`dZn?W\Ϲl/5Ci9PZ.+H;Ws 0͌1 |-/ {=t[S՞  B?ٰay'ɋ/H>Cw^r1cGyk&=fj  ۛZA% l׿]}rB6o x}+ljk22A {*>UG/%E !O}^^_T'>HiZf8q{Ս z6ȧR`3ު#GpTR%Ke# )<A8|zƽ`3H҅ux*plQr46νG**,rxCdi+i퍭FXh&^՜3Ь,ZUe>H$4j?gEj&vEd5_ |CՇpE?8ƍWVxcy/n k/*Bh!,,9 1Ʃd6a5V0ܫmX-qdfRAЀvL"sďB6L xx ".,AȂd..Q  ^LDoA/(Cˋr|K w-]$>tbC:0dIЖC.Y!: VZEh4RєŨ(6D@EГ&#%8.Y ?F\(,ٟ%0mNLrKbM/*abn<]o-gFѹLi(B+}:8CSC@m.4 Ih}$}~ B &'j%y3x| l9LkbeEa!zQ #8DtHVV֙[<8'F5ZZ ^aM2wa,Hr}t/\ّ "=]2, \&!iӨMKr J,Y͛^b0UMk-Z&(,D}^Z`.TޡH(qi(/ 9 86`Q tQ[P=:EEfSufA}t^GS_23mN*dJ H K$ !9jDHBEiU]ds Р+*hu._ UBïKK76mmP&&_AF|]TV&S*S0jjh{f&,B.^.\uݧ- EcZ+eծ.w@x$ANPa;`Ȓ8 15% +t/] ^sD >XAKANdjkQ%~+U;:&ʔ'v1D YЂA.0u4iBH1(qYңF^ oa˱lIGL!K$Z-P'< r/'N` .f+0OLBafiQVI2cġ=$gu H KCG7Zk2J,;P'!{:2bF)dIB^sinrr@c]q$UI,A N\js%-Zf9J uݶb3mL0`03Z4]BQgPRa|W<=W؇fʂA 8ĔJ56sBp)ܐα,=t2, ZmC 3Ǻe#,ѳC<i?,]7Wm> vqI1Bazi {_$HKKEs3-* ,q5c!F9ע{zhWRh1L7CbJt{ѦjCVD<\=,wuw?"Ȓ8 :6 +"P/!i&q%0#hPr>>3vSuv5SRԟ;K`>k-h1阋Ң{ztMǦ&nZS}tʩ/0e _RtbJ7\A5OV4d$hNB6[P]rwgQ(mGBgCl.\u=z8duL@\TҐX)A uvCYLm}}T[ghm\B 2azt,`]=^^8^{$}tڵ́&Y;(V /iiV#(Nw.!Yѳ!6%3Y -vAꉌ07N ڱ IAʢU\Dwʲ~9Kpqew7qPZ @QJQB A{z`~| p9 #h{iiZ/.X[ ,I?}~4k0VD`B1g鑢*\ѢV s Ȓ: o4hwwBvtXNBo:s~KO%ȦBDEQ%,_ @bJEM@X]`ov&y ̤S%$GcXMީD^ ]J1ED&sOT4otwɤ$꼴^M"@ZȒ: zϒ$LD9 ^+p)-"i\`Gj%=B6lgT&{%Hd+PEz7%<.G!0A 5HP1FniXv1`ݲ-Ĩ)Y IDATǺQ8WO-%AqKZ+!'k(i@d+`Qx겄i"3f'N`Xc>QB޴.[z AVK﩯/-D-)4=;6VTLtfe2׺Ce:3sCsևҬSTs+>^ސ%AqvC-`S'-d, oOcX[@}p6Їyb]XfgfF-WU(Q,VUV $%"'ܦՉӠ-D3f6JBK1p1Yg/v]\t-4rFj@O :`pxA-I؁OKk߸Am..s4fE5o X1VY(ďۉC%."QR9z?`r=b9 ]\pSFG[Ыk/-4`3m͘]jˇj/CCԼ1(zY ڀG3}ѠY:+eefvnoSSyȉ́s6N}vr.AI@f+kcZG6oMz+V AR裏AAAx7Z7n+4 >#: e yw3&hJe0fĶ+1 7vmI2a\ba9$}(\8~1vWӺKHHh/ҏ;z95 xC2Mfʝ ?3 {z"+" &%{`39׃8d^fw=|bH(A͞tTIƧ~ᆱkm۶aڵեs,?~)))x`b:$`f=hlgOJKҮ bI`L@vh1f{{7rU*K八Iwǟ[P-\]aC tХ;YsV`Qu!Bzl?Bh a? 6议.~FDVXR|m@9:J\.9njv"V6&s$$ ; gΟAp`+:T*BPqTnnOv)8ӏARSM;NK$N+Vb( ;9fEh$~--rB]()*08hF,zbQϋq۷FD8[ߴo͟|B7Wn4ٻw|N;~fW >QzGiCNsS|7 6NϛMıqhހ0BZ5jQkԜ(*!)!s.1 -`gn#|26mڄ3X krO]IԂ|9 De 9MvY / MnʢavՠnF>tF٠eaЗ=IЖ>>tGz(`AbR% i0#j||$'F9@qKIDG_F[ZZ`I3,$'h/2 :,VF`^niZ\`K@K8QwBqCTR9N`+͉UNDx/P;+5hoދ` sp17^AE6ر捖5o6W_}/o< 6x4cLBEb"W^.M.)t֜iTY(1sB?uƚUs>3!g@(0=c9mQQԤSVF jfPP7cHmPEke(>~luѕČrV/&VQj~~~xX$hOOփ-e zT{c'7g{"s{ZSב߼o 4h}blj➪0= #~Hˁ$Zˢ:sejЬŢdg[M=gz&-$艂NB}v%I0me }ivq޸ASumR4ܜZT+-XO A GQsgb.LJGrM.|1sijOOH)d,7{iϹe̊wpÍ( _Fhoc>DiK)}O K}vͮ"`}}k?IZ:]RȒuv0sѲ7nvq޴R䓛:V{Lnnx[{->@1g~!!Ծ<7f.J <rq Qk(d?D.s)o1Y١yiK)F#5h`B-n6)l$hּVn@m #30&FDF5$d#TIE|rk0ZHU(Cՠ$W&34Ԙՠu$ok,7g3sb&0N;jʢq`嬁AB@mGay9ո8 tڟFIZZl?ܼEJ07!sѠz&%BCLvc˝NtNHm2' ~$3[OvCc3meQ:SEEc%*@n.jAȔuͅcIhBʏf[AGGcJOؗeN5~YN#)ƜlRbD;91stSt4hc=<>͠u]sE?+z tm xz1^ &:d!ˋzNcjӣ~:;i)4C$0T7L]N ZbX$P$e0q6KВ; LL/NR455dSHLDxAͭEJ1|MP3wF Kn/添 Cķ,'2.]B_ ׬+?/@rv, '!@oF#]0j@Izɝ%%TRJI\r}YgYWhgXoٜBI1楥6&u Pm61֧\rL?r`Bvz-d̋%Z32 ,&z dW22e , '!`;tI 'gTr'!%E J[D8 GBp.iBR]EOC(ty:nsmAj%AMʃQpj=u uL? AUfl(duIEߟFMoB63:-ԗPȒmq%cgBmjH$,rQV&*\r[\J;to22PYzA(p8;9KY]Fdgݨ<vh. bmԠ}}z46vœ,9{!cKP^NjQhQQ L '!`'GXtI8Zk:r G6Wܰ!Aj@Cb^|h捹DrpFC .XNlU~Z-D`7/&Mi_{Ud )P D$&4i EXX@V^YuzuW]+ª""% J@i$b }f̙iL&\ׄS3s? ؑV[a[6̹# -!0fn7'N +IB5|}l8_.BmnM66SºY|aa6NڏN)qhEVkDk2UYM ;) םBq:+`H^9bvsTOE:hcghֈ" (Xs&4 ޢv5I>+})[e o+@w]Xrv= u]78Tr~rJ JNBP1gjOTyf B:}Fⱥ;1d` C͐B@pP;6Aw; 9] YMv~w1AX/ f=tNz\hW@׎('lnM 4Y o@w-`@$zHIBy}9JJl$%"!5*JKq̅i'NkӴ!*5Vo Ct[p-,pS8Yy"Vsj?=b͹s]1&-O5BwJJX-++u!\hW@$ ;3:hǸ5I(ğxCJ>ggN -`C sUp+*xa:kt8-݉3~J? Z=U[t# KiC.?pG}V=HCg?hW@ác'lvqk 橍dX!CXw%WuK]C*ݮ,id@RϢ qh[ݢC"ш`-)B0Ȇ n 3QG [')&)>l])s{*9Aԭ0[aIIl>t!֢Dz!phNmظq#fϞ/lHH4 ,#I(,i ((plݖ$o',pt궶Z]X 0?Lw4>8%~JK%J ?fSPP izi]Tw!M nAP91! E]Fj;86[" yyp?)PPbI.))̙3}g/o/ĦMގsGponr ے ;T#fV*#gu[1f+8…8Mz$x> 6ZpӰ6S*~O8tm:eYr;1#ZB)+yy~STP|vɓ͎G-K%5]w̷x!TK.p[} ^b" |i3_'BNB*hŮvmJHc=\TRIb=$ o}DD*ZC 1Giux1+={tRJ|rx7}`s˖-6sG`€SX,Fb9ƒ;@a {PnIJoYYM&t5nja!VQa~Wb7?C%|e^Ə7;V߇v?>MMӆlDD`p^VWzU&$%5Ln.0y8y@%{HkK``47b Y?jg›tK윂",FFP;!lR> CNa^ܑ$;j@wZa$ 4ЀѮIE--vq8qsS6 qhy9gCeٳlVSR bŬRWhWsP1%* >w낁Ƕ4bMD8z(|}|m`g I~_?b#L̼>ޢb2LGB|L`AZW6?}|piݕ$p5qqXN7rЅvZgR 999·7Dct̲LJmhUj5"Y*"L8XLMe4>>̒אnܒ@;`:Ð!(-Fyɱ8 ^֞3&`@R7̿19 UUlzo\Wқ@3I=_g +'xme1ҳg͆$:>޼[F|PÌA3PPq62:rDzNfSR$w&mkVC>3tc,"_ HR9VFaȿ  ^`Vp91Ϫkס>% O S$!mhͺz.% 1dSk XjK9v hcάfg%̭7j|=‘ĊNh3?̂#G+,)a΂ZZX0JzsjO8s2%-'{"<  SR6lEd"#u7åvg";9\J sL60ɓ(-e^)޽Y?ijg[vgߍ3UHGH/zdő#h׶cJ(}OwѣY~L`-{8d=B@ڠ]7=tQ/RץD}lio piݙ$H  6S! 2I$O7.AXJZ1%i>q"cJh T(سvtTZ AAsIB7}~s}ΙcY0I X0r$ <:IϞ̾WW[['G 8;+:+ sXBjW )Be{7^-7}%}CZ_ V,%\*x qql{n.P`mbJ%$P)0Π=>6 EZ9?%7lӥƾF@0Ɵy ohw'  ʖ8*߲3k3AkwWN!,p}sNqgd0Ӧ6Ӈi;zWF#Z>>cikZtc@ϜiܖQ!%Nĉwfn ЬrR(XF`^ix sD*,>hZo!]lY2vƳF 4y}fޏΑ5Zؑ"| aH/K$/¬Lʬmm'  mi宇7c?%ʄXjN<Ãml,7=.^d^w^ϝ aZL0+_}>;> qRiE$ɨmENP=2&-ZДdF('~j=ބYǭ;R!{ )b)S\t\hw' YBiLeCpsIB=zXL }^ x?fx_lA%%c:i̦l=eT[^[.BP||!vpš"x B,>ͺԛbj++oR<¥$0lj/ aa".κ@-&ڙmg綷 ^3g 5[3%iR;#* 3xaM]ٳo{7kOf(aߗ!2̡dፈQ]+'Mb|0hPfپG;t:q(jm6#Xq2 ;OMh>݌!͛ X \J̎0>} o RgI\Dn‘}4k.NڙɓٿJ#!3f紁ӠRѡHL,06 >.5nk׶ ATfs V_^,.s} !̡]}-4htkVY޻zATjP^^.u)q)PF0wƾ}̀Ϛe7!1+:l{-\Jl#&{Yv ؼ%X,pyfWj^!4}>40tR4Ϗ5a;:}[4 ƴPZkhFbxV[hKQZ#?D9&2yv D7ԖsJJ!}YʆJǪTe!>>7`Q"v[O YEVJFF~`3N"i] qUog={v^矉||z"jj2UyƉ OHQV;:bb+Wcffϳq+W!!DDӧ>H ݛl׶|mivC4J6o_k!Ky*q|!CY_^NپDm }g/+mϲ lRAoeتUt*ZQD$~ҡ_ٻ(0GJ :&b5pk6{9s-Z ̤=SGFbo޶w觞zLW^طazGk׮D!.\Ⱦ3n;s( ח̉…߻ױsS-%at:~.53<٪OMإnWS!?նڽNG4iԦMmDuu|# g> {:LK/IԄVD}fʹCHhc;j;(CA?H!U UXDiki!c]ґN?Ml۝wi.e@6НXlniiQVV+f-Z.]" c_{>ͼ/לhS5GD0E ֭NPm&L`/z57}vWQAD£;vsB*hg3~4ln>>A~חCCjW<&N4kyMd~+QT?=4#~aB*xqjjXϏ"FnJ4a96>)4Z '+J28~QBAt}=`3S>=*+f̦#f8Gi{t/%P̛1ӱP@۾oӛ{޴~\a!5?0~9/wJя)))oVV999sNz7=[ iȐ!l2:}4кu눈護ޢ,X`a:Iؕdggv)DQQ}@tIДbeңȑƿ9B*h}zj( ~2UyNcQD՝4\|2P1/чμa%.Fn|3?a KpI!#>r|Sd x[!JC[?lccuTP?H=ӖRAOnt|P(;7oLך"Wˇ/wpqk[Ew} . tW$j Ӎ6h`j6kDzz . ;+'q|5: ?>`ݮQ*VQAQ?C`8u-l; CSV*V]GKIKށ{n/ӝ_eț@wtl>}K6KF>6pz-EP(>ӊPPf`pE&=7ŌA3pt%6~>~/3yxo+tlޏǥ)s$:<ҋXll2dm=.3%זp0_=}3hմb%8F~6g\PJ 8e*AtN= y5Fzf[vOr~xf3ov1OT132_,gWŻ37ΚgZ ]474iHō7>Fhrی7¥U$ 9ݏ|CcǹypCہ'{ ;~^C;!sH {?V|"y *}H7Q"$!g;HMs6V^ږZ7݀y"0) ^P') 7:X,Q$MM=Xq=k^/\[@jiaY2\m?⍋HLJ¦9{* n^3bu/zP(9]*E$6J$Zm 6 &8[%th;طUӊuaH!ViSs"3͸5~׶^1p* ZNztA>?mlS~ 2J3pS|7) oenvB(K -rD ŠvB'{77r3\h9Iyx=gl:-}>??wV{n׿.x,sCƆ (U΍.?R U ^Q] U$<^kObϻ݆}Me^=8ԤՠRD΍D # qi$å-' = ! P^"޼M{NZ ]ִ Z B,>QA%ſy7!$#u7@oqJhmD]yЩu3ww>o-\zrW;> >﫨g46`ZZ xy@goK-' =~]mCS]DѣEV{v\lA|ttŀuĠ)\h9Iyx W݀cɡHJO*V ::w-GlW#X 0 s@IBën_iQ9vWrpziuG񟋡mҢ߳0I pNIyx W݀x$j/h-mWЉ}4VRW_#\hޓ-C2Ϋn@vяD#N9tkc2d]?|p\W[.=$' =~[7ѭw FATT>9Iyx Wڽ 蒒̜9'ĦMގ퓓Wy ݛÞ={-\аJ 111hll4҂۷#-- ;v: /7n1bhMH5ZlPok~_rssz &u[bܸqӟ"—_~5kOԄM6A26xb|g!exMW;~{Pnűn:[l[BB-$ޓc]7n4;WPxZP*-)x Wڽ@z&%%%XjٶŋcѢEECC fWSS(pesu:]׋"ں[SW;{ "7OOO_|wyƺ ,]pQ߿/aapM7`hb\U7v^u|i7x8sL7+2mҥK3f ,Xx܌/ׯdž pywAtt%t+AKEVcŊ Axx8^$ >|8hѢd 8s N8B9svDt֞DGGFrAl۶ Mw֮h(<|hkkC߾}SOaҤIݬ'l޼oNDDO<u"qdffҴih…rD3c ""Z|9]vOޝD#hZh-]˻Y8RRR,s"^̧NJsΥjkksv$""H]TTT`L߿U9fҤI4iZ[[1}tdffv$ITUUbe_|E /O?fEٲe ̙{rW7oܹsO̿klڴ ƍɓ' 0o@~@_~ݬH=zWEAUU@v爊6l@ss3֬Y]oذj`>Ǟ={p)h4tttݬBw*D`|Sbx)cccq/}ahooǐ!C0o<,]vnV*I(###[o@x)Ur(--C="nI22 ̯SBT={='ؒ"h_- W@*裏0vXlٲk׮22Rx)-###ZFFFK "h/E62222^leddd@x)Rd-###ZFFFK "h/NfFIENDB`mpmath-1.1.0/doc/source/plots/coulombg.py000066400000000000000000000004141340375245600203760ustar00rootroot00000000000000# Irregular Coulomb wave functions -- equivalent to figure 14.5 in A&S F1 = lambda x: coulombg(0,0,x) F2 = lambda x: coulombg(0,1,x) F3 = lambda x: coulombg(0,5,x) F4 = lambda x: coulombg(0,10,x) F5 = lambda x: coulombg(0,x/2,x) plot([F1,F2,F3,F4,F5], [0,30], [-2,2]) mpmath-1.1.0/doc/source/plots/coulombg_c.png000066400000000000000000001320141340375245600210360ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx;m[Z\Ͻ9np[dGTe<%D@BB!C$ $,5vhɒqd'M4vTcu{>{Ƙc}%Nsw4||7UK,oUp Yb%XK,KcK,[ Xb%XK,%Xb4@/Kz%X-K,oi,^b%xKcK,[ Xb%XK,%Xb4@/Kz%X-K,oi,^b%xKcK,[ Xb%XK,%Xb4@/Kz%X-K,oi,^b%xKcx=.8ӂgjpͼ/ϼxn>#yZ|`t kʁm㗧/6/&S)x3RtnK6@3z^y|~&LKiR#A/b[-Tڟr4uL*,iygwvSڟo+K,~r~/G [`lj?~len gSt|nYo·ڶ YƖM|(Cs((eTfeݔ͓myfS{{|pXK8}lsgݹݤa7Lo2տs~ׇnLNfR,A;sy. HUܪ\4k'jY08 \J?{1f!@?9Ex@4{^*Oo|ޅ/ tV !̿i]z֕i;mD>8SٹS|?Z|, /Th_F5.["'FS~Y3K hZ[ }i>A[&ܼ$ łxѕqBؔ_M.KU8iG#YӕѬ,5=:.XĶ3Hz̽:[1|eb+X餤ΧL0*&{ Tu{V5qBXT 8 l(haRgfC~#EIK a| n*Bw؄?6EylXnôptfqpvDfkd N_LE{:ځdU%Zoϳd`|%Hyު5OV9dmEӣʵ.kaD#1_鬠X!Eu`BJ1)iVPo׊Yo5Tm{'rdl6EmAʿd*w礠Ѫ0Ў*Yl:ʹdao8UͲ&YǬᜋ>mO\8yyr& (jvR s,~bTbfgl,v)9^*H0ɠnvmZ~Td9.RnJM^oGpW6WYHP s|[@f˚Ϛ(i<aeq9.9ϹB3=bkzsN@6G9p;P(Khk_E*X7[:1~_} ZI']m>:Ů*Z]#E=Y"+q\Q~~{ODeė{>?󌯨2<{pn͎`Vԧ^-l R hl<]JЎ?W\o-.yـ V޺(5+Kc$V2N0rS]ϟB1.{UbN':VaS%eilWq.> b [Y$GNZ`2֚rFyi{t4to9fLg]t`0;A9Y(hr+`'>$lt]6coh' O؎ͭZ.acuY&cGFQWyqFq;l+R \!=﹆m,??s^h :MpRj^s'[V:&mwuz 7nHtP&N-IM[8 <^xb|uݾF[eiaiNF!Qb,kWFqבtl{b %*VI˴:w[Uw}X==_k~'~w}G>?Nl{{1"ګj +;fg.FM&YTy wҪh" *Zhlnlӱt'Om[Xms-M XaUsKkf-O}'vy[rR׿ZHk\/|?c^_D3KK@P'» {i}V,0 <QRPKV:omL!ި^hٟ'P.yA0TZVʑovNXMkqktXfrKA1|GXR+_sͲ SI@c7?-4onl?T;Uԗ8{ dG_2_e%5P]]HC S>l *9,SL, g~;hΛ6Oz *Tq)Je(VM[k#-S۞s_5lH1SP2#5T ejq9 o հ=Zim?y51j IZ]>6~DOP'-׹8ojVQЗzFyO9`TEtv,f[pXJ`@8me@[-Azuj \`]9 PwH?Na\ gg2mkNaM޸iaݪ6s&&8kSE^O<4Wjсvp!@ 감.:Bx.z9*s i&MHRxk[|Xi`];}}gk#\Dҋ@Vozbo4ڥQl 2h3& @Rlx,TSPz@n9d$u3cmcuALl - %@?1k@2PLjrsR:5 a  @}'0#[Pg@uI(t8&*qDnxɼS,3ew.{{H8>)).ʾM+D Jha=X{U<ۡ^f$'CX0o5< b$ Y]b᳝@c] с gnV"e IУ 4nA}&Z"艵ѠT g!rkPkno~s/.YyZƱ7`X ;4?v, >C)bV?)ѾckgT8KdaU6i)7'kWR<Vf:mVպT>3S=csO7T7('5&kXҒ 8>(rAЃ Gp4*g9S^vkST%ǵF=SsxAPفA)Sxq5- 'ЎM ^b/DUjYJDa*f*➪n ܅n;sh֩YgGDOsPW!OC٢z݂oP늓`,Ü@D{p{ rP  pjUKTOcn58 0"&\t,uިhkqX{Dd'LT+3E,36HLuwmYp|>:VTBZ66"\y^xUТzjr (eߜl>;i»͇ %ggYVI/e%@?9$^}3\_-z^ޣG(9)s=\c zоX :P@~R.B;S8Kx0 v<F8-t;`*RI. 5̍* D嬡p0&gan- R-/Wogm!3Y&>X*_U> 3#?p3EpN;pw½=ȃ1BH4rBtVOI}[L򅜫:8QE@רnuGNṒKHxb9+VqNt74g~:&`y~JM6%dҵ`& F0ihqosvVu>sQSC^-LvKtA儰%PpQ8!U8"`jyҭAz=+eUau%)TmB]s`CӴr QVkCc\2d[5l'R ښQ]낼GҵCsMammF/c P@oQYc1zE/#gȃ9{@``˷A?TVwVAr=*z)uIG44!1:Ҷp9l~+F-Ud#YQ+ly`EV(j{LS(4uh`39VĊHUW55NKΓTgͅ\A: صjra;hq-e&c4I_tt#w;N0m@   OA)9XJ3lR 3ۀt'VS;p@88 ]:d#I^k7$xҹX5+QTsӵX)鄡BNRϒ+ PspsTT\= j%1nٛ)]} m.4W<{ccvA5 ua\øs>=pw>0p0~K *Z{w P. 58e V鉃JdtA]4x vP0][g5. -gd8Q4AtUƀ *I-xjsam$٨f c,9pgPU[kˮ3-+vA=̏\goە IDATШY,α1IC+7't70AÑ.~J ÁgT0-jZ>,i)#C:{FT}FVvgU cBp8 Uv[dA݁߁u=XkCW=> Z+Jy`[ߘ)9߹-\E#XnJbNA-V Nl`Ǧp؄ykmԏ;BZg!m=%B,~rDȩil w)ݚӇ'o =!+/'5zlᢖJjXb`]Q3IAi b]΁>YF' #^/ւ+#'< Q }UJit5e Hy5cT3@ߔ^V=H ΪYuvRalRBϔ*01hig*va} Y&ꨁ%m(]\bSCp%q e% o^?AowWDCAR<n!ĨgI۪hK~ᜲ5BF>DhD591r zFǀӁx8"/@_*1~#>[yE-IEJMR FMWp\{*waqֈǡ-dG[vqԐ^\bScyH%IȍL"2oXDjQCݿM"Jءʖ=g'}^}f _أ%gxใ; PfHUMA8ֆ͞PݓwG>jլ5F! i'۞iRH-[um/pn\3W>WreO$]cS#)Tn49)gr@?P[ ߂ݝV윏ٳbŚAv q:BpąJQM۪:̾ާ(%3]f$߬Z֐ =ᬷ<_r_}WSɍ, Ip 깾{j+Y#%=f]/ kilk4:8 #t6.P.Włd_Z.k;D• ԼH`,F9BR]kK,~jxpu'K?hPw >>PVw8p+mU006 $Hă0ô@[ba Z.'/x Sm<;""BK? ^~?}@>!cc``еC.db4JVr#v"Ԡ~9>ʩHle:T*x|*-Wj, e]1%£Ek1Xxԓ;!|,`fyU9_FV>]VXY\bCFA44/ ;x  e-5݄%Q\Ȁ`\hypBd}pڶ/*PJ4o$mbs{Cb+n^\|wl_wSyX` ða7sa~mŔ55 >m8Ѳ-6I\|DRǯ=e-ap&<>(@?dy46Ǥfzd! I]ρmAd>( ~w #ȫlls_@?=cqti{ knG鴬׈ c`$c } ƛQتg+ _fiu'F 3=Ʌ팠+ Qi*|ܿ_\9E7඄Z;p\ ʃmUrȰ ƠsV}R.҂EOڝio9떗6J T.R~3%XPuh[E_ S!\4mN}t?s$}LR(0"b12C]RԼYg`Ξ"S8,eHouhYnj π|JA$4-p;?|bo8vG qR+`*G>߁?ƯtWWuW{ÑP}焽wZᵄ}lEϙhmx!}VdWmG gJLz~lx"Xz٦:۬蜒^'h 5v;Y#\ף.A5oE٨ HRJ֘!9g`Ǎ" IGj?4.DA-VyLYP)~'x՜;`zX! 9}. e*6*T7?]7Bil(JBNnR5t]z9߃uͨ We8 5kƒBǿz9:8)5ʡ`rQQI6{TUu]QG-kmͥtƬ<ܓJ+αa Fbz<=\$0';B-sTiNgA·IQG HVp; DŦB%=x=*x ]?e+ʃ{C:dmdHDGF[}5\9r3NrSFdHtF@Q:Z`<ң3j=P G{I((irHʊ9i2r.arS#K$ 6DNSԽc:i>b5DO Fi7e u)*p/4f}%">).6$Z|I USǬ[CW؃ rs /5檣Oπ]{qFJu‹ciDwh3aaZ/Y![؇8 _q !n؞1"({ .@N5RFh(@z`NRhqoaV<2[qeuؒr״޽:'(E.r:q8Q=k;R!$t"x`8R1B4Od y؁lb+s73Vg ʸ֨:TR`@ ĥ] $OQ0_VڄB>uYh{q|q ka|]ڐ 'ş!Y/Z:MP=g\wA팭XUZLGۃ~T=[qH74܋ݏO$#X@ڸw ہ*b3_ Mi1u*\"a/SS ήJ`c;k܎= ^n L`T I4@?䈤>r RS֔91;ú/5{ b8SFI'A7f!yt@p3{^ ㇊{z G4AsTZo8B;ب907wxHkfY6tv}Cfdc>K'G.2m(Wڙ&&zҷiG.fU)1 ASusQC0y6sch.Z {VcE?!}#K[#Rmɰ,5Ad[z, jc1w G[=t|q;8B6w}Ž ByDVPV!9KKֹdk|hoTmo׀Q嘵6Qes@tsHam,nO L;Z27lTs2D71&I56D I{ + m/o eHjP/GϾul%8 3FhU%L 4&rEH{-߲?`p[NX)=fEDO ArV[Q;\X]BB{+{X(Ijھ ^ug $ZJ!|RZ?Vm68gZ|l-5p2JXmQʰLn=Bڻi)֘m3i$m ݀?[ŗ-{ 8'mC$O4.Y*{1>Yf5O.@W$H=i D3GG˅w}+\ܐ^_o5VؽLN_k:XUeTI݄@J06Gz$PKq5kAFƲpvڔkoQf))+87`1cnřpEIcp$]i |4 ּ77|i3ɞ7#9MF* CCNbߠzN[˴ xҭbmۙaˣp{] MBX=_WWW t,t߭f0'wg8G +EW=%$[`[HgE54]FU=h_ԄdyƅUƶoO/&/R>ˆKzù!]+rNW&P26 7;G>"AV!=-(\tWW~WnL^6_џp3PRwxB֮ɲbrQAfDSӢ9!P7M [m$ܜ}8!45@ 橮 bBQr~:hemDoYbdrP@hup䥢/g'8^F|fÅAX#SgDJVMk;TQU]9&XQOק0kj%Bz޿3uyzyېOd,7~7WOOkk/} `Y"}s;H[|RZ̽ѳ8 |P)wq>:)w{,Fs RutOl9&Rq3kha.7 AAvk,(T%)^hwrGQ88Y#IQ"zQՕX"6δyU);f2uJ,c{7|2bL|k_k_ZwMϽz75jqjoI/ͨlq Ry^̼w-m/}uMS Qr{bU4=6=.x = 8٩ƛFdsgRL7euPќ)]ZG-ugQ:s|$ΪYC_Q[Pgu]O8%@?1l,qS'*Pk[&3-:ypn:$)h3j'ZK*:TܞngfղZ7 !1W'gj>P xp ].GVgy{<)t;3NRep t:p"J̎s WZsۼg1Cek?f6s&cG'y 'c.zR'FcUӼ: sMe{ ZM:t:W$RuuEV0頄:pN)Mv<䕇_n|Vڐ2 >*iM6GCvЇn ]mtYa=3cs_I3zD2o+Lv[{2yRhӲVM*Yz2%B,̴m&[';9/L|y֗m!ay^ux{۪0}+Rc*h9r'OdPc!A\77T! Ҧ˲EYS1$ғ!X+87YSkgYѵ99Zak/Yu,~b["=!䞞+hF;j;epL<-™* f:ekn,VVs4Zؔgeu%P^5jln['zSdžKaN9cå7/دdu|Xb':jz5"To~A d;1Vߺ'FP/$ h׃QR[E-Z1_ȵyN )Y%Z /x-3ҧ3wMA-Ҝ3z#$ S"<[7B}[Bkb3*Q% #& UAL^|{L8--'鉝!SH/ mEF82\C 3\kx][i_yyeR+kelUlvު IDAT&6BtͲt]ڑyK{XjItTa@u^cuAr== 5#)]D|p69;, jDB *54߽*Y zSb0Z8ԲRq" j <;FY[`y p'ĪީןcE,(\6S5ۦA;*s"hY! yp֙:WhZ9УJiz!tO eCu_2`[l/+Zj:^\jд,)2nnf3nS.Β;Lr?tYJ6?J0g 퉂D[-,L:v*vx;l=EAcVɍ9J@RWd%-JTsa'"{7*dj썴P?g4{[){IO;sW[)vj7t,lDgKW<ѼC[=[L;3[GzKXd;e%D`VM_QX le~sNQlAƞ_2{=:팯\rZ~QANѺтtݲhtJKӋQbSCzܜu.5+}NM?,Z_svނتtzW< kE4뙎ut;(h]8XH p8aE*'JZCwkٯ_ mVw@<}NیIevK6x̍O[ްc kZUZAzAP;7ξr M"mQ6Nm@ m筗`AhNQ(g|_V_l߷\iD N :YIA4"q ZMY8WXPa,b#eMmE`X&旧ʯŭܐ}rTu\>kRS 5 {QX깁񩷮y'24h@ =%ZZS2oN``Q۝wְf؞LQy5z'cJ6 ${ABB =Z1 ͔sf/}qZ&l}bt4LRQf,jƱ_O7BڇI Unv:]퍵 jheC E :y6VA܃4^1˪v}P%9 Rz&$8W6,\hwHvIO$P ;RdsNAksY]jgکr}f,P.)纡]rs 1.6EWc]fB/\R&s#;fjΊ  6_se򰠞v䞏V{,}dΜVX*Vq* yhZ& X ʣ1rM|b#O0Ўj½=1^s+žx]QWUnL0QtR:7ZE+켄4/FU#&B}?̹iѨ2%v-a0f:-Lth(T#XS̸|ɉ5Rp[T|m/:=HbEGXӄ e` ®4PMsf@g;P- Ozꭳ5mF{ӲHl l@-AAZF6j:Y|jfmZa`n!%X;ۂ 05gC(pO53t9iMڄ+>*:VPxJ'4@?5IyW 1?t q+$fUzvy]餯 V=Ȑ6zv{cZԲvUQ:.Dب =(3j%"(5PԁsiTt)y2l26.h~Rcya  ]zn!<2Ζ=q `}"\i6="=6R8x# FAAY h1(eivS=#2z 4<$cp3vR l('@kt<#^g5j1 чNT=NЭ!)qQ9@?1KJM.w KO[߁smǞ1|a76Цa<1i*vZ DEn$(p@5ZzI9*bjAjNV=7eq4 ˳R đۀŸ=1@1:*d|B8"%ؕi$?Z@G~w??~\è6",|= S> 6Mi|mBFIq^ rLM7JYe*L'lg@VVLC dvP8xp+7#hW^s񛶿a)ܦu M3eo02Ux*mOHB< < v[[[ zn>y񏺼_"//^FѝwmAt3n93m0iv|ƙqdWk80 [ n-5 8laVXoZo^+Yq /D+pwr:A]#܃Bh@Tyl TH?6Jѝk뚊2UvxPpB<8V(WQ^A_y%Gx>!~ȅW^Oă }~A_|}ᙆK4OOo~3+=\_u]].mgs11&F`KDpĆ/ر4#" IÂFuO,s99=e.s<g9{s/5Zxƍ&?t)~~>;s|{K_s>TLiGAj16}Pv~Kpŭި!b v9{0nvykpxhmuC=Y1D׳1ZE*YLW*ٛuڱRJ^[zB s#=u>G>Npo kEΫfK;?3?xy??}+8|+_Ї>Ŀ~yoLxӄx*nX>+{pc/ #Cc1Ms-ær !vڕe-#j+g|ib|xk A*B|ssΝVż$NͼjHbQA )ml3<`.'LAʇQZ:دw}^PCcw!nS  |||^{^U_O}W>(tϊx*֏ Kl$0"ȓM>K+Z$qT A6 ԅfʄ{<;\s)_٣K·ןvp{`}M;CUts泴|3v6k{fwܢV3 +%-][(BY}2GB< 97`ou6Yޱ}> "|ӟ߾ͣGl^8c#0(R-znnY2+zoUly@oXW^+][%RmMοQi̐_O "!Ri9(E%Py̤bϖ(6 }G,r="Ӹ5֐rGt Ե9q,!VT enj xO/ CADy1j3s59!cn~}""&޶1!o|Opx1KwMiS־u^AsVLurn7")^r[&ވt~Zz{䘃9'kvb_:̂C#c{Ur_A5GjWg;\nn a8Pޱ'?ɏoMCRTIea,ݤy%U8smCjchVp%r%_+䖅m-W(褢svqnA a;DX΃5>?D0pd4aԳJDwi],ݓ7YnBAus̱]sMa}8;NCkB)gvr5Vbhs ?!AIRg )wљ,xǍªk Җm* [_sE`%@qUH}@iyI>hIQΚ|{N9؀S צ1YztmiCFW )BcMJ`n~!147qXgX -';?C?_s%:CS޻ %ΦTMԳt ˖ui0N;- -%@9jV=9w61UQn~%Z!jß L L"<FB { q14dqei|TeKK˒MJ/KQK`A{FĚY1Z{hepB^3gk QaC4Z3rM6ըh3w9FմĨCLUm4H= 5|Y91օNρU:^gEExRЦ} cQ:c P 7pD7mѭj6.3;bKKv~/CLzQ+|4H%9=٨geTmV );a[٣ԳP8VS힇9 2eH5Q@:Pڻ5p&M37%-/髓^ E>\V qON~E=Uг{K6Ѩ̣&Lˍv<t\㏂[ i%a \-=k!\lQPNs9 |=8q1Tob2dϤ;:$,?YX+jHFQיIArK%PHs>Gtgٱ?~!f[ 6aɇ*盞_i"laf%"ftإ3zh!Aۀ7cL[$glU ?]b#jlodHo@}Lt5 U.(gOH$tb w.jrq8A{iIE3[m{ÆvP*?a-jv_ /ЯlyP)V۷aUҒ7$(qc&h6Β7G1z Ήmm1 sVA !$;x΁ ͹Mݤy LV!y{ER4G~E9Z olU-ui7|Qvv+u>yM0H A}!y@:9Tځs֜V mPpN:{{E`1ӝ=m`[kQN!VF081#UͲ6%7Cţ٣> Cr w,0;G/lgK+ފ_lI1vk,PT/Aj%f HpN6G4 M`lntOI/lUUSoLQCxvXfɫMj;)FSAv| ?ڨO(QqQ9(EP5הdjXCoCsң2-d^F45PEYcq8rKgةylΊ<4fA"9[[7%{=869c^k8Um-;gkUZ+lWFr~S[--hl2qYt=79c+:aKA>,r~UE='P[@*jWMg\=~BYڴ4Bt EA+NӧV5&#>ݠ1W6YVgKM-9!%]މK)1p&6X9Y}!5Grti[ ?W\fOWm =ŌV%I%v7zX xkoVD۸$L =΃DZ0kYX)gC`&8k[z%j- ìlQYpW~52+ߟtޅsdA`ܪK9Nj=h``M3ٕ3 Z2 ަ,i>Zz~rgsUj6=[= c^4t}%V( eiVSevצNAh}S(49sJQ X!F0sg:N}SqVo#|+i#ZTTR,z !.No˽oկ,ي6{ pQC:U}j}ApVv%+h/U;-͹&*JoCE.689-n6t/V2Qfl :T\ odj9oN %{m-8"0sCVAXu`ts]WnM!}bq.i?1q=Գ}oy>9򁖺q:IPIϥr=}8KU7Ft8J9䃆~уf޽G)70I]P3 /hWAz'@ߤgI ([dGB5{r>Ilա{[AmRU@ ը\XEo v&=-lld 夡M9m?a=ki- o!f:_4?JAK5}W\99y&zggh%Yg [Ws "{ 4I)/2QU/kqO=W f{.|ݲFq '|tt G{gnziEr*RNcI(Х!|Z^22n|h]LMZ%δ`8[x>N!FE$Kku3<;&<=m|PvZa2p-ȵ"VZšJ=ۋYⴕ֎:n@?;PRK9m V=g8V39* 2* jԱJ9*eq8DRvgz[^4_ҵ55NIZ>F4{x ceꎝ?p=l|PmӵAA_)Zhy ظr*GUz#:V.nUxRu9%Ӆ)m> L뒒e9ZZN U l-zqKGMM[C.[ 7ixd@v'=1{wEGj0J@NU(ͥ'&sjl<\xS͜%spπg .]^F{Ch}g[ 圞ٓiBbmV,wq9S__cpyyZeIt2 nVg_gJg mA݁sphs8j59Vկƃ\t TF<#9!N`:r'y2]+q'jR)g ڐNCǁЀ%7، Dy)67sؤ ECfYZ_z@ v>c^Qx Н??} SzT̅YDۊYR7 JqDA8+Zԑu4fSΤ8|Դ BQ/0L f'!T}P5<ʵ) },OJw 9r#li;`e=pў#.UZe~*W=0w8!:w=/O|Z?|ooyI36KKqXPƇy*뚋2WͶa,08k;]srioM8F\(,VfZ8!%"tKƎ͑K2@]L/٤M+yȃ&ag{-&1ݵcE \DkCP): ⛝Y2uO'Wrt:KcJR7$u*,zhwSNTBy0gfO}SQ|zʎ\Aiի{[2pM7p@l_ShR{tIA䞒(^R1!nhko*GJ<_0=|} 1W贂 ->\7aUX o(Dp\ ~.OW`UY=ۣ!ސho(gކk{~ V5?+W${ww={K_** ]]g<+prr^Rm T1Uϱd_VZX#&ZQA`ez.=K'F (N4GxR&`t"&/p6D,T"݀^?ayn_VC9#8q'PgϥU)LK`^lOWV]w,~VY _?vTB9S_}S X4JRК`S7\(P\%'mTf gj +{ҲPp ɛc!LtS{UZOkqغO: S>BD@=0<'ͯ^ c|,+CYŊ0 dxF*Bt~HOUlHV]N.4p2I 'z^Nc Q 6A܇VR:Yjn??ۗg3. fc1V +[z)>GTD8Q w.ХZRҩpyb갈HߗjNi:dC3gensVjFA%M|ꓒ^uŘB4-!=:: +QGA^Lf%P\NP72P90.Sy \#ߜ++=1u`\ IDATV|'#xa!:<02d"S78d"VImkTtzX/Tϐp,D՜ dh/EQ{F#C!%+Y AWnE(hTӾ?ҝn:5ѩa?:8LU \ ܡo ț M *XCF31)IR gV# Sc  \$ޏҘ ׹I9/͂JAr PJڋm–p1o]L.jtAQ]7?PCQT7wfʇT$J#Qi$$sơgYlk Jz RdƠ޴F gYd9$y+p%\੃oAJOx\0A1p*B::::%ixB 0B\NTa>a{NCㅩ4xOHr/s!qRqZ=IpfG e;PGGXbM;TFzq4+k° MS??{,~.B;gr35@ F90ȆIKc5.%k`Ku/V O%IDŽp:6Gk*J=7R w,t2L{(>V}#Kare4v Ie ۨ9pD@WIu|r\XU|d@QKG9wpp $W&&%)ĔqO1'xiR.A*x Yl<(OڧK[8gA6868plC !)j[3մs X)ޛ7$ VI[0h(iUbT*:kJ('@߹xW&|JicK]1NwDE$mUBV-;r]9R"4{ѳ.D(0-G8G'ab҉ 6}u\ pO 8 zEIoȊ 9UrecCJs/A+[0>ىpLV8FV8V8Y!i'd6O0Ԫ:ڹhq"a&oZRTt^Q7*#Q9k֭=g'xW.ԸZ`됽22 z:q5'#"#qѣĸg-)I-JZ*Zf*ڀo7v "9lqZI w.EA׽tB. =C}xNĔ {rw Jq4eG vPטQiQ )6P YS+-a?=}*>!s{#G>yi\`}l݀VB콊N94w-#5ɵ}$+i`۪mBO6<$[BpJQ:)u.8%1a*q]IVJ,hJ^1;iʼ4s ھYLv'z}2lJG#o+:])^\gZk_H 0 l2J̱]fN8ro#UL<%;fL\"<xyB_Y!$ wpsA6 k!Κ|g{cƩTiNyZpһ`/iwhA=wvl%zɆqN2rz6/~ZV̶ǬR1.>튶'o[îwRu9%ЭMsm zR)@z\FE'`)>}gРܵHլѲڦV1ŭ a%oz"lzT1@}Asз~OؽF S!b!ldEHzk+Y Tpxթ3e:Jh21~έrGS9%ܐv8TMț4an_qaշA0O 9%~7Ca1:iNAͪƄxhҪPB\/Ki>F; F>yrs^Oz+~(2-ӎӁmT{#>ocu6Ir%GeZS݌jnZ%_Nݞ9(" [*3~K<|߷'Cp sd؀lhcRө2MCś6936; վmLRǍp/ z#T' :CZ=c `u"|gzjs&6v]8K:=TR9e H!qД_8&+taЃ~z[\p. *be`6)K*RH<1qW*ԓ&TQc\z~yX=}0 h9 Cn:FX+A"1A]L}iS(Ju\2 +I`V.@z-Q6br7^7X@W)qߤ~Yo{<=Oq;_]F .'@߹ (rBbO#W 2L~`xr2C %UNߎ˽ Z$&tK3}f#!9/A _=px2 _CV 0\{} D#^!F`^k2h{Ϟ 5Q&k#Awl}WbS謦o f?Hi*],YfZ[C9u Щ}tlt nA9pxn/x=ׯؽX}g0\ U˱E`Vs.iSw&]XʐsZr3'an-Zqg0\z_^R ~ *w Cn}IM˄"VFS[BExq3D>+&#cavAUGX'Dr ylSI3ӌbxGDD)gn0V,$z9S8sEρ A._(rzS6gn#[7hdļ!=#:A85ˢzNO1`Kcv!4t>iɎXL۵UiRvX9~{Y6uT>5Mmc,Kxs)'@ߵL֐78S }='>K;e`*.aݱƱ*Z[lI .W>!]6*-p m7s "p, 9k18$*Z"EBeys0cd815ҭ 䍽B^7Xªidfu),RgoC3He:u*ެ=r-Ou9Eݐ9gX)<' }F qgC*e/zp 1!ᰁ;}۹8^t2 !3ZAԴl4lد6AYB(RMȦRq"2ІEHgC?DHCAU^8(` z2a夢:;rz0az)>mEa ' w-#C}-!C.}%ۤ,3)= 7D^l͛C$?8nc]T^%AsͱҪ)uJI{0ؽv RxDX֡eHG;_Y}.Em]E򭎉= 0$߼9& t'rK!VUןe(cm+˥ePaq☗Xd \t[4W굃kkEB؈)5w-$1-P 9g@9 ԀN`FI}4#b9"SO'̡bgHȂV_2jEc"/]H@R) W(m޹{`A9sOnmhPz,,UюAJ=i g ^ ƏVYm Ӂ0ug@_j}7`K9ENЭ6BzylpDsNsA81GP1>y2M~ Arxfnl k؊ESYF=/z̗YO w-:n"[Н%t{veM(*|Q!CPѣm,#.ž6*بRAdj>t bt39ɾZ6kB0ԕ}5 %+8CDsNև8 f\,F95źdVY-װ.f, zݙVG V-z^nrBt)'@߱#w;y4N`IYKeKPc`3\v.stC!tWj]cARo'q\<~` !-AI /:8U`NPe ^ I=7L$۰RgV Ү>ú 4j?gMkK]]y9%Z=[R=ɏ&IU(i赺p!Z)"JFfì?U YY|hj"ZsGY&i}5UJV&/zES6Oŭ/'JOUxSTmNF 垂E;*f۫VY6`UG* ;٘6KTVw"]qc{p5@b3f㤰du(՝hBU{ϭ:rTT"ُ>d#]h 6tl5qkQScN/YfYtmřstDI08IY9C0}ҫ$e ~Ea{SN~[% П䮓4L(Fq(Fe@j+4*:=HpM򠙫f 3,S1ܫ5ßu lًN YBit)rBma p˪9/zY3m^B=89qjY+pa/ |ftma/Ʈ}aYg{~4Ϳ;6TB9%(h첵.TxӬU\S'UI9CD\r=84j,ɷwE4Ftn$8GՓO[#9昴tsW,3<<족09D=9pk{;!m,zҭRVGGKR )\HPfh ^zue ѩ}o&_g>S-siLFWd̵Xt3:8CBІ>m?P7ҁsڃ X i:͡ AeE"3* -C9>/|Z.dVfʵ>l/Fs@ ̷FZ UtKiYXX^U %xI-gyaL m|UV`fu$X'5* oR̕!և}9Iq{.1T̖U̘$v#itS1X޵^VBp;ӋRCcw0|㛼Oo2OvJ(z@ʫʫ  g!/~)E YH7ipn!JS nnZYٗx TQmYn`mŸty\̭1/]r ztzZlk;I>g-pu4GޚʲJi*; km2R:K_'a}%9ϧ̩r ӟl3:B7e啷}Ks#!ͽoߤ[nVi3Uح4VGg#@n?GwT ZF9w+/ھ/.eKinLɑ@ksސc* m;) ai=RX vk&g<;tAQT`K֧joҡHIϦg'@2;| +iCё^ B1Ѝѵ>^uӉ\k\Ee9=F9zqlfwMaK[Y=Pw=zY!u ө}2L㼸[5ȸ捱zU&-IZsOIdy巓5KH w>PVՆ<[fw!ȇSa}s8$,KK]i8d:.JT}a2n\evs~S)Q\Rd0Ky66俷oxgү6.ʟUV_1X ,9;}q 4=r̕үw5"d%S4?*'@߱װ˴]f Q7o'AB*6wEիq 鲿mb:@ݠX׾R>颸,}z ɇnO-Ŗ?6WΕ7]MG5=°QՓZU||CEa//A\'Dr(:8& Ω3=Q-qQ%MJ[slڨF[Ch瓊͓FuF4@z+hЋg36EW6Eww†-omlcҰmo&̟J('@߱}@D%}+|״_~L/9--?#`r9}01?: B <&tWM7=W87Yo:[SOEw<j+ZM 9KE.聸,f;-軖4];_svt{[(w* 4V)VY;iJ{p|m̔2-[X Ist(r0}T9Kpx>t{ILcwy3֟p>PNcIK]#r$p4Ѵ!ܪ0ʹ6Zq[eԒamzёB^lQutbܙjf ?w[ C`1zn6xݩr=Ꙛ,|7hPho֞6˜nAG篱Cҵl+ K$G#LVAi54ډ,[ȳF+畒o mpA?ݏy6GQZj7;z0W\;.ũ o"78^Tm>q~ڏloZw%ݨن|yްp*[+rxlea !}q#K ~5-{ z3S}8Xg'sWn}Az^Nc6XVO\ 'BSbAZ6y,Jƪjt+ 'BrxHjЍ ]feDNw6!Utas &J,\ *"ZIt!*HePr E6HۦjiBn7XҼ;g|ͽ[d3g;3ys=y 9x+ ܪHׄW. 2d:>;PYVoT}cxflضBXsj}KQֽКְc[DmDZ+LKYGm]YJcfl7,9ͨ_Y:$)6=j~7ϓdL-l-,v-)C>6왘3$2ØZ'1.hע쓀- GK9AݐOTr^2SNǒ8tPɡEnX)0UA iOm,)G"fȞ:9d0j=ay;0g(vzktt-z/ú˚anubk{.:C=CbLsj "*3ZTrK ek5l& j (cX+P՜7s,fn!"OU&h[-sHձ҈Gs-#lb̖{v:zIí'ӂ\zu'OR<i}3b`k"mE LAq_a˙A5kƍ7066z سgOH }lZB2 AU~088-[`ppEEEaKI{{; pѰ䤻LwQZZ9 }IA***p֭eߏ͛7ҳ忐dp!bɒ%8w\ؒz*N:rb1tvv-)/}}}x1–2!&(%!ADD!&(dĬ[nE}}=1>>nl3<<ӧO[LNNnӐAс2>>sm .k...|Eʕ+ sll,Bgacsw}6 &..{SO=f3!ѣNVB'(Ə/{qI }ѷo_1dȐGߠA'X̙3`39+zΎXXD>`PPA#P}d}l"88 6j-AArԼ|90vcWidjk %t…`uqͨ欚/_Y&7;‰д~MNqUm@ev*& U[jsfW;7̘ݻk?8ԾЧAh(xz[VQrm$ G5g|A='u\;/8C&{|4k&+%&:Cm$ G5g|A=gkB в%DEA~rR%'>X`|)l(!3nۖsKP2@IBQY5_PaX9>rJgP4@IBQY5_P…H ރD3UK#KlF\wߕ~vYF)#I=9 j9_}q. +Wʅ#%EG/1QοNe3G$՜Uu/;p z1ƻ}vml&gO8uJYCm$ G5g|ABirгg2emQQЭ> -Z@h(uooge %$՜U};'&ʢ;,ZS,XdҧvuݾYEm$ G5g|A7nV3r+PYO]Ξ{YӬ+_;19Jɠ欚/It.2RW(ZT ߄4ܹrC7(96ڣj?͛eP5 :ݸQi8QVc6 A:$$>}н{w ~=00>}0Jh#I=9 8o*7ݹ#sp%Ŏf߀9b,)X'Fm$ G5g|˗˂Gۄ f76>X۵K9 *Q2@IBQY5_pԩᇲ?&KC͚嚾y *($欚/8Yk|8W.ذAnFт'&'Ð!\px-9($欚/d9-M.G(Xv+6Ȿh 7/,[&8y bx%$՜U9'&Bǎr&dI9@^MxlLՓge5m*hB#+'FuFP{TsVw{W&J`dkGL"O8qϘO>0iM0ڣj`krx9{Ng~zukքGa ]gPOykBÆPpuKnEܾ]nM1CpqSO倀־Ǯ>v\\?F7MN0%I܎欚/Z\!Zlŋ !zޫ  Bxz B̚Cz͚bٲ`9uh`nĭ[OGoIӺuk=PHʕ+(S /_p$՜Uk0>۷CZg,hdWħί9&"QvEo.O(;t֭[9z(*U"""(UT{' u0~G˵:u|=/_ eP-9 y͚t&X,[&w jC僅 ,굍9ϧ[?emSF8 +]d Ddڵkl8s挳lF5g|!݅X6>pF! ='ą 6ݮ6NLM ^#gV;/B竷9h%; G5g|g͂Ϛח"]:U} zkoӭrݽl4_4/w/@9h{0ڣJ'çg06h/^_`Ay&֔)vK_L_:׸pW|}OmoӃ37;(96vjjΪ ~ sƍuhB[VǭZnTs*Mㇽ?@ezoT^پ@; UC5g Ç'ܐҰFII]N28*w f3xo^jͫW"Ŝ7tӏ Π> NBQYÆȑrĎ&/BÆ0g-* ~3fM>#ܔQi^9'dL1x$՜;v,  ΝUy6YK]Y@z xi=>'l13\-11SN坪ŪQzYE$՜;uji,.k28N 9Ƈڟ86HX0ޭn3O؂#h#I=9w\|c-Gq\r3Zk1}a>AIBQY۶o#~9D6;߹#+m(ʁ ic! ~zh*>>h5#=848>DvQrm$ G5ggY eӱ AsRE&+Vnߖ~캸 ;3剔[z>A$T ՜{&%УG˲ʕrŋrX~PgM&=Tg]cGYafP2@IBQYǎAaߛsj<׹3$'Ï?ʃ\͞ƿ?UeѸ3xN>A40̈j}JNqIBQ+r)a0dm?My^(TV~r–6mpv1i)PF+GP[C$՜s7, Zy/:[yP εka3dS)?ʳ+(oƯPrm$ G5pZ[?6@NǪ))0o܊2kݗvoK?¢t&3špj}JhhR9|/_5e 3<䜜,'ϗ;\fΔއkzu>9N0,-lN+f@>l %8$ׯC!͟%WsCb{7ﯫ q%釦SiV%VZEɼ%_yӃ3ׇHjjZFE9r7=vk%#`lA܇7O ?gK&P[é#=zЭ[7F~=<l ' Ldb-Xϟ /^?[˵HݸWmӮF:&6og|.acZJ`?@h?kcඁ[CQճ*?7͈NٳgǏɓAO!B˗?вeKܨQJLJ˗c6)[l}vʒ%Kl?@Jn 5kE e˺AZi:!Xuj7q-ѳnO\9-BlرcV՜囚*DǎB+ qw ɇm+D\Bm|ilI3#wCO'ao.]/ t1m+FP{Tsv,[N k&D7v,/ZӡΎ݋]Ֆ퉌*o?/}#wk %8ڣB_E\B6Dn܀7ހ#G\97\١%9- L`쁱$%QPfū^}}+}BO(96vjj) ;Kɓ#G?|;. @hL3 =HjjN 8۷%uvy3. ,/'ޒm|5*b5КgRP,?O %GFP{Tsw,yJܰe <,<7dp5 .48lTMokNTR{=lSp~#Jh#I=9`|6 /iifg<\SC6>y:IJKb C8 +~O%8$U+ WY.bbaXzY.j[ kKBROT)Z%[ =HjjY]tEivq4j$sj2hcpǷbfΑ9TU%!K(S헳˞lgo HjjΙn 'XABvV2gףG>vWWϨf(]a_*HjjOݵ :v,.Vs"QQHM6xRsQꗬϑGzC3*($8dr{w;.\׹3g_N mF>JNqIBQٚ#a$fdT_ uFmSNws_G{o1>E8 }B5AIBQaߐ9E/w ~uKNiZ%s< q|J<_Zsk?r?5@,|c*Hjj2ܻ'lsҢE ŋ~}߾}<̙3e>2Eb$ G2w4i&Em֮^gOغ5G܌3ghQ'dL1 Π>0ZC$ݻwׯO|ŋyr <3\|9$91QJ%ʿ&YB7N"O4ȎastXJ)WvշќOX߸qT>4K6mڔ .Ef)S`20`@RJdcR2s `ݺuOOZppn\TwNN- ʕXD޼bŊ̟Lo+&1wгnO?Kquq}NQ7-&ѺG=KyTJ *QIOF$aqwwg$$$Pzu; *IBыzSPJq.\{] 9lb;ɱ ?gbfj͜6sh k:FU_!VH{~wʎ)ӽM߉YMz={:ujH744a9,\(\};Ԯ6ld=öY'^8`ӹMkϴV(R_ל`&bT\F rWM)T k(96 iU>>4F < }{M&{"MsrZ2c*l:r˱ͬg]zBpk-&H\=])?gZUfɳuUzM¥o/q}uf*L@ЃovQrHjON9X!+úuOsy{jk %GFP{v޸_yrY&,] -[;w((^ć5>Լj"|S12"* jSȦJh#I=Z9HI˕ty›?y<_yO\ps}l4s9ZW\wHN- {Ji50ڣr'vR̘!|,Wׯl:l、{|S{{fks,8zBK{8Vz#v*%>.APRvgP}HjL0q"||옌׮3ʊ+|LIk1uzfW}TZ&'q D 0yf_#h#I=t>v Z'q_|7[ܽ,ƑCfN|is>n&ܤK.z;%8z‘iqi\+&jm^^T^YZk9$8zkG^9KcxNP!yw=c71aMŐCHwD}\0'W\vQ;X<{[lQrHj#Owe_ȑycr2˖B+W)l ! `ඁ\L,$pb쨲xvDSFP{|ܲ%'L+E }}þ^U\L*8 7\7 !6Gk%0“(zaԣʚgP}+W6lNiӦ M4r 0 5#I=q>qB_?>1pY. J7)- L`$P_+3?TpqEb˂Fr9vjk }}}Yh#O\\\ȟ??<)FP{uep391yVYS#<~7̦  #$On3/p:SNqqbSՇjQ@=rJIUVVfѲeK~MoÇ(P@19>EӅpuo><[1[%` w.<IHg{\=K_'{s 3Օ󓚚~-""XnaaaL&zf2t㢕s`-޽`nHL|}z vs+ {]L6SjWTRRvQ~}W&՞DqNo\;xn\rd2Y}݇9yTXCp< z`l{ɶ:Ztttwqzk/5rړ]rrbau…л+n7۶Uz[rQ\]\j6ZX/$_K$K& %z*sD}Jhc'|lp~ѫ鬉aYOͽ+.M]%0۾I=֜7l'bsmIXQFg~[軹/#qrFF7gDžW=&2>ɝOU g8LJsen%@W /ZvjP2@$Tm>,22ÇMە+eMt޽P 4ksSw`?#)*fӢ\l9lIk4Wg^%ǍKR_Ire-ƪZCm$ g?իc^ U*)R>:^#U1%xjm5$aRB= ֮}(8/[/(srg`&92&i ]Jopi6 j}pi[ns;%SBZgY+_-QJ$6X,rߴi7o6lx`"- R*9s S2rHL&) 3Z͠mwWQBssMnI-Y-%d䪐jPrbP臘B׮2)[ …a|kr… 6߫;Qn{hXV"2W"W. 礚SCEq#%&CW K6NK1DKSN=sbAqa'bccB;Vܾ}[$''nݺ !?8sHII۶mB_$,.^(iii3':w,"##ӯ-(_ug+ıc,&jsBDEBj8WW!&N|TAD#n?A"Am$lXDxc~18=gwvϝ7nfY{B!~7/"000G||Eܹ QE.]B[|R;v< Ⓧo8qD0ŝ?[*(= a?DX0)Z%5k! SNB1qD*fSK&>}Z 7߈~2[lQrIB=h/xv :tP'dpLU{F(W-koS$w&@Z]puqNZComBCTlÝmwH_穓"mPmaC\\;voqqUFӗ~a cQBORr̛7^xJ*9S1S *& h!x5{WV7WC2cDr#t%\Uc[PB9<"H8@bpo=_;Oi2ޮnSm SxwӧJ*^;2`y+mڴɱAm0<3L43gΰbŊ׺wD3 ۷ ;҄KyE7$ň[ \#./BLiށ{"b\8 ? {\#u-DZ|Z &f B!f3%ٴi([pB-(9Vq' |\W;~r>;s#3z덛mWiX 'O©BH8@Dە/ o|TS!=III,\~QLi޼9}m<oƥKx72e Dw\!@Mg|+W6lN- z3׵kW,Yö2o#̟''Oz/BjF  ߖ~쾴j|ė'R> ҥKON޼yqqqUɭ N!>>D8/g-8uˢEhݺug嫯bܸq۷&Mn$ Æ1 VA.!)IV_7Ù>}#{kY6mPlYzIÆ ={v '$X,,[!C0c ¦Gt9q|}}xg|r׍$a$%Anr"~X7H}aR0As~ l<[q!%r3h>{3<"M|-d"HNk&-. ss4},is0ݼy3mڴ!>> 0`N @Q =& _N8tGMz]TT)"""TR^ߟ֭[@XXXzmUr/G?7:>իd0~D ^.%쩧0m_~I?[\wזƛ$",2tIDAT;˿ѿv<<5s>s Olf;oF **s 7pqyz W/;RSSIMMݝw}kMZZ7nP*馇$ajj*gϞZj׮^Jqs˘WosN F }&wGK%`,:j|3NoϹrbCݽbN4{(?bӃ+|O|pOP.]ĉ |U;w2h nܸs(Tk[t9FQ-3RSqڼ\Q6m ث|sUVl= ]a|/{(_2!O<鿼yX/^^z+bX^z93;tPƏ@ӦM4@־V nTi׮l̙3=bbpMyW 'ؼ$dŹ)} sbbSNB }{9\w:ApLX/LTBCv aqbiODէf\vmkѿFc: )R 4|8d^ct@@>xt}cbb0aӦMd2aX;wnnQ}"r+ʁrݺB^^ƍzU-f1\Qp|ASKCf%"+ 8'>a|aqi%?7Bb;v"...}m`/^K|9آ9Ip6tlªCx|qP9cNwa{_= .{wϴ$Y.QFq{mRSI" oo5GE)ҾgQɄP||<'N~`>}:uP^=ZѾfwRHʖ-ҥKy`5 ; W.] %F~woO(T-^F|3EXxfuȳZy{򛞋 _)HLjW l{9kҥK\z_|dnܸQiii3vXJ*Ŷm_־P2@ϟ 6Nb6wr ^nj+bJJEAk1O|HŹn.ɍE7H8%ѹxP]v,J6(-_gĈ ,Hɒ%4h 4`ܸqٮZp^x!8Z"Edjk %w$;w|܃毵sh !nѭV7?Kz҃%BhN?EA\|S 䩕 +Z#ZbKqvZ3OOO͛Cwqq7ޠUVYJ .l7|\q],7+F9:ĔHQ'^,b 7ݔِ/}PJcwƌ5q#/tsZEӺ[6QGi&wFDM9͕2 @Vfƌՙ_|Azl{HIdªSTTi޼9 +ڵ3gPXXHBB.Ãx^lք23[OICxmޟeZηo,~>"VtZSؿbOҪ$z~;_o^oګ`IoXX.A}'S4Qwǃyֳo 4F5);;hhi8-pªoHݻw}6͛7cm۶]v.\޽{>vX9v]"##嘛;v㡡ܽ{W{zzʱ Ξ=+:wL.]YO!ǧO.9ysww/8qt9#8vٳgFVV7o߾_֭[,ӧ}:t9xb9X0`߷or|rʱ^zݻILL֭cnb׮]rW^aȐ!r|֭$$$ȟ?g֭raÆ1l09>c N|8C [CMG5feeqY&NHFFׯ_4V"j1Ì7ɓ'3k,qvvF`ggGnn.$?y}SF&Mx# ^F!*Ў!T>4i'No߾A ӰaC81cXzj,5a^c528::BJJqTTر҈Y; % m5ݿbWK$͟ g?3`>__333z-Ξ=KJJ |  0Yqe’͛Z MFII F9).PrB5>&-NNN$%%˗ʊuZ;;rk/tsQ97J/5--,In;f#:}ypW67i֢$e%ѽ{wv;w3g&>>?GeJiUmk׮%44 ڷo`e˖X[[+B_mPڴu]1ZjV6\ѣGٸq#( :ooo7nLÆ iݺ5NNNDII ,[\?%.q_2]Y+ċ{q`kkә5kV%'^I( `ĉXXXrJy(SoMMӠWi&*A7d $i )b%ou68oHrY^{ڦMO?-w◒駟L-A&22R$IxbŊ*FIzk4? z::@)&a_n'o08Thͩʯh5ZN5PT0XܹСC%++6?BQ; e]7>dKPAd3e~?_equ{h,/^$++ 777oߎ``ʕ|q#Uhc%%gQ {_ERECPvd2vXxV[PYQߚSSS 8s"k|TYa&\ӱ[̑A*xt ::G˝PYQ_ٷoaaatڕSE@קIh0gA|u*|x)8icѣ#}O5ۛ<|}}(w"r\GL[),~a |L`chޠ9{?˵_~dȈ!5*W ԥ撒g///BCCfu=@5>,umJt̻x{g[esg4ϰl2>ZǬF.4'''sq(((ӇQFՁRj,I[r;-ܥff a&M:QvΞ%I%%%bԲQVoU$̼+g_%\tv/pegѬx}$ѴiS6l؀VeϞ=ѩOKMk|TYI($L_^s 8iX@r:TZ͊G|m ]v̜9ƍ׋<9VBQe~\WK}ygx̹ɌU3VCѬI`Wa,]|||hԨ`5Obk|TY$.^=a$'SO>CXX֓RhVT9//7o/&-- +++c$XGQv,N.l_鸙wtY\]QoqGSEeH)d< 9V:BQeIx s}3Mhs˻Ƅ2PYQ0YD*_Aュe-jαZz* 2 %s`@ワJFaM_jU>3K_Ī6BӮ];LfI={6ׯ_G2gSKr ,ULl$4u63NU1j1+bcc1 j*Z-'O&##6m0bSKaԦY5>,M{roMiœ^ˤ&RJ6+$IDDD|'?)% %:ԦY5>,/ݵ+$SH!CC4/n3tFU(Ѭvh4:DQQgqF{tPf@t:^uf͚n0ǧR$]7Djq۱kvNս19rI뉍+8;;zf͚1p@izI Ç7n۷o'++K~KA۶mٶmDDDwb=p)*vV7Ο?6ŏQ#͹ I 88֭W\QF^N:UX izI tjj*杋 )))[l)#DG'63 2 'Nѣlذ{{{Ν;Ve̘1L2AТEj14%j ,$I1@WS<<00KKK^{5yŅpߟ~!ԩ=P:m+lk4M/O7;;lrrr|r}K5&-:ooo7nLÆ iݺ5NNN 6 (,,dΝ'&Ť&t:^^^4j{{{Rq̙SRR^DFnnn̝;JKIMMeŊ\vK.Jqugr!iݺ5˖-*5111رBeףZP25MIu5 vvv`bȞ={*TrӬڵv:J/۶mcϞ=|wr{uG&)N QQQcǎ:QrC9ZP~+Uz~>|8}۪{=Eh'''ҵe~=11'''iHuj)%&M6M (9U-C0a~-/_&77zTRkf"VƆ JJJpuuLNcBT |}}U@DgnܸAׯ~=zD4vX5k-\:u҃eٱc45|_{{{@z6*V;qDTѣzQѣGKjժV*`9755UTʆ>f|U"ay "}+hBзưP(@DHIIuԂ>f |U!"- &M¡C!3R)쌠 }0b #h\odV֜e2RSS4}o`q7kHIINfY5_U0---NNNV֜ F|mԃ>f |UdNNNַF[AcXsc.bk`2@[[[[A#\\\190`Y5_U0"a"!+)%XUZ(֜Kq,* BP\>f |Ud5g???4}- uk...HLLԪUK6bk`2@ EBÚL&CBBvzQ%%9Η}c#a2@ EBÚstt4  >f u|a`LhH{XsvttDbb"j֬ }k}_KCP),X%ޯ/ BP| 1/) q>è:6֪,Kk +b5:u`' Ǭfe"5 i>i7mFz2,&4EBNa9** [>fW@Ԫ(l T^Xtзb05`lhEx7DCl*{{Ў 0:5gCCUf)@,fdC<&ĆgU #hH{Xs VfY%9!fs 4{;g-ϷD?3o>+WU-Zmۢk׮7n\3BP,sc 4k}w{s 4P }R[Tecڥ*۴i={[p],_~g"a˗ Ь1_}Rb `{ j$b:8}DΝ u^^^_|" EBÚsll,4k}7_"B tq`T9m`܌wzĈt|}}!J|Դ|222OOO:u R>?WƗkNNNq:'%%A$!99Y.^7\ԹY ;/""1V1#ZA$!$$ 6T=xzzbӦMHKKQŋ XXX`ԨQ իW={bԩ :Νӗ>.,9LMMaaa$} K} WDԺ(D̚a,UI&СCZ8zo(_RRRPzul=ҷxs g#+" *b-76k/آ"ay%瘘@4Xc@99&~CtGSڙk ^5E(]sRK ]/q>=abc槛_- { &GJBÒ3>*7a\Ð6,WL%gVS,1P9t9aLJ̀E' mMgU#ha%aə4K} ֗g}\Zƨ;.DbQdUd%gV4K} 7+" nxs h kW]WL8"a9?|>S"jmx7ߠC5iV ׿`r- u+ W{2*X|ᗁ)J!6n.hƌ*A EBÊs||< Woaц"K狞ïRXvDGaV3^P$=875kgaoTN EVx &eeZ4EB`9?Xn]=h+}Oy}r C@dg\,8* BP V~E+}Oy|/rg퉃m[´A++ k &SBP3@׮]l9q>ó!hg`5+>;C]X_U09p@NNM4>G_"BG";G3F-|̹R3^P$=8?{ 4hU4>Χ,ߜ9俸TxCcZ'ֿ̰`r- u 2 /_-sFMID_p>JF&Uzk8u[p4_RCdϟ6mʄﻰ7Y{"0( 4}âۿ>>h-yHsLqEBÂs~ޞ wam_b/R¬uE =ML‚k p(xJ &GBP_ g]Xs>¯"GvhێW(JNG 8Zf۰plX6L"a4 šsmb D Zq#̚[M%aC̼0@fwսVJedf ⶇ,8Y}R"HqU1lln!2Jvfb`7:`=hW-KG)̜9SLe d2;Xxq"a9$$hԨ‚3)Cz^Vl:8\NGz VV;x/N yݦMٳзo߂'Na0zh"::fBP955qqqprr }Uw笈,<w!6^ܨYghEuzQ7LƆ>PӬGEӧOcܹsXlmm v,G(;7o3!8Et3G;vHDpJ^7ne`*8<#FK T ;3** U0Ь,xxxN?1=5޸Wކ/~\[p}CHVۡ*يwҮ~'4 ?Lbsa?4RĦM>!"^^^x"rssabb 5 M4aeesss_sǏrR1(;ϝ;۷oF{_U9$!/9UّfX8uoo3̹4]i>}{ڙ4i:tѿ_;zhϱX${] pvv_UY*G[xs0jP>M<}cz(r`]vO> ۰b09N(;а w_U9Z B& '6&Mx>>os)\bG1|oy{<EBg甔ǣiӦ06涰oIY!S p DNljۗqLZ >=)1)0 Ƿ"09V>;?~@ ߾%/"P ajUsš^kJ Ļ09ŷoIT3!nW"2[ YoPžmUf+ ݋%ח -' u[0D-7:WP$=|uFpp0֭ڵk\oi9M!|N8HAhl[ T^yw%7df`nZ|vpVL"ǏP(7.n!`J*ppy; >~=~~3F:m^/sϞ&&\LY,_շ4tL B(@N 7}_ g@w}$%NG{իT3ŧ(7* 18 ΃AAwߕtZ(:mWx^,yf0/ʺG `wLk ^^ctbTE O|sr5kf̀3g;;YyI }`2! u_@ǎ\oih͕7xS%O8ìvO:ѦoFNXlhS ރm>g\:c2`"J#hH{蜙G~G߲І2O狟QGKCrEЎ/D 8r–{[`flZ py@` gP$=|tRćAoYT9;*#n: , F"T7,9 /ƵZO}B]+JN\U,غ@ bM|tw |-8'IBPS0`ΨX#dX?\8pAQt`  pT56./{?FSBPѹG߲(2[pp~ΙW"i&GBPУG_盯:㬐*W_bKm!2aY_\싳:Xu1 |-ܟv:Rwps֮վfEa2@ EB74|ա,gY O?,XzpV=*|31<{r ЯI?Mj_"7زXKg4h>X:MI~ۂC~02ҾrE`2! uߜo޼ H]:|ա4! ~}@{g\)Ƕ{ǞC}81.|XOr˶UK_8ti.ؽ7+W" Ƙ8q*H@[ַQʕ$$%I)W[wP= 4kgbbF&RD})Ν :(1|-zAߘ>}:&OիW\D1sLl߾sBP9?ѽ{ᓯ&>FԪ(řh^ͪkkLk:@tm3FT|C"?89'N66\ˋOj*һ];m[5kjW[5ݻwoЧO,] `ii Tz*6O׮q+zU=|UR<ϳQYU8USW~Cߝ}& jV 'hG7W Ëq N_8rXHLf u)жmۊ]W(ԧOJE7ԴBff4/J֭KZ}|Մ|W"*$|Byyz6+_}C]D3Ϥ77X1c s};qn&uRD ?#8a͐dꫯ}M,yyyE?ĩS!!!j×kѼqaɓG˖-ao]}/_Us⹋x3x,[?6Flݛ{y.ڭm{/qstFBTv?c֬ dV<=k /o~sX ժشi+H##G=ٳi߾}tEӧӔ)ShժUŞrc-[oC~H XЛk:RIG:A,i$WuW5k s .$иaZv$kͷ‹ 2D C}+h _H֭[_uHJݦ}G|)+2KJ'G>"pfxED:0C s{]3^WZo(233Ԕ,--)77W:FTRXat$OIзIs"2ZiDp5՜#ua))DqΎ?!}X5զ W[lVVUnב? \|- E+Dp DD8zs/EtZ4̰̌Z4FE}Pp~HJUV~5`j71 %w8+`h%_"ayV>8?0dȐ2oIdGeÿ?^zzh{-ͨz=OydžbpDEcH`~ł3P>H.~ L q4 Ώݻ&py$ 4g֐ڐ!JlllH$QRRuMd! $ݏr^[i单dڔnO/""/LwB[RSkuk"-09V}; 66~!jԨQ}"Bh<yyqm{|% Zie7 <F8 -n9(FFMr"Um\ t%_dZXI{|aԺ_߾o)2)I' "~G[}2%'OĎ;ФzPWv"Z?T+!ׯ|å5D".~=Pxwϗ0"ѷӧÇW~}'J2`.;Dg̻2l,Og?f˵F\C=nN sj*0>мB IDAT9쀓'oo3#x'* #hLBݣO#~F}|>C!UpI]9'f&bᵅ8pöv jT6nrr6l>\x_Wh^ɾ Z(}:{xx>Sї/!vk, V5oNeg@ {NG 8f!(ppU*Ç֬b`rn繱c5WrΜ $'Sr)rS2$L7oo2Q*(5$7%xUy=$^!&n}CisN]BCуO·dC(}9?~k\eS)0mg[Fmh9%+K/^߽ :=g0@6ofCn[Κ;VqSrQ#.KX ݻ0GDcǸGnjѳ< ~r5f-3{| ݩw33ww'Our{4r9w_Ӧ܌*Uu) VABC'ܽ{PǎR"Rɧ20pP US vrv %J~P#[?-YRm@D"/$zJڀoP$=p>|0`ĉ?[ ' w^f Zm Cg 5uJfo܊V[g~W4zDʿ-s>BB7b7BBB!C`࣏xؤ"sW F< ++ؘSBIϗr'm0Ac+J:toOpU[[By -}|yݻw͈Ff4iBYE+HX Xl OQzuו"e'``a'zTsxr8\/g->æ~PϼaS`e{[s~$}{tv ;;uDm)?wdC(v_SL)}t" vp㢵 7Ş~q>=LΥ3Ξ647ϏIS+73XhGŋϹ6ABC@DDDjР59@Nd<ʠ; z!$V6.Pm զ}=Q*\6n$譜ܿڵ 9(.N{ bFБ8poߎ7ojmH{*yS\mh7b2;#':BqjȻi1m0}ab!hN7wInT nse,{WE!!Tu+[QX+`=gZ`yzzmٲ&L@O@ :zQyn'kRItQ˖C[ -H~"~ohҤ .] P*1c P(?yN(r>u1|p4hРTԗNPZnOd2'Ǭ S}ﱤT5R_,\``n-4nUV۷?w&ڭvT ?w ޾}{ݻ% mذ֮]KEO6l,+O[Ac*k׮UQ`@@B>|(nZ\!>#lRؤ4I}Oԯ_0cG7T@ѠADS2WwA@JJ fϞ,۷{#9~9z5]w(0jBBCnsful1?4k?iin)>xzzbӦMHKK 8f̘A2^|I#GTyϑ#Gޞ\]]iٴo>x")J6mӋ=Ƿ_C4':: ښ233+_}E&$H_g/}I"w;h:"KK.afF|9QzMzEw,,֬!J|-2Zs[Ǎt>PEѵy-]T+T*$$b ݲmRAJ ߯P*4rVINQ\450& kT\7fSS.P~]>zƌta hv}7/ u.ZjdbbB(PWσH 4IɗtG@|u3$rї群יE#^87_lm #GrkHt4Qo-y kP$,&M?3233ѲeK,]\{,B(]:ڵ R3gD:ufY x2 -ϷY 3|ۤc(Hub=dIc"#N/^p jA#Hn݁@^`f=oPǬB'EBD-[cg@XIXY*b۶m000w}vK| N~H-փ3p鄭 ;T粜 ˹ 򝜀)Sܿ?a M>T6268*-8#XU őN6mȂ ~ P 6?~||^di~$PARh3BBsǟOLDG5mZۗBpO++"ww7o*_o͒"хT*5kX,7vGl_I=4"lFWr9,ѱ>>=y*qX[s2ʹP$d`yqFu.w܉$|gpttjo>'s!6fsB9zλZaC p @OrR ?l ={r.]n705[}P&hd$'e|UB @٤|@Z꒗G]]ӇRoj)/hC ÏԨ7P8AԼyሹ{w"D|}>:ul!blW[A EBݣm͛7#%%&MV8lwǛKoPչ*\qegɑ`psaƸ0N9 5oPO?mGAA(5 n&q{ oocm׀ b=fW%$tL||<1EEU`Y iwȧֿmTw5*9p W22טRIt QօCvR*_/-޽DZ}oE8`qCm:\7o6,h '"`bsQv}oȰ渌8̻2ǟo;@S릚7F;[ڷGիW99\^yV. p=j{̚JPhӧd``@VVVZ?[Tҋܲâ=F+)h-d֜> :YY ;ܷkW8mߞzv3 D+V-pM;Q. JB&4:Qd D觟~j.~}ujO+;`Ϳ2ҳ5xJ:t(..\ ?~L4ujrlh[3-0 ox4FΗ/_&ԤIbb4U=!I w)QF}2h)3FkސRIt2QNMgEԒ )lܜ믉?/wX{+h-N(NNN9:::}-rRNBNV(wUPcM:pXtRIt*Q΅QU+ӧffCT؄_\"|-B`XQQm۶!44ðaô|!C!UZp bSq}0, ¬7BH$倏wE 8|xG;| ]o>(AZ5_#hH{*Mfffddd%Jb*WߔrFb;rl{$L(ɧ4v,!!رDZڕW EB=N( -Zm)r:#$7%x$-RINMpY=\7o}Qa`vr":vG rSv-|zuŋbuwv-0")ٳg Uxs7;$ڷ)ퟒe%QC= LLJ۸(?:8pҸ\ KҞ=,f=zo(F't… IzeEei^]H+ [ț5rn%{DϹ慏P3"P-EJbEy.\/_bر4hP?;F*xy[3 ^){ח≹"&=Ռ; \nw>W|sens%o[Fu&&fsr֩r; GBPh $FJzSxA*Hg:1b4XeCF~;rr}>Z6PU^|A=@ɓCEx񂜝ՕmVk|t#tr+g$nޠ%\Z YyY 2YeBpo'g^7!СEw2DkիWt EآFmllpX[[.`ii Tzݨy޼yĈ#0zh?K!UɈ'h}5NQB=-rD"g>F&~8 6 h׎ШAnRrX0mZ;CׯsMNĥ6JBēǀT^W(ԧOJ̹sծ]5~>+:~@H= lJCLZ <1 1 xÏq[{mlv.uثTr;XXժDgi.C[>. X KKK\<==q)@HHd2¿9rM&EW^Ŕ)SpYլYSH3.g:5zYAOMl" -fG'j&ę1gF1S BU+iը܉  801)lv6lZ K2_}X-kwd2޸sjOOOlڴ iiitff&͘1lmmՕG/^$ooo>}:M2VZUH{rV(4p@@@ަ$B !EsnFޤ滚A+ iѵEs^ƌ)Zmz"hT`lƥ>%ח`^wž{жnے}_V~ P(kkٳjՊ=Ý~/@j*wGn!Ct'kP$=W\IёZ*JC7 aHSz1PT!CTǚwP gߟI,/駟Dk֔8{pqn?2%{>md['?D"UV8T.S.mMq^81u;Э8TJL*H ѪU*j4FDKihQ? b Z(ꞷCCC‚ɓ'|6+*|o~^Szv:G+ {Z%?M }=1(xn:%觟6,/:R`x|։eRRRŋ˾_B>5|H uW%T*ēTS};|9m%lC4kV7 e˸(DnnDffy"//4l[l Lccc3aaa:t(V^]D_"b^HA?>ljŪp+WmD=zo֯́ j^UT7s\X65kY6a|+&tff4"::NNNЈ(ܹW\A-pQK8U@،0$ID _Qgbfea:l\8Z;bנ]ݸw_* ـ0o[k۷G ܵu77.8רQ  !!͛7UEJ#+26;cs!y{_fx|։%n޼I&&&$*Q*9p~Wa*7;ʑ[ꚪwV;+ &'sZWLMIBAt"Q߾jՈ%PswQ[la2- uÓ'O#''6mËݣ)e&@l*GԙP<,y!싳S|{T5zRSޖ-@Fܹ…\L9lmW_qgYZaY| BPDEEHMM… U'#@/I8̋W4w±cMM\62f/llp7vtMgšHHqǓ=ɓ'co?$7)h۽md΂.|h[R)Dիs9 CCn%[EH__n5(No_@&P$ԪU+@Ç}P;geEgI ݲEIgNs{5`vF_;S૷̟'L6۷5n\cKT@@-0'##ѵkWxzz#cN jzo0`ggTiT$%k Uk>?bbj5kXQww/_;{n٫@ aJ}\9 UEB>!Y̔IDATJ1x`ܹs~!.\3332O狞C7r|m>m st=MÛ7nBB1d _`L.8'N &q 33 ￁:,Rԭ[7@۷6*-Fs/% 1vo[sb^1$!C>$^ deEhQlle÷:9#o2220`ܺu ۷իWaeeH 6Hư "{| ;m076΁;`tys`D "w'a ZFׯs'k{Kkk΂ =cbbhԡC" M6\]]iŞr,͛`N FΊ\=[p4Τ5޽5o)X111E. '&&ݻwG@@z ///XXX BєF;v1 λFaC =e@a\ѯS'HVĐ=ѬwrDpЩS|,Xs|+^  **  zFF<<)9d'wҼ9NW[ BP ??-[~͗Eg'''޸saÆjOOOlڴ iiiGff&͘1lmmՕG/^$RIӦM#7779ha%aܿjԨA/\)lZLWAM5a޽\"?ѪeI)~/=J[bX[FĞ˷/rК·N.]"333@s%BAϽ[oK2 9p LVĝ]WN9" Jt[/ bMƴi ˱n:wg!nok.1`?;̓s& KG(~\ѱ$1֜ʇ9!"Z &M:tzCFhv΍>f4Gl,lp~\}ɓu4wzYqjV/ÿ YbY|A[ޓ6778x U?O G_GO)փ" ãG0v_a]cT ,-4t\mܨ;`8ngX5gar-$,$%% Q~}\;v 5WDHLD.LۂnQ#toljڍ Ash"m ĝZ j5garmmmopqqI2dжm[e"+3 0Þ CJ` jFO0D1> `j;\1v,Y Dqc]š[0"!cԨQHIICH. ܃"̮1?U/g-> ׏ ݺ"u k{΂od}.v܉#%%sF1xݬ^=thZaEX ʶZF'Nrн{apֶse/[09~_999pssall5=֠ӟRri >0gvv sp*j D?XۄNΕk{΂o},ᣏ>Qۺ6كN;Ad-91Pc09k1#VTðI9`̘!BXpHY[Ε k{΂o}+޾}#GīWжA[,[dk$vL[7$%vϐaboK+c& 9qRZ5_=ga2@/E|~ \ᵇ5}TUe?D &j` W71ӣx 쒎c`/)Z0S+gʚtl8.WC\x8ý_>|:Ixxz>~=nҒe[z9n,7|P; ־I(܆8 i Y#RjڵkH"2()#idFK8e練mD; >p1g"9+_n%aUU6\qg*Sݮ7oǿ)yn4}=gprsCc͌4_|GZzIO?Z>nq7b_זÞoCX\pّ 򜕯AK- 뙟648~+^a'OkMԾ%qFN;KA/sV#2%$ᣇ‹irx `ބm,` 򜕯zp8HHH ))s6Y|mI* 5M#Dtt+skR̔2~˨#i9,|AC:''x֬YCUUU@- VnNJIxiS__D<=i*#x?E p#Y{'"hۛVHyW Jlذvf/ 5Mc˦-`3&e\Y^GS'#yYmE/sVch@a a}777V+7l۶0.///6o|?uyJc{AhsN'r}<0ɓ*߸ra qg/_ĄH-9+_QO'gϜeXPLCU]yIiʹT^Eg'OYeh,9+_F=Ih/0p< Տ^?wĕq. @i s 򜕯<л$t:,0 NogthFD>G'ypO4Is 򜕯AY)&qT"G/ 7f@p^N"b=IJB4_|GZ[)ԛHbX^̢C;9AfY!Y/sV#rK¼xcLΓxAlx4~d i|AJ³'j_n44:z!]:2kf#}|+ i|AGM]jW5ǽGX0vم7 ~WȾ ,9+_nʒ"I!Yf\!V^M5$Ҝ,o ,9+_yc%i=twovd`@+"CuIJB4_|GUI7k7zhgՉUݧm*i|A}kIxE^zb#'StmZhϕ2%= H,+9KyWDƤѭ}WW|IuĶ$?k>;C˟yhye4gi Yꏡp8HHH ))s6_zә:umv5яD"N^s'h8c6Jnn F4_|Ѐ!>>5kPUU#I~~>;wfՄu!QXSb%ۋ\8]qwY?9KyW J݋LEEm;vlXsKĴ/{̦whF#Y/sVcmvAAAv DAAt]xx8= W.ºIٱcB4_\}ŋZQX4M+1;l6JP2dSNӓZ֮]kBP}7SLח6mڐ\+MF-p: pW >XtBJJר$--<ذnr6֭[r ̛70]udddP[[K`` .\`D4WJMM [ 00۞4]9uqqq[׳uؕY ի̤aQ -ĕspp0lذ&خ3vg~zF{V_w :5WG):m%r sWqssjR__o=c 3xٲe8<;^njxٱcEEE4{gJDWdggt: i83Ajj*;wdСCČlggg`y޽g׬صk_}uuuj ___FMhhhGaɒ%F6 SBP<̘CP(fT@+ IQhݻ4;v,P4ЊfW^aժUX,FZl9uVY|DYvZCVV.?&M036;B0)jP(&EBP BaRT@+ IQP(&EBP BaRT@+ IQP(&EBP BaRT@+ IW|_a IENDB`mpmath-1.1.0/doc/source/plots/ellipf.py000066400000000000000000000003431340375245600200430ustar00rootroot00000000000000# Elliptic integral F(z,m) for some different m f1 = lambda z: ellipf(z,-1) f2 = lambda z: ellipf(z,-0.5) f3 = lambda z: ellipf(z,0) f4 = lambda z: ellipf(z,0.5) f5 = lambda z: ellipf(z,1) plot([f1,f2,f3,f4,f5], [0,pi], [0,4]) mpmath-1.1.0/doc/source/plots/ellipk.png000066400000000000000000000276271340375245600202220ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx{xTՇH0EAT `Q Vx)VlR, ( M*)ZIBq)ƄH:I !s^asId^ᗝ;vaN nAa4Z0 3Іabm(Іabm(Іabm(Іabm(Іabm(Іabm(Іabm(Іabm(Іabm(Іabm(Іa0_f ?8ŤpIJJyL<9HM0@~ZZ=z4G}yڛjVow/- A920&Gm&hZ!xނ~K[ TPڛ zݵzCq hz^w{8 4jwz]mWVouYض ?_v֌ʀ$ԈVos/+in DNQ$ޠ]7됝 }B^()*ښkzHn5 G7u SSap_>& hkVoqao 8*ښk7m͚W1Ee@[z^w}ΝΊʀ&hZ_/3!) ӷmMB zݵz%%r{/ hkVosxy}yI_Q$ޠ]7y 4mmMB zݵz?t^ mMB zݵzCݷo[o|P每ϲ&hZ!6Ee@'7h (hmhZ!o){ ~80!YɕprDغVi<#㎋㏗r zݵzCݸ̢MHT? h߮$l~+9"Cth|O=%iN8!:vF6~z^wp~ FIc\oCe@h_o%W4iݻӹwoBZks_V..(I`:SʀvnѶms]Cx]2}W9O:IskXVo_g79E$\l=%%%tؑI&PVV5\CÆ )--'zk/e}ރwߕ k*Ӱ-W9;vT36az0ƍR;-`_X{<[oK/Wdzޛoz{׺IWGygySjyG~+->˃yjp1gΉ|RRRh߾=7nzFs͚ɐadѧʣ,xe9@W19&  5s͕S|\SNJ8f„ B SXXȂ `dgg/YIs;wqqqdIs`42{ ~ȑdj|BY =d<'OwDn~js.59׮];g\byyLN96lfĈ0sG뜕EFFSL=àAN  1dƍG&M(..R>y7-#ޓΝя9昊v2ͯa`:VA=#C\ӧGNpmWv풆c,{qLb5 ޽]8x<6 nY~Aڅ^kD hߓίkHt\ۼYFّ~}ي7+ݺ!ZݵzC%%bM@zl]oeK8,9JKʣke1M@^Я}¡k=o |<_|QF @$<@/k<+~QF֕C{J9@Z'ѹ_?fLaYDki˗eE]%{'Y+ kSv3r]2ٺUj3fn4d^p\~1AO_>1D7TwI8#c ÚFx_űn]cڶ('sm5JZ!IIre%mw\%kD\ u_pxoo]YY` SOOJh3'̍7&PX(um\Tu7 5Rݪ=$^{M0@c_:ۧ#: ޛ7K+(*ʕεEښSF]\,ˬFFo%HG_2z;HY̞ mۙ/rmMBoƍezޭ![fӧEIqjRΝef3ȴ:n<<`>X~ώ ۶uu5 < ʍ/~QGUO;MepEa!O2;GiYq-[T8I?u:qrksp䑲r۾}0>㪷E0q,  \{T]wm,qXbݺ;MǶmdtpUmA%܃t!y{{j7ȴl$VaOaLX-veva S:;+.2_k٢rmMB Ca02E7…0~<}4|<( .;%^a{,yp^xA.>[8^a ]/[&{GhH$u^_8lY`"C)iT.e7\kޡ,H$/ \Iʕpݲ.v~%nݜMsϓ5NQrY,r]p5E*K$5qqЩ?.M{) &/Y"gl) 3dU=/)Osb8}Əj>/c%b.D=p\J~ЦMW9x)㎓s\"˃l-*G$ް{&}۶IPqi̛'ӧH [e']C6ln7K8"=Տ?+8pyq AFe bKR*C C%PR"SYkY\eU׮AkbMB< 5tON*e3%Kd rZ$KI!;́gモsZ֕n*͟PY&htA쥗d_"m.2zUh =&]P?..] 7WffrA͟aԖY/Y"u좢:w!п;nee23^r2; ײEښb޾ 22dtl2";[65yٞWV(ml.$Lжm&#G´i|AOWY6̬Y_dҢE^wI')d.ZL 7 ֭#O۴!I>2YY)GVl6m*¸o_ɲF> ڶ;T$LK ALLF> Gul߾?/?N~k w)) ̄5k*5rEܾCXy'^dh]ok٢r$kOP[ڵѷ7V}GFw2Ŏך;W$_~|J|~QKFp½жܨhmC8MUߠtݺUq=8ݤGtF@pp}R;9N{=@e@ەSeeWu4Dw]V}tͶ;:%)I67o`=[O-[UWmMBwIlŴ{ggZӴ+Eu1`x}'-MFw fI oOM7ɔ=WPYvNt0}%^6r.O\u4ܥ0}\&ˆ}O? O>YYbR\z@wo?p-[TmOyRuaʿۺ\A\y4ܥԈW=umm-~5}V6R|19zG>Q$~Yj•GGos /~!:- 5 ⿦z\zkVo4 /-4y ]7 ^XQ-VT-AD˓ݞHJ݃8%EB0ϓ5@|R.1?48QvqZgfMBa#?_nzbJJp.G8ݰZݵzd3SNSg`47ej~'@4ub+B6rS͚epǎrGMFSZ*3?NPAF1e&!$wՏ~7n{qcBuהSװVwްpr|!<׿ƒz7'菴 ho-IDAT2ݰ!͛;W[o_))U#a^wP OfRyYcDYɁ:Xc?<+ヒ>rl\} զG[tCÈ̑:_˹]{bJu@]5 wRžvc} lvՏ|>^5~UJ Zܛ5V\j\xg]쮇#2ٕ~oa^2=Ƚ͛0bҥ?Vlճ,4xpKx=MU 2a_۪U.䮵k~%+ u|ԥ>z7Vo߮z>>^ՅmQpPWimhZ!qqrQ˯-K}> d~uBek13Jha%8(+'Y66=mL!8TY[/㏗h5sfff B7u >7h z| b0/$+t}\nV-ZPkvz^w{|,kRcS Qگ$ԈVotoDfz] ÇCN_~2]p_P+z^w{#BNr{q0yMrm{Vor2Dӓ'K;dm_ hˍjD7u 7n,;^ '˖ɖ>Q$ޠ]78ޥ ߲-R86mMB zݵzMjy/ k3<z%@:??+^zE/++cر\{7I?ZAVoP>|8|\uz5A[U!ЀNIIaUJ+WSNM P(Dnn.999Bw `dgg׽"KM%$$8RsQ .Gd1e, rXR8fĉ,YCҽ{wBC aܸq4i҄bx≨= KHjZAk%hBB3g}fͪyڛ*sk.dc_Xz^wޠ%T5 G7u ]Be@ەk.2JB zݵznwPڛ zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vw mMB zݵznwP$ޠ]7vwAx8ꫯ&))͛3ydrrr6lK.L0!y$ޠ]7vw@G .d̜9m۶֍#99"ڶm[y$ޠ]7vw@:??RSSٸqc׫V駟RҰ&hZAKСP\rss:B HNNf׮]QsssY`,^D䷷3.59j*g\jz.++۲e3.󒕕EFFSLkcƌaܹAkh0!!yW3gm۶?V\INxHKKcʕQϋ BNZVhZAt%III 557V9߾}CVZAVo |P(Dnn.}%77[]srr(((`̙uY,Z(~6]:8)**m۶[V%%%ٳgW*ٵ<ذa]w]ԹѣGs饗O?qW~ߖ-[Un4/2Fy[owɲe8p`Ewޮ秞z*P&ˣw=L~~~yO%~knr=55UVQVV:t(s:--mͅ+Vp*-[2?:3sy^yBk<'''O|+Sf TA$''k׮ kk﹊9S9r$ؾ};-{eԩ[m۶裏V}Ǽyӧ7|3h"nFnf)**b֬Yr!AS[of͚W_}{Y^{bb"锖ƤIV"3qD,YСC޽﹊6 8Q$4 86 p h^op]wE]aQ/4h\ve̘1C[QooHNN= X@'x޽{3w\&Nz4Ŧa8 00 Q, 00 Q, 00 Q, 00 Q, 00 Q, 00 QN AIENDB`mpmath-1.1.0/doc/source/plots/ellipk.py000066400000000000000000000001361340375245600200500ustar00rootroot00000000000000# Complete elliptic integrals K(m) and E(m) plot([ellipk, ellipe], [-2,1], [0,3], points=600) mpmath-1.1.0/doc/source/plots/ellippi.png000066400000000000000000000526351340375245600203750ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw\U,QT\Ad%jnEaejlh95G#qiZe * ˁ e{Gq{{ޯKs}yb Eጔ[DCCCC(0544454445444544454445444544454445444544454445444544454445444544454445444544454445444^o߾|駦k:^{#G2yd;ihhh'yf _~ɍ7HLLk޿?'$%%COCCCî8wލN_~ʕ+ EBBݻw'!!//"+!dddPzuIMM^z"\i3UL*|N&͍Lp)ϵ<4hP},n޼G)#Aq\ؙ}siӦ(-^{5bҤIwߵkW;XV%K[brNJ sNNB aRP[+[oY_ص]H=ѣGk7n,~777Jp96VzsUx%0` ~b%v/V!,`0[br^}}\UXW_˗axb6_s2A{{{["RQr9ՃVuO{];X̾RLz `1r9˕U~9s~UV-j5*tvv,Br+A2o)Ǻuo_2P[kU&Zj["`1r9Bժиu8iĉ6*XmPeNMMEDDD[bpNO4@h喧.У|mʅb6_s2A׫W ѱcG{+X΅֞*7Utl6mgEv-UC Z+ʏr?bnZhFF51|͡ G9r$hUX_l:fmdݪZP~pϞ AP|..6UkU",gV|?77ذ\\\ 2AkEBH͛[ʎqv4a0…pk{]E;A=LZP~휗II V}4OSOˊv6k{T"X9>gx;/~}XJu.2AkEBϠ_o-}j4lXۊt.2AkEBS@1BHICgEqeU&hH(?vYҲɅ ޢ82|m*V$k;˝83FpdYmr.Qe֊cmgbbo@VLrD"scu( Nt^ɓ\kq)ϵf.HY`( !q~vA~~>/r9~WyGywLy駟l1s׮neGޅbrbm[8z]/ 2AkEBs- C׮CS'AP[|m*V$:?۪mK_/]j]hG Z+Oem݃jg΄Wa`z-څk{T"Tֹݲdʁb|kvwsP[|m*V$8h638J1B:%`Nnذ, 2AkEBstl5 Vþ}W څk{T"T`gg{I_/YbEmB=vMǏgԨQL>t]k1rH&O|"T38 1=ᥗǬ#Ujkkn߾=_|W6]߼y3 /ƍwZ+OeуTcb`|i'Ujk֭[۷/ݻw7]KNNoooG+Oem=*c!?_wzRev'sN=JVV^^^$$$Wg˖-DGGƜ arcǎq.\&Mqts!矉ؾ~)ƹvֱcGŸZa"##V,X@FFJAqhg_رc΋/Æ vԬY棾lذB&OV~`vJBp ? #Wjko4o㷌o_8{M޽~oƍ%OEBU9*Jze*`yr{7/9q1\?)oԮ hEBckV)&&'@*hqBڞB[HO>Q|rV[!@D%"O~Am5*8"Y p7<~Z1c+T.+ږknyOpprb ꋯ9Tك֊S^נ eA`fЧKg * kf&&$ [GfU+-kgذa 2?t=>>֭[3j(/^|"Yؿ_xAHBر“OW]TWSOX=ʍnF_ֲ$g(oBB/G TvAٓ={O0uTUYYY413m7*?qNH$hj׶TIq:0ą (bjkF;1K8p4 icye2|fϞMNNTW^f <鿽9x k׮eŊw9H6k2˔./O2GmRߌ3x 3!R> ^k@ {ɞt;vp3m4F#ӧOgݺu;Y… t=GGGjժEAA}] #<<-[m)F)bM[kvt޺mcW0abWkvRKy%&&܄\~#9u.\hG{rŵ͜Ϟ={׵ӧOҿbccyGС˗/'##%ay6l`֬Y<899Ѷm[^:6l`0c(DisW>8^ ~};CL lO?m B7$M$yA2<#UTw/ h}'g1w\rss!44!q2z){+Xıc`1e9_$Ѳ1{$ѯ8vE*EIFQ\_b/{jE8ذ(?Z9stf[oаlT9N+OY΅Ϗ]OX:TJMW'g!iժ~!~!NRerS&R)O^n[b4^PsOM8Dj8lV3d…x[EZ*8"䜙 д)t_uаԋ.ƽc{a70C"N5[GS]ARR]?~<?v" ]ve˖3(/A=hH(?%9tP#p~A:`xoAA+V`̙RzufΜɸqLPJ|+*{ZP~JrW_Ҟn{)ƶ$xNC>uՙW$9}ϴiӆw}45!QH}O<NWe8Hݙjo-OzVz࣏J^\!vÁ0<#< :DMqp.TNl>CXz5cٲeDEEѯ_?*& mw^(9sn齻{%ry8Đy0~[eS5lذ)SpETĉ2eJ&V$/ҩR=fU! ~[<μqd̤Fӎ ݷo]t᭷ŋKDGG駟Z6QUS!#_ '#XNe/'bl- ?K$i^#UV nSǦ{y&NHxx8]ve…t*/Dm8Lj,mESqgoH77NA{!ƕE)RG|]i6osW7%%ٳg|rz=̝;_~Bce6QUqhEB)lmtY~۽ʐq D-r**ɓM2WVs+"Kru⨲ ND8qBZ+޼ GK_/_5ʿ)c\QrrǵP3&SF,$44瓙+ƍcҤI4h~Qc(l=xV^ŋpЊs-v}S!9^y⮺cl) =c90~+-7eIP~_Net:FEll, ,Iru҃ ZjtOOO"""믙8q"["lC-Dk׆E,~c\^^pye.L@{^8ɻ7sYyyyZO>˗/>}]Tc(, zܹE|I=;6mBԩSin#pvv`0W_yV$B<7iᡇd6L<c9%mW1Š;h4>ڤ=)EIzu1k,Ӹ/̙3:̠6QY8X~鿗,Yb~'={dʕY}_sV$BYx؛,X r?h6Qي7n`ЫWR]f <鿓u]ڇV+Osl11l WWis+jqI_'~FcvjsPc(lEG}X]c,=[p!:5///U=gΜ!,,pl@tti8kq̙hmyzBrsaT"*7**~q63~sKĺ?5ĭvq>v˖-#(({'Ob ~Wjժey*}`222PBFG!t:xx޳~z/F)F-VX!v!F:tÆ }J^QikѠ >`ZZ"/OQFQlN-Ws'΅?xgNΝ;hQZn~zު4hU'7Vl1~?.^^=ҏSk 8!"{gz:JdGŦMD۶mMub˖-HiJKв q9uq9طoƍѣVyV$D6o_zI7RSa( jqbb"Iy]( Nf[ZgBt@^y bҥDEE1p@[Dqd)W_}Evv6mڴaԩ-c '==DhMݻahDJ -Ɔ,]9<0\mhTYr%ŋ|4X1֝;!mo~_sgUOBBgժURJĉ+}J9kmQbEX@"bŇ;H_ԯoŇ+3iČH#nKj kEpnsh ?K.ёqNJ+JMΠ|͡m7jT((cvq `餔ނg%ccK/?+ =N518V'sDDsa˖-!S.!!!m<C=hH(&uvuN+=tf;P+=(Jۮs#ČAɈ&t=ߕfI ݻwӧO:u?@Æ 7o ̚5]!cKP9TكֶM#|4`(cu7okq!#ْ3߉|͡V$>å **viO` NٝkЏ׮sIhh(}8880`ƌC=lGLZкt~=T"MSU)\ ['9bГ0;EɈ|kSW|pPC+Ks6 %44t䛻;G&88__J(GmPV$.aa?ҵ 9ggK{GA6-kXġC$}g5'\hd Y`<xbYp]3(GmPeZ+ZCG}B OC0~uʉbKŒ}*[:9{p#|>;Ϟ=ŋYvҫW/ƌC߾}qt_J8j5+V$QQ?(\K Q46lP*ӷNEljM\#ǎ_~_~|rF#Çɓ޽+"9۱9kU"(^,"hi۪[8tr.# B:9{ljh<== fСmJn(k ¬Ggld9LZ:dgK›o^srqlin 4<#ɋI8CxO8VǚҥKYr%Ғݻ3f{9-( (fMfEPF=nTۿ2~wHh֬Vﴕy8qxBa'+ږknuq4})]c/'g!_LJy摝͠Aؼyi%ғ3(DIB=--` \O.`smlX N.$1dѥK"/\ Zj%F)BCC|Oi!77C6nШWXO2fG89>#ٹbݺucǎ=<<ĴiĥKdL9rBXC0LĠ-ĥJ-vA{zzzUYYYwҊgfi5OBwLsiq#4l(gy)7bу9dPݖ6?-к0k,jڵkիIJJ?qe:+5ff0vXٞ iӠ g 4؎e ܃.O>f O,5_NmBk'u~ɹ3g5zqam^qqqEa,0Z"""[o%T"   +FF0bἆ9bߋDJ-vA#jբt-!!0ٲe T5NU_;CZp%sg6Megese7_Ox ?>]wJ+88;Xsz=Gcǎ]UkÜ9s *r"vI_yt:ŸS{yxü[dlg|;1u*u~{Jt޴IzsB(h,7tqQ8ɗN ]Ϊ&͛'Mbɒ%"33bg7/? v_JA=AWQM_-|sdnnB88{,~E'_8iJGҭgΜFnnnܫW/? `Ұ,1sLQꂙsk%8aU΃VcP)?Tz0J.Wu:i^-'Y}k ghd݄k.Uƈ# UV~EyPިgMΕ+Tq{Gy,1{Ug:Iur'CI]A*1/. .}'++K,_\z˞bܹ"55*Q9F~nhiܫ?**LUc csK,Х \YtMH}kC74jACW~w;v,=QJ(/J_'zx`^ytit|+PaZ+ZRqc!X"&ŋo19Y^2:%i9yL*U&FQ..._G](]X|[_7mNezЪLJ 1Cʳ+WZ_IWW!KLs>}b/{߾[Vz~qnnXvm~V)]cG/|iQ<(-2A?SVcǎYJ-[JKñp!ԑ޸~%`3S$OܻgLX+W3g svĚ5kDER{1QGU3n{ܲ3VWKV@iAT2z[Kyv۶r)=] ĉh4k?^#Ws'Yw5R=vx7Ms='ۧS箟C‡35g,RRd\HhYXV:&ᩧ Bw nٲ;țĎ%}T۷.~ުz+)ztߟ H'DmE,[z&TFaN::!ԩfYXm5*;:C+>I%oK,mE.q \ pkB[7Ydiz-jԨ!.*#1GcTQWj9T3 Gh(\(ܵk9J:up%r $/H&qn"l..49M5 cm:ۯp'|1cЧO;3ھ£YvdФf&vȰNps\Wm5*l_9;s`hx$"39\*qǑC&x=ږ5Kپ}WɉRW敄|/߼WǾ⫈t~u}g7^5^j kaP_|͡ fzؽZ֚`7߄v <}G-u.H+ ~V<_BU}{k^'<,g!?;>s9MF6TiPoرݻB$g!'dl?I1Ύ<1G~hؤ|'JoEQeVf6 //3 œ}_sKs7b v.{O<޽;]vᆪz? .0~xv*k _o.s>ֳJ^U,BxlcL;݇vӧ'7~s7h {/;ǛX_Yך5kV"## gddd$ǁvpNǸqصk}CxyyѧONժU˻k 駟槟~rf"9:tݲŴDs9 wK8|{jПڏ޽э7Xr%K.5ӲeKƎ믿n_/X*/#"9siE!PL=da$Ÿ"oG5AWVcp.,^|7 w+HΆ,sIZ1HFUC7Thn\߾};v,zR,!KR#ǧuoиCth:Zܭr"ǠH8c;u2 /;w4\, +kp _DZ#Sx׃ nO )iܨQ X B3Ny9WKAP7@J ӡZM1C Het24ٴZuVK"}_:1!x 5gUU%::%N fذa_y79zѦќO=O!ϴ2E ߑ5lGMs'c\j5*JCץց߭oK[;>(Z)Gԝ71pqz{C5k2eʔ"uرc8pէU{ !HL6%h^ś;̓ :t[oEW`%;C i%a|<< …'/WH7lJF %pqEDwU|?KM㗅6oތ`ɉW^y1cЭ[ lΧo9z삻srp"nzҢ^ գn;E7{8V'IDAT6_s2A$LOF/^;72uf{rt023)H-64ϱ҆Fz[h"oԩÈ#=ziNSsX"!==5 q@SWjKQe_(Huӧ? ӧ̙q7Bv;>]|CUirN dر#,, Pnrji|bb8+~ gMI9-'{lJ E%=i D-1.D=Lrp"2য়Yxcl(mmܱqT!<#ɡ$|:4ٜ#s7]vPn]BBB=ztd%X dž I8FFaǺ:r}-QR˃k{T"e(ժI=΍Qinw6(׉Kn\.xk;|ʡCh֬իw%֤pDi=[Т^ z-hVN;9^-yhG ^,~K#۶c@HIV4(ț'{=zx+ٳg4i/r/U`)7|g-:1#L.Ш)&G*5d9kG ^+^-Xtyu0|8,Y"})\z{꭫|=K.ӷo_gTbFnʼn~g9z] gJ .iͦe 6g2AKEu \\`˦/ͩsv7eט{ki٥ 'Tg,ܴU>ˤIxdq.N.WO%%'8yDN&]JuRBk*9kG ^)~- T/} isq歷ƙ/H̆![XG^^... 2 &T|yD_+_y׃mؖ6 Ъ~+ZxԼaK}ڜ5_ۣ}/ 75&?=A… Ю4Ѽ9 3nj!wH WhF3vXBP߯>m/ϦEo,:DhӠ)mؖftK5 Y=Lj/.ZIyߘyx ]W'J>qqen~?РAƌèQSNs9r.$Z5(VOlTQ$ܦAZoIU窕|kƂڜ5_ۣ"&Hp-X?>c iNgtdcD\xe v9"gW6thAbKPڜ5_ۣ"}ّ̜axpT:MܼALNlȴHmڴa̙ 0Gҗ! !8z~gO&J֕"rC2%䠦AfOwV[Em>g2AH9*OKoO^ .J7Ljs[qqH֭[3sLXjbNLNNthԁ]ִ]=r_ʵ߄|A}ΚQeVK0* 8>kPUH:ݚ֑>:uDDZjŌ3x&T]*{saRϙHP zOOz»6_Pk{욠u:Cݝ:u0g߿?<-[$$$P$ܳ{e~$d?µA+7D xٌ3xqrި@qs"ˡ[o>ӧ'=vVW[Em>g5Ao޼K/1rHiL?[V-hҤ]SrPieq:0U7~F̙+ D-Z0}t^~eSb)׸_1G~:9ܽkyW!?8j46_Pk{욠y&))f͚1ݛ}}ME¬,iS29E^@*=0 ӧꫯčl?dW.2iGߓX s|mv'7 $$$ܵёZjQPPPzNNaaaeMDDDڙ3Ц1}F:L#&dܿ&`rf͚ӧ b_鵾`[q(p/1lM>:^JŋkD\o ؆c/ `ZZҸ#Nfhj`bhKc`mfۂ&MHBxyO/s~=oY~r&j"̐eL[ւ\:sTTe\de}WVV͛v_*x\rOt:IKK#((v inn&<gy i ZMIISqnݺK]%҂UJFlu峗YЍ{}ptML>~Grq cTQ$IdP K]`^Z"9< %c0-H`7 xQx&Ӝƿ?==WOL!521^P5HŖ xD%ᮝ.6|Gi$^irINC܃q46S{R#SI VHyk<"ڬo67sžhP:ƑpamԀIVSۊ_li Y}Gd@M/qxD< տЯۙq}ƑJ\x>> !款civmȒS|dFa }|-h/T|{0q,zK#G^Hs xD* [} 4҈]FyK$O z=>_H,+9Kyk<"wFE|$~rKoGo]t/ss?9$Ҝ1'Tԗo睏Jj8̲B4_笾#rݚ?+Ӄ 3&d|XVHs xD$=7؃7$ K gYVHs xD_IxJ89A&{c6C3J$Ҝ?F>N/9xlV#Y/sV_15  44G^^owS@7sCo f+i|Av*++vR***wv[uƞ|:_HrsscϞ=uOG)X:Z"'PJKKYf Vjv7V'>|gS_ϷC^~D.*[+**9O-x{{c8{zWg|98e˖t:/8,`_ʷ+`ȑlݺS__\~ҌV"zrftm:t( 1K9[uƅ,X!CCDDgתؾ};[lN:ѥKp8c`` /6[UX:EQe,}CQZFZQŢh@+b233`̘1\.h@+k„ Xk+J[ЀV:,ǎfu;k(&Jd 8222<&MQf(bQt(bQ4EQ,(EрVE(Њ(EZQŢh@+X hEQ(bQ4EQ,(EрVE('BC9IENDB`mpmath-1.1.0/doc/source/plots/ellippi.py000066400000000000000000000004061340375245600202260ustar00rootroot00000000000000# Elliptic integral Pi(n,z,m) for some different n, m f1 = lambda z: ellippi(0.9,z,0.9) f2 = lambda z: ellippi(0.5,z,0.5) f3 = lambda z: ellippi(-2,z,-0.9) f4 = lambda z: ellippi(-0.5,z,0.5) f5 = lambda z: ellippi(-1,z,0.5) plot([f1,f2,f3,f4,f5], [0,pi], [0,4]) mpmath-1.1.0/doc/source/plots/gi.png000066400000000000000000000434121340375245600173270ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxyxU' CBH$ $AAFqTZU+jQEuzu`uhEX:UT@2yHB1L' ʛ3y/gYg]E?}0 8H@aH=aFha0 SXa| 40Oaf), 0>aƧ@3 ha0 SXa| 40Oaf), 0>aƧ@3 ha0 SXa| 40Oaf))yyy9ylڴ ~mvmHIIAss3͛Q2 $fйxאq~Ŋ4h^|E`Ŋ !0Le|ݻ7#b? -q著 PRRs9' @^^( 뇪*t )))@VV)w}Xt>싱$\ss3jkkQSSzlڴ)IB: bΜ9زe ~_`ԨQÔ)So;DCCz衈rrrlٲ';|& 7x>^ٳ= qQ1fĉB 贴4̝;Ww/u9}6k@vn SDY㢆c"A(J#$@͉/Ḩh!D @/DI eK\Dp\pLavBL)*`0C%59R"Oяuk\=_qQ1)Z1HN&MAoLdtV =_qQ1)"CC@^з/աnD஻ (**J| E D舩Z~>@m-oihq믽GN E DcP:ƣ@f&4m8.j8&r @G ϧc^~ NǙ36~ḨȁaF tv6~ Bo ض-~o ц㢆c"R tI]∗@?| o0`8pƏ659R5M¾}/.+Á$2'` E DPd99GZQ-jCq6ok?p\pL@J0 ++iJs2r:U|A E Dڕz 2h6~Ḩȁf?ד@ :u:t$1hI$0.**/;6r+3LJ:ve @Y4y$ɣ :-/-%0^x)X0c#lȁtIx(3h8v̻A4M}Їyw_=|ycGK3†H)m&Ƞ]^NbAǃ~Z ̟q6pL@Jn3 J R{_nnȜ+K&OnνFCS1)$+qx -V /o@ϞtLlO?E@=t(M}߼V;aCL DhC>6ʠkjif#I;†H)ЖLB;-v $0!Ե2rdw8lȁm$اODe;vbj8&r @'$5pqAzv@ s,m!c"R I(j^ tz@JtQKK\߾a/6M$lȁmj ƛ tz:SC`ߚa!c"R I(V@E= 8ͽii! FS1):$ؑph:tYGYAj:6pL@J̤_h4:bE hߞV΋&Faky:͆H)4CI[ʢȠ2謬iނx 159Rf66fVZ1G39 159R#LBEo=EvG<2+ƏaCL D6SQY.G ZcŒsנS1 t0q㡇j;_RRO?/sϩk3 R߹)"C Zc\]/q!c" Eaڴi;w.*++^4@Ep2iW#LJ ۋ ڬƎ2'If _j%6pL ]^^\@~w޶+x饗BxR!7džn&b :LMMBנN`8ǁ;>(eCL D*yyy(-- )) hll8__[44wlݺ&^|[;t@ hhzs[ ;?WY}mLڵ\ZZlu^֮]| [QTY \~9.Xq9ύ=7cIK,'Ty=.|$:eʬY_y饗?PY|2sLoV{1u]v2u F:΀_}q7.ԝjt_l;UWWFI$Ŋҡk(օϛGKQpԆq9Eh3cƌD!D9᭷矯{]0OVq2H|^(++3CoNbh?䓴͜ | Cf r1)2;toԠBwqsz^{ly7v,Dj8&r @Wd]b/58 ?B?,M5 HKS>#կ1gCL DDeVKe|ǎAFpv_[횛 hM;ܝwlb S1)BS6&%SOWnyC^0 ĆH)mStpS/ݹXlȁ$ևNM5~m5h Z98f!bj8&r @55тDbŠ:)) 2(65~wǏu9+!c"R tfsyyjb۫Xaj57;EE4d7rJ$ lȁ]aUO\W{G&?7fMެq%s87D7}bj8&r @gua8n];S'˗vtJOk]0ꀫ*}Q[pS=eV#S1) .Эoei5bnҥ cxq^sO GajdQKr=DU$|]. W70vlϕp}曚aCL D:@+zC"m.HF FEVmaSYIXԔs3v@70̡s<@[VtΑ#ERX{@fO4bj8&r @g( t5ص txS%f`1C/ __BU̍ A'ZafΤ.b7Ns9 >zZk6pL@J, rԹ`s$f/Í$FJ|3F߰DZcz![Ooa%)M4B6pL@Jjl?@z5>%Kfc"JR].]뮣0#t:8c㧡4*SZ[_? 2zx%W_M6a!c"R Up"$Iu5:Gs3puU[ɟ~ z5P_tkG1 tt[u.>D{iW_^zMTMB9RGHQSQaJjƍy˝{.5|E }g^V=  :99z9D\~7ۗ>r pQԾ>u*}jjr~MB9HI`$ll֮8ɴh˨-a!|@2L``iAYycrOBteʴ͖9qDe%-TXH2?ﻰד ,}ZW/?D_?H$)3h+&aq1eL9#LvFCtP Z 2UeSUEӫsxkU(ol#kNw_<^_ |=A>,# ?˖P/YB{8<80`e6 @Jb]K>CZ7mi~-S]M Xp.bچI|9V'M&Y+02 /<3IIKkG^ޓ_z 8x!6j'lʁm$\ZuJA۬Pydq `v97$B׭qp JzƏ?O9)z`P`Z,f}7о}KwMVx1`nУ(~G@ YaP:tA":9JoB[(o|-Ǐ枈dP?AC=i 5V @mY{x2{ڕyNS]M=p rlʁmf?N=zG 4~:-Omɂ@7q@j zaMiO rsѶ@ЄZӺ͔8~uhA4oƜ9b}Q<ߩ&}rI(R IX\LY͘1@ZEgY mtplFaàtܴ1Ak?ޖAHk8|ܿG-"!?yrpWuu({)ȄːP!gA+?0,&H)f&a@E tJ -Fb!Xf*Ёo͞چZmIҥ MRi Z N}gclf:' (d2- ~ R[eq1pd2sҚI(R Is'}Lk=!:?28 ;Aš ʢ :8gO?=} B%G5r=vkpXLCR3DƍWrN @}+WRF}2zY0x5k¸r @gk9݂ʔ@75NҭjX0ހC4Əfy0͠]hEJJh6v3qΜ7@կ0UȨ/OL>Vu>z}o}W6 @JnJ_I$j#I' ڠP?NZdܮ T-(p #ٹj={R[W\`~A{m݁_Z/Gc#0>UggZ!>z{r @׉O N%;mKMJƏ@8:u"#$bmg)I=[M#2gP;޵p!mA{oa!M k2:r @gZNjTvHYO V{6ix&%hGwm| 0Q妦ҊsZ> i̤N7ޠ.Uhu3ΠOd \2MB+}?)lʁ]QQ;tv?t9 P()2wAf$ǎXҤn47G]&4rC~ujl1#4=mۀYg][$'ye&'ԩϘ\z)e>KA lʁ gOuH 7m,Z̠BCfu$}_`R7~졲ر eeI3w>vi2zh @iܙ5J뷅hn &h8@FekϞ]ڵN]Xob蒒|稭ȑ#qaLB3`*Ц=55^ܾD_d}R[e6)qա- 4@Sz>K| IDATr\{ɱtu+iRq;1f郄8q *_fC߮rė$wuRSS1a梨*~ez&]ڕn.ZBw;zR9pG :9̛M(1> !e)f'՟.Y D͚ڕ$n.} ~;}{SN<%\A*M}>67_^@wk3-R []⩧nCJJ 1o޼LB-$O(RЭ?f&ʢ~TVRAP5&]Ǹqc:NZQBk1|y Z>LÙ3],bڷْCQ{Ɋ8AOqX'bNKK ~~[aѢE6mΝʶM+VA/+VN$t"ЦuzJ :8t[ Qni!)oa^W/q#}B5YYs/\jUu&a @nݨ,7p Ǎ.> ^q0}:pmwI&zjbAWVV;@}}=.b[זcĉ~a޽۷/ˑۚco/=pNRՁM2h@:8t BRTWH7X,e={Rd @j 4g͍O<\u faǜWg* @8sS5y{1q EQWb`ʥ^L:UٿkϟWEQn6DQEYlO*(O>|ƍ{ァ,^u[@NSu)([lQe:e(Ӧ)آw_\ĵ۷ӵ':PsUe7( lGe /Ը6|,Ŋ(F}ŋ:kX|}!=eh|OgSJJ_qEQz^tkE\TQ.]{esRSEپ]ٲxR'ʺR=VW]uʖɓ߭PQW(uҷ.;[Q-J]jkG-ҺT=@y iӦ)~"(F8oQYYk fΜ.] == @^^L[o;vDCC}7b~Th6k"ϣn};'^P_mEEOq晔t;SX1JO;deuHv?a@`~𠁩S\LS}\w <rW_mx[mz"q*)Ț5quxZ3f**Ⱦ/+rM'"{^ 6))צվB}{$Ksm"iiix뭷4AI[bA8Tj;kKѝ;BWL:8zk> [c[(quh]_OBѿ+ DNN!>-s4fQN$ذ j8;JOOp1ؾ=Ҳ4tzAw)))~: IovL0ǏGjj*oߎ>ӧOرc -Щ@A]tf̙LRe̤즾02H*)Z/I*?@!N7Xdϯ’:Xc:Nfq-F,bIMݜ(+Vϟ>/>n݀s!-,i9bCodd#.Æ.!,r@wsqk,6 ^ ^q^pM%Kt,J`ؒ@Ç&J[Z(NI?Ѭ)SOh˖?2Hx ~|c%b&!c)W6 Hw5!թkϠUX,qXʠufOcI Jwa۶Bhjm;9lo@o@<<z$'S?Mq1 dNzHp$1hrs vc):$4? ;97̠ Jbž=MD$n׎DzvzsY(qXc2\XwY7֟ N{ܸ؟8ˁu6 EkYͥabB L2h T %ߧ}l I-V[1wc},ȁmZtr2} ?|X#5(qX*o4`}(}l6h'Dz@[X0 Pj8xsX kWg7!c"R tIh@E"0(qXzcJR(v 8C(+V ɓMDhp۶Є] ArkqJ# Bذ[,:Ky8y֌H)&a0H]&[ޙB5A[0BtncAt&!%<h6pL@J7 Ŏܦ"i1V ZChA2ZaPWzNzyC<_ ?Pwې!7gCL DpZ ZġQި!((؇0 t @" EB4-U:ڞ@''S}i{Fn.kh@;bj8&r @ &O[D@ ҶR8 НmŎ:hOJt" ҴoCzvU%39RMB}{ V^NeŊڬ 0C[(q@9h]A bٳݮ]lű!c"R tIh0h T΍:8D-֒@emQh_-B6.7֯  r2 159RIVSXhUڠZdBL m@d'NUVVQ r'Kk 159RIx ifȠ%M裷9)Ƞw`/qASGp`8Ƞ-бԟ6Ĵȁ-LB MuJWaB!,ڥR+YYYX0-q|=O;́c#ڕ>a  +W{RZ†H)$lZ<֭'tJ vb `ZVss?6,9,FZ _~IIb߿ 159RI@DqGxGLmjY6)q|Nu`(qBlҥtzklZZZJ.q0n\ &[]^N5TW7܉2lȁԄ't6vNO7Ƞ2Nl a$4ؤ|v)T//#pAEٍ9R333j}Y6.LO'aD&ЎaATjݽĤC1?ݻz5pF -':~S1)+WkB Fa߾6F#lTOZ-tp$'x?6BN!ǥԇ>|8УPH)YYYm 6. Ё0r$MP8؅?] iӡCa±(̠Rw3h77lȁ]Sӄ={H$MvĂ@yaucz:h&!KȠ@ ƏUN={Z@^4bj8&r @K3 m7}tT) צMe㷍 zH֮a#Z?6KYqc P{B7p6pL@J>rQI WCܹKt\z24u>Tn1 :9WUKI 7l3nTaCL D={* LfBݹ30zti!iu54*sf^92 2GpS1)½UcQ`A$5Pd_t {KPàA<^&!@Yӂc"R tJJfrp EʀSu.֖i8Iډ-vMMe>6~ aCL D#꜉  `V~k:?} 22h&csCu8vI(DŐAYCd;Osɑ`CL DamCbW LN[ouvk&SWK喋. ]q=i4 @LU`CL H)bQh!;N6vP¦Qx%@7EK I5*IJaa=@:/*]{78;^#6pL@JˍƁ@O6U۶aq=$]Ohb2~w'js\Tt z5%#MS1)ZIh;*T v)z(q@ PC-#:̛GIq` ^ 17V.BES1)`glCd Gxi:x1iO~^:&ǁQ8v,|V];8?li1):3{Po1@@;`2෿x~5{1?zSSIqA1?li1):&-z5WנU,Fr2ISo9{CCNJz`xa [Z 159RbGLkl|5xxm.&wo:F,aC7pVXW\a2[!c")lʠK"cCSHKKs6}h6)ít~{UALq9Iȁc0q,oZd 1?BKKm] ܌ލhnkC`8L[bj8&r @;6 @MCCv>lBLƏ .шc7Ý6͛:bj8&r @;6 &j5g%+d},&\T@卒${?{Yӂc" A?8vjjj+ 55wF㑜^x!:&!iUG @lG:dk˘]I* `uTS.P$,.))AUUΝSwމ}FFޱIX䨩Yn.B"mê@<;aGup>[ZiVԩ1ob5c"q={G?Qכo<@~~>q/ĉLL5kűIXj?\W”,ZrGzYl84 Ӽoe_OjV`CL D"裏"z AIIIXGӳgOD-SSS bɒ%xw[nm D}M\K P[flCU l@EZZPt0۶Y׫+{#b|?Y޽A\q9 f,>waɒ%ӟ*|ㅢ(+ Wf͚\wuJ0T6lؠ<ʑ#G3f(fR~+ M:MoIQE3TVc8}rzM~1[.-^L.{(yg7*|gϦ[?uzxb'a djXA~v} \ 팮űct6`CL Dl$C`ځ@'$\}5 5*puH)Оh2蘍Jm현b؂dg&GhOKon؆j6pL@Jy&!Y ʢ+*(͵Xu믧xf @I -$v76ĴȁIwr44PEnCvac$ʠS1):&0haŚQ5㧠ԉdE~D͆H)Ю@w0)J553 v ǰ!c"R k&aگ&!`\޺z%?li1)5Pkh/kf%A;]5~Э~C 159R=5 QI`>:ci]5~F7ߨt)'Mr~†H)О(q-(FF>lWҀ/|9r9CS1)ZzP<m-sUC i,_:nM9<[ 9%6pL@J$4/v:~Iخݽ!c"R t&&!A~<@n׿V$ 159Rc6 tqxAqϞ1Oa!-f 9,Fp^†H)1b,qOGu'zmzx bj8&r @lT横TTK {wg `޴ 72xbj8&r @l$ЊYP,8 IJx9;>_96pL@]c6 i!X[K}^qm)=3~ bj8&r .IDATeI0"^g&Ai<{S&lhqQ1):fH@Thl M./Ə59R]1 Z|߫Wo2w*qlhqQ1)PKc0m]K3ttlhqQ1)-2;f ǎutlhqQ1)30-2/ki"Mц㢆c"R +&aϞϛH6 ͥ5zGtE DhWLvIƨ1 ;"~c9g=8.j8&r @b$č^'ze񎟊m8.j8&r @bu~1'\\ubGH9*>,X@喘ֹHKKsqp'592v$":a8W_MŸ?p\pL@ -yshzw"%ц㢆c"RfЮ\@O?vyƏ6592v$,(eGKJ{㬳yƏ6592v$BSWW_Nђ³ôḨȁIDN}=o`GHYp$.RSiڋm8.j8&r z2d<ݟgr-ꪫpСߕ7L/? Bxw=_qQ1ѦJ̇ ^x&LP?~8VXW^ysܹs#~p{1c}!6~踤{Y"p >}:9r999~a޽oiipА!E G^ɵrF^To#G0qDTv&-1UUUq>UḨᘄj˜˩&(F$=z-}ٸ( y3 Fs=]w]0#`ӦMoyf<#HMM_:CZfh"L6 sEee%vJ>'~mhLTWWO>NBk63駟_W,XZGGTբWŎ믿7nlK.1s*68qK|D7߿[gŗmTCii)&Li&̘ŨGũڰBǎ$hٳ'ߏ^z9SիUW]3gbʕҥ)!mٲO?4RRRСC92CJwŧ~:\NB 3g6oތYf{wߍ4tMLBaS 0 SXa| 4sRtR<#())5\02͜L<ɸ&@3'-Cff&H 4sR2o<?ǜ9s&a1 Πa| 40Oaf), 0>aƧ@3 ha0 SXa| 40Oaf), 0>JIENDB`mpmath-1.1.0/doc/source/plots/gi.py000066400000000000000000000001411340375245600171630ustar00rootroot00000000000000# Scorer function Gi(x) and Gi'(x) on the real line plot([scorergi, diffun(scorergi)], [-10,10]) mpmath-1.1.0/doc/source/plots/gi_c.png000066400000000000000000001606011340375245600176310ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxM%IV3sEd&ŋDuMU ,hMWkv@bĎ_H=j5 !4Zb ݣ*̈szaf~>Y )<ݯ]5혙3?~9c9ީp2s10c9明s1h̀c9xGcs1;3c9ј=s 9cw4f@1s1z9s1h̀c9xGcs1;3c9ј=s 9cw4f@1s1z9s1h̀c9xGcs1;3c9ј=sFw5oȏcX L?s?p<~_sYA~/"7qss933[[/7{~~ٟk6 777O0Sb钯no?㤸*~mYƟ(c58ۺϲT%]\ -yۥkrusEBLPXWj%u`vfuZcZՈ:Zj~1Cjм,@6KBwD٣ݡ^. dQb, KH\vqh0! YC)SN#GZu }g}vby~w6_ɟI}}A&_KZHNqb7׾޽sًa`WZ1E׿"]дh*??~ sE9vhj^,LZ`;VGCXAXc .hÊqxx‹ָpabfs;;vxAszx|8;@6q\` , 0Ymc,NEy0{@ sE" T@\AR' WL} {=&{u\RGK\\0`[dn <7 ?ص/؅ܵ;* :å(}W ˞?=6 O~!U<_S/xdO¹+X>2*vEKJ8trn[H!f 3ٛLRE=րV5E< J XP#ªVfO~AXX%aRÂZ<3՚s?,!\\@ lw FJTX]%u??:J0r_<,|g/f@ V.ɇH[I~]H݄dx;vҞ~/Xmp>>JusY=+igU,foFey5_FۤkF+ %n ( ²+BL߃;- d"ÎepI#:@ P'`6`peȍ&P]8|aKWD <^/eJa l%H3P[}z6MS5:6>zHW5'u36 VnC=Mz8Oir9Թn˸-O$VOg)Ac8['μUC,& `GB}3&SCh-phdy^X+ R(YMd"[|:\S˂e4j1uh=^]v#<`m %4a,v 1 ?1;/מs]P u H*\{5}ZYy =%/OnvI=3<9v9= w]FCeٚȻbeHk:Op6G.zp13UT4AX\%8kUAUҒLnz(-A;{9})0M۱r|rp"Y'w΅ȥ4?\."7`۹hðA*ndo`5VN B6J@B4TSfk*jPW:kiq@X$h+FX\'8#@H`B [x:xpį|Ǹ^k{⍕dTn]W82$td񥖠?Xa^X_tǚnsY>D5]XX ;8amTrrA-w4=3a&ԬEYXY`CT ;P)1RNu6Xk< UpCHw\Oᛨ;6G?Ǹ|sfOkrophP<0JţՑJem]UiݪQ9{ Qr1c*2-AwΞhdARihttس6@`oar0ap0.:iBuZwpq5mھÇ U,_#lL@D7v7bFSgIƌ XPcGùHKP{9r̀^ǴM*铜b#8j='=[sNt~+naQYQK^gUC٠k̐ ^Ag_+KmS@Bzd@*8V{Zv+ WU"_'%)j\Zxm%&Q}N(Ϩ.p4, ckH9*s4xXZt<1SJ b>=NS:'c0w'M_+ё`},UB b$s km~p~'-֐&Y§Y5¡L u!xq#pZVu^(V'`W tEsn Vl hP(([=Ƒx /ZxN jrs }I بM6so9aS^N/yq x>+ҏREgH VZ3w;`;WJHA?KvªdwXꨖCk#Nkr֭c_#-%sZTBEFU-wC[#vOn\#vpcҖ\QQ4FKtX=3jê*^!sǛ Oy8Jϵ@ou-5١l,[cE g^tу[3S◹| pŇD ]kg4*W$8[g}XV']tZ hA=; $TjG˃5%vovr!-#< "@`QI%cCŒ% ੍mtF'hTLjWcZr`rJ8@CiiY"+xO0 kQ&NJn ܚJg5\ 8Fk%r/V! CmQY5WP%Z܉.!=ni:3˘ \xpqa<訕bq{}pÁ7ñO i$PPoT8pYEI]uoKWpm`ж'ވ+Y@ʕ4~>q8>;19xrl*Y U2Okm/Mx`<x\ӪiZi@bI)OܥEW8chPzNAimOmi p Ӻ==(g;f@86>=0|i.E$]?u%sͧOAtCۆ/I}J?b69 aUaua5kh5a,8Igu[RzFVq1 +Y" PJ:@݃l#n kG86zX Gh1/x%ƫσ<n*&׊JKh zˆEf%=t t.02;;gkLAz4csujszIXcH"EB+nLyڋQ~6`@Lzm,?51,EtQjԪw- JzRw&Az8FCz\_lRO}҃ \̀>fooK~<5zq!FsGR0|H[N -!C=Z\}lYAgS9pƑB}R䜞L8vfvQ|PˢRaeJTAxLͱ`O;i $#+i Q=Aֆ1]Cɢs5jz'D #·Gn. KĭVCVXXBXw ;.Kpk6*gN} X8bž1ed4{@*:ץ765>gH}&??(Q9U669RitS`&Scq-nApl'6Ng97]is ZM~n26<+iUB`?+Bt>mlQ uv廀ml$$Ȇ YħFG X!@L2bey6+An'k1]0YCؠa wA p5[x6WFhcqn ELh׵!DT5}S)T-pgGGz [g~|']As$T }ir RfG otW0V ks\p$ݹ.Iy`:AC!h#0Nݚ BI *Zq$?:rsi Bj$PIKXu `X;8>"Ay!(_Ɓ!\r1|w䖻]kܷp4vG}METJa`cCg^Џ:7)vǴZv/䞏c_U~~ OOpss׿K8h8 vRdذ6Ȯ3 M|b'*-vW9m[ty$np,٫p I ajbo;oy(qG}hhؠ-bZ(TnY+J{O:wX )#F=bEWRQWrE xjG-p!-W \}k+Gx\_úd5D3{>}{]{5v^kpqʝRmS xXW)`3xKx?}?.y ߞf̀>??~M˩  .U/ۃ:_Tn K_G'͕o@}vv樨qS⻘ <k<qVI n0 FUP'I$E-=(nB\eA: R M7'X.!\W])\9<BIo}+L1G< e IDAToy8ǽ!G*AuXQ[]ؠuWa&^Sq` Rˌ7>Ye3?UL-FWyb<6̽4(\|{m]]GyRVKTξk4*<6Pҩ2V{7X-6*=0s>tΛWa_w;bWAC,gaE%/3E$;i4ȍ`kA*Npwxs ۆEXY!=86`77$S7GП(DXyOذ=nWؾD?\>7_yK?qmR-U\\ԛ vxiwTX5;Z*Zcd=@θ;+(QlQ,,1UcZ͸wUMтr ´ty_\Sc7_GOo9f@ffPծdzVh\459պ^U֍{VG"k4Qam5jȤ8]ts FeK%ES@J }Hbj/;.hijH^JZsA ݝx/JѬ:@lpppT5qJ@4T >!qs9%YF~8t27LW~ ' `ET=;uLDȑ6:6)Q<u9];GLcDh [*yuxF#+YР,-є-.(`Lno< <+*6sLiCQ򃻨s]xwZvxקM# > #8etL)@OC , IWڬPS4\}EWR8ITrhxg8ORυ讫 5fC\h5Kid;òvrw1G;rLBQYq溾܃S5mڰ8JR+yFTP9sBؠ"ȵr< YVsjb-!>ʊfS.=Pۯ:1D5!Ft1 2󙴨qhcaw2,=b磊XED*5p^caRҖ}i:uH-fBFT1JZ"A:g] @}Hkҁ:t /\|"hi +3>>>DH=& IQ?`vŹkE<֦<`lMäQdĦ OC+ H%#MlbrFEVN)i9I36 XB:tҹi'7Pnr|Үd}Ɣ9/grLIg/ sauE^tn8luTr"C h&ΞP⭳9z8'%mG9 M8"W +apn8 17XFHz}@ᒚ M-,eءI6+D]DƳp5Irw\3-S೓Mt'q"Ř1g9U‚]9"*+\剋u:ϐNxKM8 $#5]Qag/z?gݡCMeuCZgsT 8v5[iIIk ()/僵yEH?WJ`YMgڕ:= mrbwEHmX81X;t@4c̹ p;b{u uyTwmOTl'1csb;7nX< ݲ]k_3d@gěι,˭ɱNkg}e ~ f:Yb`^ۭQ[E.B:In#%%rF۰l8d{reoao0?,p| n;'@ ^nѰE(K.P6pXᩀzHQ =4/8u}2i7aioku1-#j.U)6L`欠DiA:d{C]9S@A3VYzo<чc8Gyecc_[\Tҵ.Yhw\I`^jrf'sU$ި%%m5$%m }l{i9p.@IQ{j-l*V T!Ыi'o-dO`a")u46lgqQKGH%ӏ%!ݨ4)ʽ>9H3?QtX|Yge1DG@XE=Е3KH' xKM':͑h8fx&4UJ:GXHY -pGءPۥ4٫IM}Dm]_+#~9u{^{0.l<Ի ̀ K7FܴnD"w)]5r#u1.GdK Ѭdy6Ց9{cFfָ .}VX:] hNssTؖ=G3?AԊ``s􌮙,=t}򙳷|;"mHlY=x g؎MSls=BM(輤2>|ѩh@5zST蒥WG>HRm: V+^Myb%9o>f@?!~~~o&uuLޔ8W ?H~(~U6D{뭎 {@o<DMU(ty.'ڪ ͐},2v]sxƠMpnҿBz0T6p+5mRP 5 u?rr^U┴[vބ{b B7X9|$ް#@E39r)h"aȩΪX44ѐAFGLxˍֈg#8)zúRO BW #hȱWԡ 5cjZ ju<ry2} yBG# 3{{@Tn_SmdhtNsqOܢ-|$jD7*٧0~tal`stk et${^VN3K%4`m}^Gt쎶un>I6BvmidsBPVGP[ս61YWzcJz`Mm,/A y$D2yXsC޻9! I1詭&P>OO28$j b_YЯ|+|+_^Gρ۵l4h*iK>Wt7VRtš*G7cяa(Ƀ֖_Qᬦjq%ZւlGs͑]5k$G Go1QG-.|g)@]{#>9%l;P!T"K-{y`+GV" @j3tƻ@jY,z^`*:0YQٰ  5qLUvkwyJ_Uެ;\OTS~ N3:2~ "$@W7)tBAg/޻C[}{Hg%]ە^"[QiC?Z-Ll6/u۪IhUt*>fO_^B`QFao ڧI~ű T|7G79/xwq"uЭGGRѺdAY ؅;4G|\o5 *VASM+ܣ^d5O|08Us1-#:Y Id"RJDo0;a< |<6GF :]K  s^ 6GJШ7nEw֞.4q46.--WKCΏΏ<"N+OVWZֈ~̎dc:ׯ^E k6fY.fXɹ-.<¤E &.h+> /ٶ[7qAsxT,1k.:u_J[#5MۅM27Nq\0}0#k${I%ˣY͠POmu)majDˠY ]&=)t~htFZEdvJzDZPnu1ZP+ĿA 4X O.+ (Wwp%8_&8?` & IDATuZ6X\bzzkۏy8~?QT,ihg.%r~3}zl ٱ.8s:U[ 跌8b7h}hR\npoˢvi>l8s]L}&#SkqPY|hI9JIomtk07N9u  {OBTiEq.rҩH(Vřv> FVX=̈6Gb4f T)koM9ދ֘m! ;.:l`>}y1xqg?cS[w)1-#s͑0lRrMG]|I-F @2qDP1D:̗ls,a'^lsX1W(YEُq8͇NJqJ]+"Cb"ްht*zWrIF e*e~k^=*^˾c7b;{by xn%6#Əާ :=>?٧U>!c[Fl 2ߣ5abZwEŠТqQz#٠0=,B.mfSVw6 bH=`XSc. ]h?Pѕ 3:iP\tj>8FE9E\O$&ã 뤞w%;=ߊG>Te 6-fҀĠ!$3%  !@Ȉ bdyM,30e`tK\s-5צخSu;_+"3㸐Zr"22"3N_=VšFiBrjf<@+ kt͍`J=joR7q|  Y<6Ѽgw+}9&,lj$4XoS#?ƤnAgUgs${ӂuq'h[]S/Zm(t%ŞUI>~=c~GQl/2rN!B&*j٭"@Z]Ŕ;沦z9L`Z;s׹T%da/ݜǕ l*dY5s+`t°r@>h`>9ǎ;r}a`w՚2;,NJ*D!vjj(l'ìyCO5,fCkq> Ts6Gr]$&k5%7~X[I+k݌}pYVR׃VR.oV?79Ŝ|&rrT:esxJY"ng7h* 鎞 t :MZ@7O;D erh>p^Cl 88TB'\tk ERa hzX{MwsCV@!x6C6O=#2CYhe+[}O6 T"h%ЪM,(3"-)Y ?KdA|*fL;8r}a/vݔU! FssfX n˚HCR=R-ۤ0?GMOIq&Ҧ@ўJAADZCү1?[Ws! i 668,6M,yyZ`S:8+'Wu_JM=o.{(3Uf-J|Q~ܠ`>o]B]aؖUmitfU=]c9"6h8CA-]tLrC;)T- seTcrvG8Y7[9itRѱw;ܑ-6 }> ؇6z`o'p/Jų1u}O9 Bߕ*sjb1+%)h\A1쀮-J ֊Q$w4x8oJ?&rqi}1v2cd1m8b_^Ͳfki抨 :ʆ.$ jɁt;>t7hOVw%3@krISľBi]8X1tw*2+yf8@`Gp.#UY<-C|qU96(.~;e, C]EPi05.KH#z;=N鑻+cXE#P>'WAH{U蔬b8:S_辇HmCt_MEw C'X"iTUCGTt&6ǐHt#)ho[ЍG|CԦu \`Ϊ6X0<8pXXGzc:.y:t.CuWКT{o=c7v )X֣UbŮ>%Vj?_[?5(CDG : V`r}l`E ~그ݪ qE".tR+TtjEUʪ ȋ jUonW4̴& It " -R4"=)-WA=| dv^HFtWۇ N# F#v/3(,o>y`*:'}vlq/ښ(g7Qt<,E*T Ҍ29bn9QBV7*)w':cˣSm1#4J\,MEx[򣳭1i []g JMK45.e5'U"n&T'gI68 x8q+wW~i}ԧ>ŏQ?s0J &HA$a;|Bb:SNWN@N甲9:O(t&ZletD{ꝵGFS:)iT{.RtJURz5:0pZ5 qz؜f7Bմb]Ё첊VSH$zH='?lg-ʹ\?ﮔN#o{l6~OwF.s{ET hUg1Egr0Pr.(LS20+,#ڧblst;]|,\R氌I2e#KHnH[E@2>xo{fh"kЫ޸$dc; Y ^t6x΃Ol=(5;6EUNZ&j? E GMRG:_{x BEk'VRYIP šCE_[GsE"A]޳U[5͈UfY3W J$%!-WzW=9|_ -ϑ?;JOx!yGG{tܤﮚo۷'@sD`Kg;30TDAwk\hWYtvC]G:b_uQ}h|+1-XC|tFЅAy޸\`a@agݵzytP\a9ąd]]Ps%{ѴGey=)Mz|XI>vqsQ|_..;tM'@{*lU(]͊ }U,eKM*WКdҭ"H(/q&EɷͰRLߢWT}"PHBuv~L2YhM+X)tdV)̳9V:Wj\5A; iR ]u2xx̀g.3NP&6W$鮅(]A|>}}ls}+lrU%IٌP=Ra D L,gW#@KC$=MQXZ.Yϐ 284<9 qKK h8iMeXP驵:̍B*ʱltv*n4:?dsymċa=hr*z8^';d\my}<' '@sD a+֐RIߝNa' ]oxbY+p"ݷ8.}IABLʅ&G}5.'9U33wXb 'nh*\ӸbŤBM㶵xMq)"PV: -T*{8Wû`[By!i߻w;Vh1e|B ON{MQŗ I.ta5-K7uo;!҃AC$- mvULuurX!xӫ$au .˞H ж$nԳNZ he ~b@[Oʺu_|.iv?zCpܱi3۔ڽY%o3l_oq=G@AKLHENa A#2ӓq y],lY'䰠yЙ=mq4Rv8y#?E ss:]qw¦5C9UR95޺:}i~c8^h{aL,|H><'&Zm'@{ k& Zwƒ΁Br2{om>?[nzϳ-ଝ!`h%ef#Zы\iHwb{ ӼM)kT/s44.@lcU,VtfN:,-tSb'bT=-X)] }̠q4žnZYYC>Ƿ}q(Y7--*Es097B)U  )zE :ha|蚜{w$T;C  :ž'dkVst?ڭyZRJK49u4>l7tE dtf%ge C`>9kt4N7v8?>Ƕ]{9yKٰb &i nq'f% 6z\r. ;zVnݫbeJ;iq?8?] }V> N οTOԼݾt!#@K )Cm(deǦ7Ed-=A@N@@\ѣ2 % mp^@-q^׺+,olJn.T jRЍ=TR o8҉L@= {C뇖m;]v8xM{UWZ$ MAGTvߗ=,g@jUH1Z(lv1 iʌ6(kzV[N$yh-1ϐ- NHST/%/ΞAи~.hp^FXScEʥdű?hiɎ@z[9dÏ*~v'hz |w7Gx׻M=oTekvl8 w*l4z?fn O[נVW،wQt-&E 8פDC̾AA[gJυ% @ kIt+mTmǀ|S p8;O0'>O#?#|~?qэwW74&jemr@X$I=Լ} FYek`L z F Q^/Ov=O'̺eE _&Mzr(lXur[?ܦ6u4Jc7{84'˿_|5®t~K?cӷ\kI]B| 'ŬunzM =&:L^!@<ἂeu@Bp_9{e߱IBtW1T lAzo%Ɯ^yf<&^Tpz0.&ut?3Ϣ@ +Wtz"z'+.2P P#e8T cQw>~8t_/?tUUg>EA.gh힧^݊UT֯KP*TW ^t\Ы5}F6E,*kzЦП b{̫#V! _X@ (9]SkEGE-T൪A_P͠σ<J` ʉeZ*_7k00bo7N*vys٪H.V4q *Ajb}Orh,4'u<Ӏ_e~W~|:k<7; 1?:!us-=_} /Ax PV\W+\+n^}s' oђ@U:(bj̉&ܗiB^nkWl^pT[! xʷSGlMa‹8V>zx:+_o<~xf?| _1F{9~~NpxAw//~|m \ sOߠ{uncUVG5WXN__~,s=gKzxG_'傆/SשxD%!tPRJмEw;mE"ZYX]T!\RG}ȗ%,y sy@#/R$5kGj5wa p!-~Wytm@xdEDsOw ƻt Z+-K޶8 3ゖR#7B"b%Ȅٷ't6>_O .˂,sPW@_캧|go<ӀG>=ձ??@ :+W@&T_ <\՜I$pBZ֒+CA?C./ .KPChLAfX25k/+5Ss= Z !T]Et <ޤ(ۅz& U6# I87PRo'^6]" vy- jx)]yRx*(-5-BMK%s6/J*ށ1$DQE7-Irl㾠=<Ӏ|1 :v|L}{̓o; j BmA*'5Cfj^ OnB!Յ0x(pI_?!RC8pa.A J@^ .+; k*TlfbKK zp}a0DG h*1K+9 (67*X{kj)'yB_7.EiT/AV^_OcHKΩ?R{zظ:>~lߛwq3 +f3yܩ+؈\̶sQ@C %Brv.x9 rBz6 .:N"*N:=$sQf 4%>ՙU/ Gau*r94fmpLL-6& ^ \R]*B_Sx.DZ\-T&8G$uhZ'/]N3sGys}ڥm;vN{`,; }`<Ӏ~~u}N ӫ)؍6f9g@mZ9Xp)[KmHҫ0( ȹD(s" Ph pi&_ z1ax,1\!dŒCgZZ-* |1ȫ %\.wR$2_* *6nitb1Z/Zp.!]dF1x@u۴è{}֏)T 1i@CP8 PXMSge9B%t hfL Hg.q8. kՀXEgMH) ,si?IUWb3p,=f{ 93,^ 4nPa )"5IT)V(nTZkk\=<} < ;!αLJCK`;Ʊ."5:L:So~HOΊܶ>T.<̇N&Pnua@}08|_՚4̂ϗG20:ye3bL">s9i*Zv:\TB[Y@YyyZX`΅uB;fR5PUjf I L"}Hg|ZZ4_'@cvH{;] Um3/Q@G,鋜|].V`=.Zah4r)hu:U6Ln)4󷌞V@t?иl);$l#prN :zv@@gT=@O-ֲvJds`/oc}X?b-i!-.< ːU|f&VMqDS4 f3{5;tC^V~d8a,90SIj^-<&,.n3 J8hLo|h 5׈+LA:Z*"+tD8#z,=[fAF /~ʊF*INZ.:rp:QKU|ƚLPu<&P%@KhHm{ jDq4F(\ mvP_ m:u@d"JB5vHJ>u ~fiIL6w@N GlFWk ,EqF`Z`[a22g, nsD6#gyh,'UzD9/孑= 1Y)C.%@e(˰ʾd&ۧK~%=w{ a8ܕFX(.X!a jS@pm5rFM ܤ-U]AB(D/tzӀA9@̃+|ϫC'P407%n K[۝e/|>lsV!vQ ; LT V`r{ -%ݷ:LQT!H3ٖ>7jȧqt}Qawcħ,fnq$:'TVXfUʧb2m]\%_,M68[9hY 9D])_@j:~*zr\Ut+ĵ@E"pr%3WɇneknuIHr%'ķ:dsvš3yNrpKVGjO}&i]SϔV1}8#H`Ey"ԋ' gÚӬyL;t*|aТ-0ζfV<@bBRFBy"ѡy3O AK蠢H>:q0kq@ %zg,ûɖE7!gX~ 8h]5$ZPO~1PtKr^͊ZG=RG }P)c= cˉ a R E\ꐾ`CG= 9pR ʼ!f' *[_H +tx0yI³}KHE M:Yj%N [>yl-y^2qFAșźRczK#lŗJ, -9M\Фݡ2-ys8dMjOSLbZ<6RԇTYcdm 7Aۦ۟F]<=AAp6VhfmX_0(meFQQ[ ҥ.C0lFfsbtBp^)g ̂Kz_;%%CzoPDǡlE٢ACĭ)z>L,a +,\JF456(UF>[bH=JMOW\gA28p$@AJVb0@G%fF99,HcvT9wrN*U8˨jVC"ca *g٠:t&ę殢FV դaRѹÝS8'_CG G^3L5:7n1_1qq=GPQ_ZrP.ge@kYsYSz=ye H) Kh~јCsV-F IGoԚT,CZ% aw:[r@ 67BEYtc@f&:bۣRmEf8VfuKHqZ&ܓUF @N-|-Ȃ IDAT}G|p!]ku;M'v'@s,!\)v39Yc]ZaGHݥ%)W#Y-@%iM T(1@S1yPе)-ÞrCY gQ9 KPt-t Wi}m묉Y PK!<В-RE mINd9s^CJ&M#}C=P:s >73A36N,AR@1 &8Mt6!HX3tPDtTx]WI`o$ktDL(z[œvRНd圁lN+gW^Fhcg tRbm`aEvdDt\BXs<\AG?Q/]]U)zR&i4ojt gϳMB Zk9deiv8c!Ǐg84E =dp$iFjFUYNmABtM`2Is#}2{Ca.R7AʻѸ7tVђjNMpg!gH)V,n(MeőF z4kh:, y$\0f0ҞLiEz#b^T@pTR(% 8?3Ve-oz Y18ߤj6peX m>wg?YOd}1_w,=-&XƄiv -RTE*SڦT/1hšA[99۪5 B9ǎ|&2X&GA qkAhRnq+wȹ >wH29t=l{FX +A TdձNS2g_G92nܧ7R{g0Ҧ祭}6IE| ȯ]<A_^y4(J8! SЃ@Jpu k@_{aefŅ)*S1 Ee5skp6C1}ye^yl޳T ާT2 +,"qgvIE,@ X+$lys AΔp8HfGzٸֽMΗ)WԤd&7$` PSuPGrKRSjK%h&ppeD0z~T 'S³7N>0wK/|,m@ Q"d{ݬnq0rj-X]pzް?}e^BX.k*TU&IIv(=JJtP'uU(TfPGڈHTվt(/mIOM;6¹Yz.pav^E8 ^;8tnOl׽r0f&8@' څJdĒxބ*H9ATҢ{6G].>eXG}>{qljF҆AN< 6,E]YJ4)XS08Wfuad@EJB2{{2(C&GF;)nw6ی1؄l]=i;s[?K3A=H3ja'u+ZDQC: U|Cێ) Xj!OZb;P҇?Y*#@msG9y YAK5ڊԶ4R=XzRI)KŚE0+hE*K驓j,*AeJ썞{t^[6WQR+Uo[`'{^/\dkCJehtRUH%?h ?vT!Sޑ#'Gt'@sMK zV%ch"yPW*|]tLmF>*)T[|(![eڇ"alZgsGYEux#-\9`itm[VR""Zl[+=SB=5 &QrA1 /`U)OTy \jW AXGu@ [Q8PZYmT],XK9.ů4xx@}79P'f{#K;V(i^6RMSGK : ^W^,L=XAK aH$d :%dihg~k bz{)b#Aic\`Hݣ`F'CҊnו 'rR*ͱ`a vX0l<3=@-nS8:}$`17mc G B  Xq`ep 0|i9҄'n;f+i @joU}dCRp0Ϣr@A M=z?Esԙg̈ژNḆ=nmF L^ H) a.dP%/.`•j~\ }Y) W*\r`uP6͐12hDO^ٙ O_,Zz@^kr㦋J~Nv0:u hT\ǩnlkIaqh EqNj8UVe4vaIHs"äRk썐m E3j6GA",;=r60u|g/ze`x"b Z?Ge;ȬgW?>#4"H@l9В#Ӥ\9lI-9; qТ4#޳wU""#;`NAʌ̪_-qACp~RA&yg)Q% ZA.+8/MyO0N]Fa!@:@U}-v|Y98_M/ؼ>Ah؇%k8:zC&ʼnGb1Z_~IhULŞM#8@ lVlDoBZUeҝ]]w|7JFs[kq0_E=ZtggϯΦgۘr8c Hĝ3q'9H?qDat%hDk^r%S1S*¶O7KJa)%&UW_`>(Cff˞Ȳ'>?_jfxAk84!!ifωzEސORUȠ>J_~̹h9PDSD 3K- @ǮQl$FtoUڀ> {NR#CŞ)c`}-Yf4Zn ~  -}L7f%BꐼDy_lf: %P+=m%b?*14Wh͠;njڌ$c͠VBIH jH Kf-V9^blE9ɉ)ES:31bϪs؛=$9aAWq}$Ξ`P/bHqϖy |MK8[0Iq_y`.o܌֝Ef#vaN K=;P[ I) rZW}wݖg~v<~47ۯf~? wE|`_y t *y##h>;ZPz,qTUiyqВ4ڑk]gʝ3cJ[79`,PϬkZ8s>qsbT@2{6-67iVMY7x -Q+|!,=o[tknnI|#lT˳^\6 cwP2//+j#y{y`жY!.020Tl9蝭*wQ)n4Dp/iHybhRV=3(+r2O8Dm5 g'cax&&MnPe{3grvݹ1M&=-a : %Ƌ4[*uA[ѿZiR|lyf#>9c})㫙tp?Uwhti)65@GWe۞`?B pY~:?nO3ڐN5Tu!8@ÂPiҬm~̞6J  Ax+YE28;NI/3g<8ns;klE5 kHOi'1b6l̢ b-;E/ ^f3\TݷW~"᥼;~ fX3HYjP&-s@H IgY3.LچRx]pHlլb CFaLs. kUnGmX/̞-M&ci{ࠌmIk~M[o*G-vԻ0aa]IEĢfiy O[x|x=-3>oH x28,K۳`6y-,_M~)nh?5ZbP*A* ݅E^l*9#yib1gP.A5~ctQߛ/ow13hϖ.HC,֪\O&ݔƱmY~y(6A֘S4$3gPl)'3*^xJ(/>/1GilSlͣ{ؑ9(/:tpp~Jp`~P֡NbgK&9 H,ښ%KP=v] ΁nqp|-m3~9.Ͷ#t-=/;ߗ-͚Tax?vol3ažл EڨAQ$P籼CY)aL_&!Y(~ aĚKx cF bOwb*qE]Z*$`aJd P'`Wh{lt#+#[<x@^0M#d66D;Ftn7n}ۀnm|&Uib7h9fC# 4ObfI2rv9JT_e@4;an>~;76f˨:S̢(z#y 5N^vS~a cn51Yv z`-X9B@5-rkŒAl/:bxv֠=#6;+>V*AZ@`҆QhZB @ω`&Jya0c!Xmҝkaֻ-k*ZhGȾlq$xh_֟I iRgΜ9[n ]*uDMjn"6xi9#rș0`GTD{=7j ?wQtk9P~kU،Z 4y\ibn5q1.@#R>J3OecoUA 9$owpzsHR"Z/WyYP3Q Ca \30Zxx6x O/jhX!='9NPA t#t] j:b-vi".r ę`fwD=ێHn3 3 9'o bIw>l!n}@HavVM*t56?i ,kT3 0K zRjֿG]s0g aj;I0Rs2darƬ]bλز5 IDAT [MC0^,gx.lh7&Cܠ ,W2t!/vݰx.gpf-Xuz GաXK857W+z=Tö/9 i<)`\{öf=]{{mso ?ѾE$]TZDB*p>~yeO MlIHV٣!? '7Pfk`E6:gil~\r1b(w1mr)87 `̹+̙aXĞ-؆@xwS}9`XTs5?m4 Es3Хh.gq[PZ"'Di)bCdƖaz쑞'L/D^fͅf 󒓚P[AO^lL;hg۷c~# ?_+??-?_O;db@_IK1/*Pz[͞qoCsg {f4)Ѧ2VjiBa9.&ۏ c޸޼9s&5̹sa8g 4/LZ8`l=cHG1#2Cs6t&.=s;Xpgj8+YGzCi1{"B\C\- ,d2ңyވ[*\9*RFͮcΥOO=Onvtn?y~w 8E4,(r'k֟Ee#ْpjFsOHIxJV5{5hN$o ,o2NK+Q>fɯCVIX]cPBKgv2M ՞]@'oYsI tep)1{FDT$9eazL`{Lza+V* q!HV0&5!c7H{?7obp ~v{l?/Ew.Ou̠ʅTXtgQ@3gcM7׸Uӆn7nH9yCJyr0`-`n,AT:,vĠvxƲA, ˈ-A @'j{q1{  3@7=_ avl'g2}гGvǎK%,܂^K![ V’FL7T˓Sic[2,g҆ki"O9M痩0&i}?vol;`T񻰟jf6$q}D ٳFn!I3oaZf٠='RK4LH1 XB:wiÖ5s/$W,i 4$ppR4ţ_G;Н9{59|kFl'h||PF3{%Kd+5 -̞謺-eR03b#PjN9 c32Tf'қ>{Դ?evWi$ΰ_fϲxTǤ 8kc͞|Cng4En0ҟLl)9%(b"sP*`Sbi>!k8 hW39$k&|%<%(eVtg%9XƱĉ% gi#Q9p\9 *E8CV//CIZ֌9}3g1|Ty۔)`rXײ)?@k3ҫ;ذdl*h-̀Grf陵 M0*b_k d2$XI-~U_Đnk!au΢su݊^Y|f"Ę9EjXb巖5Ű sNXB6,0[;{Vw.kpo>1xGҡ;}ށHpq 5#9} /1](4AW=ZPbZZ-@U-Z5xQ*UixauJϵv=, r2/f3) yvolΜٗ2hMP*Ϸ?/ke:E4-*FHL䠃e1$Ř_H%(L=(R+ib0bs58PĞa , 5`K\'Xk-[هT6Zz9uH3=KL z6::sn 8;{474j!HNE/ArOM>-վ70ewޱ}?lfI#̣~!7 A~s>CIA)9&Z0$*.'ʓ9hPaSUЫ[$9)Ι-*&onXkK;+|t霠4kxB=б7‘ѬFHsy1x}a)?4zTE%Ǯ90f4tљAw.F"^=*9.'ۈ}Z%0Ge*!dr"J͞A[dǍsz F Kvhhu6YFG,u%5 d|S!yyZsãs$p5i!rQtfϳ 9ށZ plWܔ?wDv8{%Pl+䬖V@:$Uvz=4̱ž#lqm+qּΤ \ l bl\O̹ut.5j&u0CH@%o`fAMpbjCf{۔SI"S&[ji֣vӦ oh`g7cM<Ř7ZHbo{ff쁷U,썬!%b9c=<¤JP)ugY-t&v :2PG68(BrS0b4[<]5*f54 lIz X$mDtYg;4&qכFD.`rt6 Her5&7sS`rۦ8'Y+zg=E/Rb#@^gSX:lK69I_6%= ֍#TC}bw)rVF,'rĚ#WDg\h{uwYcİ %ۻZH#u(Ot]BaΟw>7KrǫA9&;,0g&q`Уvl&I&24<tY{Ng&=t̞*f9jctvѣbωqSaѱL"sjxB2{ndPH)y]i:єZwN7VjUcDs>!LCKd6C:Pg ;-ְ3X20K,q@~DzĚ-XEXk\%iH8OyK T%gl^*ULGBkY.klq+qcΜ=.O } kmC1NhuBSbJlPDWt qpj.gn:~l?3BwJiz& 95X`}=orK2ǡvwڿ??c^|wo; [6zO VXj>ڹVarqlJob{^iYE?L S͚% )LsszsEvĬ&@K=c =33؋g5.X*U)ZWtYĞ)n!˥;|R6n_&mhf픶?%>-h/!E"|n]4p{ڻZ>Q&zdg/D:bKtۡ?h//˾[m~pA}@WW>DyX7qxw=-jrTyb4 Ӑ>7,$FSE)V%Z= , {90/rYCYkWb7@[:2 ]gTT3㜽߬Dk]QKHf?1ٺbg^er%[%vv9qPc'OD"s<7LKxhEζA`<&>i ^xgs[92,>ჵ|L3,NwtvOG=BlRP?{?k]ٳU,A{#>hAgL>/84o~!kV ^8HFE"ȗV}sW3g1伌ª9Zٞ@UіFӷKpd ܥMb-ϙ hm%P6p(ۂ:l8(gk%= &ՙ5A!;kZӘ;cuKF,O~o˖5XS:c`잠G=qią 483Bs-7Z?O7Ky$}J;/ oݳט=O<,HA1TQqUߡ,AW{Fl9fvowP\G YtL@;?{qspRYDN;bthHIKQ&( xiFƕs ݀D2 㔆h #92hyf LW`טn o`+Ö"E6a10تs2tKd$mo^fǥt{zTL*i^7^g =G\!x7+EH}1?'$z G 978cځrNPt3}cՇVl]l`kL(]v6"6I#]er)+]6`/i {km FwO(j8@y7ppf8S<75Uf5dg T MC ι!ͭ=UjuA8<;u~Y(嵊<-D?W:/2z-hV*Ƒ/ =Ѝе"&p^\Di(N#|hQ|@z`wl}}b(\m:t +ej~ybF76qCʻ=2&^7rTsmǵ}Vx;%e}wÕ&zĠ5ZMKW\R.U9m N@ǠYfV&{]8N+*?cȿ]7+wTLp~c%;Vhn7$Ԝ| kwHbu7Þ,1LRNJFx5H[Lߥl-"C,^ؕZZ={^R*ubՠKFM͑4,H+0nKc q;nupIc#q$-EqFV(~'B~AD;]ܣ-̈'rqmh%4L>R/=vəՆ?o"*Z(ń5 }}8tq{.O7N ;@f$OӬth&q_(%3zb0;el?5(/!&&q4A98k$tskE}آ\°1x'tkؽXzźMFxr|"8b^@=/kڣ'!sϕ|}g-OM[WF\5M/i5Dkʓ ׮#v&:~۝#yCGUI9/+m?BM^SYFof[PC+\\rYWIE_=BSWo ՞,n 9S4mīd:).to` δ +9Huq%-)PϠgىcĢU),kR=^ >^!]A{l3C'Nb6Z̸ٝm#"CS9Q\FwMख़5KbD@azpԡB?wUzC09[>:ZJe|8FпDwFeJeJx` o?sL[u/LV֦otŖk\G y)C& *=rl)3bBL-FL k[R ^ 鶇c<su=gy3:jMD;IiDgin" \4mc<7K  mu'!@O]pi1o{),٪eߘn;zpwHv/[b8o՘^3B,kk6llkZ{O# 79sVյki/9 zdF[fDZLs١z zŶ875r`0=%p {Nvzlкqp޴؉Љ4Gqi Ed-/B5]sBlOP !{+={vEL)(Vٿcνת_A%oo{j_qʑV]Xz=E3{"6_0e jV24)0gKske߀s)g8HG"k8ns 霽A03g^e`ϋFHw Z[5(ka$m<[nCȅ>rnz3mP*EBF/41Q.D /40%F0%4QRL$Qw Q5 -)ZnߠvwbfwgۥPJINf:sfi;gss.iv:!M*!a!YRH*FT{-:q?AЛ@%T;s77Edֽ}ZOdoT:gaz\Ϸym#1uc!Ba,o'sI+œ_űmZ􆕋Ү,$S"T0v$ zqI{޳vCDG(0x޳;"t!q.+spJl,M/wkn:ᒶCڝ!\$r]0JѪQh+z=#H$=ݓ@ztلz̈]^]= V1H$(HϋvU6@Ml{zJ|kY"#蛭ŭV7=h5KiZG'УE[(/Ixa̬X^q'UBb6ID!jNb" ! ۂX sjG;`њn I.F(Ö0Iq v,C'KB@.J@vK؄7bB UXnX`hyQK*đ& q߉nk@FߧSoB'W3}a~rx^,$5r{8n)(dүyݪS #$mW[B OduRH$IBX_@UMm¦fJ3 P'AA'(IIDP"n#2%գ#+Σczcx8s Jֶe˖aY/"mmm|7tQǩ8z\oXEr PVwd_CAߑfrN.9;Jq#W4 u8:)qE:39\epCENlKѩ!,΅(gab=q^{Ał+7~He_4Z#ڡGluKu1R$ ,ǾRNMCn!b#IcI*$UTCvMLR b$uqJ%^F\[tb}oӑ3·>^>3/;Dss3woɓk<#ضMQQpp8kϻ cغٶ?3on%@ i8<۶mٗe00@+V/SSS7[MMMyff 7䧟~oɛv6nH0$w^ &F4套^ zI=~>D"Yؼysl$ y͛fGkͦM[ŋYz5w}7/_f޽yu+a 'ȵ'G ,f {ͫ hllT$r}Yܹsn#OBsСC70me-Zihhӧ8^y'(,,,IDATʕ+u ׋ ;v져5kְn:^uˉb477H[[!s z05L]L?hm͡C`ٲecmݺn• xІۚ 0gΜ-Zd01`0LQm0 S#0E1m0 S#0E1m0 S#0E1m0 S#0E1m0 SFZl-IENDB`mpmath-1.1.0/doc/source/plots/gi_c.py000066400000000000000000000001331340375245600174660ustar00rootroot00000000000000# Scorer function Gi(z) in the complex plane cplot(scorergi, [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/hankel1.png000066400000000000000000000642421340375245600202570ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwxSe. -ANP_[_AY ".Db,+ CB mtݥ{IyIhif^Mϼszs!@;xŋYa/^xbxŋh/^x)^ŋ/2kxEx /^ŋ5^x"Sڋ/^d@{ŋLh/^x)^ŋ/2kxEx /^ŋ5^x"Sڋ/^d@{ŋLh/^x)^ŋ/2kxEx /^ŋɓgdd/DLL í%I˜1cٌ%KxP/^x۴i˗I&v>Ν;c…qa)ŋ!KGFFڴiС=ȋ/^܏G]Ѷm[RRRлwor @S%h,,6_ 7FNhҤM4AII v_R@RZ,)) ;v.KMMM7$ -YѼysYh__f3j5JKKQVV yBp̘1l߾=ǎŋsΝ$Fo__Ϟ=)Idi)Lm}L ٧Y> 'd bҷW!wIRuծTݤr?裞`GGAAAXhQ.]z||O 8|$E^=:+ 3yطOv׍Pn@ڕPv9!KtUth;__[m ;0v,в%goSS"' .lv]RuծT݀r7l!y=Rx \!B|?=z4^xQβ-B#hgR}}ˁZʊtJ (WRu.'i5K̛\ ,XL _յ;GZZZ!Pv]N2ͮ*\'j@7C GZg;owH7T݀r+U7lrB#肂S>X?jBdds ]ek4WիWQjvݻ;WPn@ڕPv9H aMN?#mz` ԩWjDjWn@" 5ej $SGRuծT݀ Eh%d Шp!pH*5xT݀r+U7lrBA 6̝ oRuծT݀ EhO Y3MLl+xQjDjWn@" 'աT|=н;RuծT݀ Eh +hc,OPv]Nx+ ]L6Ҳe@~@Ӧ (9TJ ([PZnAª-Mڂ'Ή<;z%}]ek4r :B!Ig`vJ(URu.'i$V __`];Q#b9䠏R+U7lrBZ)AŠO~8{2 MUSQv]Nxn|Q#`Z$rw*PrGڕPv9!q[(-HX'|?&A䠏R+U7lrBZAʐ$/.N[( Qv]N(@+=HX_*哆䠏R+U7lrB!HXW_vVj9䠏R+U7lr$t3Oy1햧Qv]N(r$X@AjWn@" j2FFׁᆱ<~+J^|~ݹsرR^wqjB+]N(@ +C`N;]}7,X`~^``6ɩ|$2=] ŋ3gu"I{^jwԀRu.'VzEV?<)nzbúuEz,WW̝ },<():wݰ!(~~}s~ q,J$ks=Ru.'i? +8Xζ""x!ۄoѢ4n*?Ap0p],o1rr7ڳX^bW_u썹 ]Nxtxj1d;'O.OII]w݅wyͻf7ABsfend6 0G޶u@˖Nѳヸ@׮HNLv0|h^V#o7ԀRu.+HXbCBBHcƌajj*I2%%zaøqk1b;ezI"{ &Ȣ"ML&:uݻwzY$WW"+? ~ ZߋϟgLmz"f[<:@6m۷GzzuXX,^dn >>O _/.a9~n[oeN{:{MT̒}@śѡЩx}Ņl/PHecboκlR+]Nx@mW>񩩩Vcm 6h[lݺ7o[o /AdO >.ζ/#gmѢs$""鋌.֯NC'Oe ޽<t" . Ų^IJ)SIJ@`[0٬xF$iy82p>l? Vܪڈ0w5n;ӼNhA{nƣ׷}τ%k`͑"֪VTj5\&d^ypX?{6RTBHbeC7%y9Һ!qѷ3I4wfdޤOtۢnvOϙGf2*+ I*REUsj5i6]ruf[| ?}H͚!(.NT`௿D3ui>"jT#=%,>P!6p4l[܍.ͻඦYտ!=>4\s e0kv<@k$"GXmX#ܻ^ߩ_"[ E]]q"$RNE@iUnw;^s/EhU0S=8nwãߌ"#)IdfhQSS6a0иp⇰R__tj $.~CU|{C^:ӧ|PUZjwvۛ&E#V#qy}OiVmo槷\a(}JJÞAh\}_JHߌ@ɖ胦>1QS=Hz NB@:s)S7~1esmCRໂ%uK$t8FCNN^ w 'L9ΦKN/kg7z`ntHktO7r6]JEj"7) ޽dvp#͚E;G| ;b%ֿSg2֟܇3ȽfҗI<^$.%D)6,,tқ4&fbʌ&Ȍv;oYcsǙ&Ϲƥl" /i "IMdv;vlEDD8YP ^:%lIyCד:i" YuHwygZq4RR= ۝䯿{kVRL6L,aIJ{NYfGHN$3~d<3g>ETx-AL~RfK矋S ,ee+_xQQUuY+xqEF?MvNx>w^vI.j?0R._&9+,)\bNBA?Y2X1N7Ϳ/ؗ.~{OOPwQ$Qqyļ<fW25#O?E 'O>GnjYqxkή˶7 $I|3tQ\*L&|dl(*9S?}CǬQǨK34.b[B,Fxf{_ 7Wk=E\K3q'Imo$I#`fh:OJĸ88<$9|O)Ji$9d6DW“'I|phƍצCL9r$cs9IE<:,׼wºyL"Zc̫1TEx(I:OOL[؂_~˪n"nV]9r:N;$9L-Nd{>&ILɢ"JduSԔޑuxp ,S%FE<+~#MHgJROjIkY'\LX ZڣAO?;l ?N_/^QAa||ylsaw˒X|] Iד2,-$9xh1h(_ flmˮ< x"fKr)h3$w-Kfݺ{gV3oS Dӆ-,U lyQQCu'b3|9y슻y|e>M.J?=j ZqmoRusKO9fPlf{{aUs9TT˨KQ4gI^ik@~\t'Ňm[H63ܺU>q±,$aiav7dB~[Ԋ¨x_v5sBrޛ(/JJ^'x!b [V4cdr2FZՒ/²2TG_;wtis+IodeKrcDM-Vg-`X̧di+U@s|Nj̚Xp$q,xfkV=+CbB5NQOr* I"uRO)J8#1;"ǿL,!m$~h' J%>O$IH8vM a_ZG9IMO?&Kj`?ۚPm'y ,=K.[&Vn([WL9dpf&iCOhSWt$I֠Zf i2TčN%`y5穒qč$*e套KQ2J"*V0&E~(5 5GU::/ļ 8-HV&>7dB* +l^_H;c5iL^Ҋ/Τ$p29V*5U<:\dn)?|6t6rrQ2?!=~;SRr [UU9S$It򫂪Eth13\l)GN۽?x<^z?|ŚH8{E՘&6 bw+R|uiD#yIX9.Ny]y]֕I|o-ֳA[E$qjjrdbX~{.AGpiJbY`wA`:-vWZRI0;q&̲2Jfɮs^uEچ1eF g`* IDATy U;EKGZ] f6 ɮTțo}T&IMEBvu:2*`>mk`tSrj*+#[o'ɋ"дpH}$6иҩ1h5w"~[FSP 4T} "?eF U"ycq]%tu[ǡ6^j|ϝ#- GQ#*pՙUv7mtv4ZFugMwW#F.Q^,NwIS~ܷnkGtKٓ$A>~V䒝u4)-~ ;FzI5ehN`]T$FWrMjY( dK9B.0XW5NFAzćlprK$/ 44(9m?yc*|G&'1s<(Cʸ7}sj;rPT$&uN pt|i ?_dhK/U]ywcvivzzҏrcr%I<䯿Rv%ĂL@ےDzr~yd[-qFZ1!|=bk9@ZZf6`~ *; oBP@7 6Ppb tĤ j_!L&4n.:3Z~hXo)-^|%гmY~>4Aԩ@aӏ#S7v0Kf|sµk@ӠxǑXW7Q+B#о= E6 lhگ)궯7ph"ʒʠ>Fܰ8zF̚ie@k-!BDWµkr ڊgF٥ kv#epV_MZ Ȼ"-.m1IW"cƈ'vAf:~t%IK|wғ2]ֽp]ךTވ@̬vV fh"#D $(G3DYIZڡ ƍzCrЦA"7]}N]iI$E u2?g_&|SgϻPWuNa>4g{9T˂m׮.>~gJ6Gc׵kWx>4%FՓ:JMukw4,Y7Vũ|^L |3vAB` V&8I-^%IbXJfeie8DQYcs¬լjXƟ~Hŋ}XkEi085֍ZG=۶ф@bs˒˘3sҭDXZeHپh4Y,ƍ73C{8(d^V]$I[0`6ij~n/OC_'}EeE{b.u** -NXQKan-:dJp?_ X dnN-oU2ފcےp$&_a!/_t睵Ɇ?ajdn49;v'2rxW(u܍4iL4M`OUa^PTxz#;6Om8,VMĶ2[˥/͇/.$1ij/|xqo&i6Gao(綏V/dX..JQ繗1q|"Sfp}!Op?m4aggfqVmQ,V25^U.k،;EELA|e/=(=-U}+WVYnܩf=ZI6mڷokw܂FcON(59IrDW<ʳPOR?x`k_W7vnP߀N:O&";jmH&s2<|uo_3 VxE?-W@jT+{uZ*괬.h?=n|ƚ\RQeUۺuŋ?l׀m%%.Y  $­/`~|>~/Ā@߾@T22dTJF x-"hb4hH#"},kϭEDVG{lw>P j` &7, PϜbck-Wx@mTQ.<%%m۶ۯQ81;et ZPڶ 7%S)nDFF.hH#d'7>u#F_F͠~^Av6͸g=HR%YɎæs\3ltn %%}{>Hi.HLJ[r\f}v*9S,իZ  thoViq1"'l*Ev:t6<cD6cۀ#a0#FģevN."5L*D!irbt|SCdd$o tAsNngϠ  - \Ȗ-ŲiP'@ <8II@@@4GEEa֭QΑ#>!Cpܸq4i/^̝;wR$5Ǐ9 kYNLL39V9Bn4Yբ *yu*5$qƁh62(ST$NL*Ska6Eox /|$bGm@]AE\$ɲ77191WT䏳"z 4M\2E\ER P5V%Y{#3$ZU$VsRf,ㇻ?$I1ⲛP-@~gLIǖTxFu\ɂל$ӥTW?MLos9j1qK&̙CVQPCfd8Ml" S$th7Qr.VfCRԌ3g GyRDnމyɩ5)IIOzXuL"Mq*uK^QeY.-\sIb 1l2Կ.ňIQx%E:$a-h'9 Ⱥu"PVI/͛hNz,֫i|%k׻I"׮P^e/YY@X$(@Ê3 sӑ9oeD~rv]ah_Z  "Z>(G:e&yRP`s.\ؤ<%Oܗ3R‘F$JO;i2YNoj(4X~L(e܈Ү_]!0*ˁΏ!FGEEQ5#7ۢH- $ Z;+6Hw/޾ohkq9:TӚBDDx|{}+&O1d=dx94LUѐ:: d$'ɬ&֢q;9v&O] :~I}h^v5a\'),7R4:P_'CmIJ"}F7"1?|&42ɓn4$Kk%]?&L+L+ag+h zW>H&"#Zl M,A՘:UۦMJK2k߱C|Vf.\mWǁi+}o{諒ȊG9w-Wy$1Z z~RյkS^p|ouŹs?0}:p#RFQ֛ )ĄExq6G|xe^!ԙ-%h2(.>7tFgSkFT&yB;>,1z tTc?Ό9]DW7_G HՕi@½Qb&E ?ܲnu# Y2"($y><Ϋ^CpIu)ߥM`%1Q4VJD|x}kT$I0>m_ļ8wFI]MRa{.%T$s)+CCqgɃ 7pPŝ`6E::;LۖY>>KO]$1&kv\}C.[&d:UKK]c8c?Y3? tS)ʄ-WHd[Nپf-lJt6M䠻Q#qy<{ źbL5 5)67@ABӜN o2&J⑾}{|-MAp#^~Yl{k ֮>h__/zM7{^:(*+rC]i$;* *vYV ?u%49>]d0#C4ߙrvr^8kEs!I-k~ДrX2 @4M.˳Mb@ vY5NAv)M _:WxGNSABIV֬1d$LIt:KIJJFi}iӀ=~0ݸ]x䨽)N%kdwrq2|oj@=$,.j6;N$J,-A51Se"tꔭ/Nʪ0sɵ\ MR6&sĦWϽJnm{O#k1h)v_ʊY/" '.bX(VӖ%T i)D̒ .ڭ!6$;v2*#f/i Z݆$^yE{6/yfJ٣hb(S[kfcw Iùq-VSZ-Еk'm.rMY,5u8rwxw5n;x!Q 1r$p˖yV! !m rVÍ6_=&~22D9D\_х'q˅K*p/H+ W&M4 0vh%Ngm2[U&Ʉww] &>Xvm?.*=^;ߍEF,IRvo=_\73׼M[Ǐg&@mӁA3{t~zp8DA矢 Kp7<}\tمjN F͍e|^sE?i^ͬ?DmQhf3`j9-t ڮyEL#Α#jE//듓[˖AJ>IšH ;ǂ'#Gq ݥRFgG$=-,~ulw6'].CG,5:+yNKz!Wi>tb4"ʸst`ᯎ!-SR\d"eh9ETb]@ݲ#MۑFh΋ѐU=Sl+*j,I&=m]SG"yNr9i2~iɔ$KZf.rpn*7c6-Zز1nQo'$yni3/wCc~fFa jk)z1Tm6/,8%+ 6$#BC6/%vj7 v{ѭ[?aܩ;$$ybPա2W=s'٠H;uqaҘQ̇[ufk^Z*c۶~)bɫw?mEILCѓ(?=&J!Il(e~$tSc0?Gh=oqJ!> e黓hXk~_gz pW%L* -hɵ>;t0,-$9lk? (9s@g;w^{}Kb;$%~myYcsNT9&HܾG?n[fgz )fv/( ߵ[b{nC/wXRy}}/F2V[ϯ@;w\K\~ עR &0,3Qg/ytr|O,1ǂ(|_\=Kyr9}~m)^]̩1t: el|[[+g@;冷ӝ\$&`I ~ao<PLĘu%m6;5k&JSqy-)I%ɩ!uWΎ懻&WLgh_D|\9@ԊS2Ks~;ͫut爈 7 0'N?=sYr$ hE4iĥf̨}QJEtӉNDeB0I&i:͂?s3o2?Ml@ÇD_]Qw}srhL4O Nj剿۵^زENrVb}˖@a!л7kMZTڕABJTn,ئӉZt'+™/.ScPgqs՞E%D]e\l_?maauee^|^ĉu[ۻ1$I,EͽYWq jK*.]òC,L L90Xz\AMK: 9r:C" MtͶb8џ (--zsݺu<???vݨ$@D0qo)m33E;Áu∬ŧK.ݮ7]j=}V:iLѠgwʫ%Tv9QtPPV^m{U,Z/6n~A0Lhڴ+W % ?޵pRuk1GщnUGcЙtx7N@]]%J*Ҟ174-jMyAQ8t.] ۭsvPA z U1i{t*pD]kui|wUz,I_1sVu.uA{R^(9ЦdrGKG}mnfڵgذaHMM Fc}5-[Diiݲ8`֭ؼy3 >>Z(]Kx[e5W||MbYYUlڵUn7\ع3 q.ۼq3ХPеB_eˎ]i"/-_,** [n? ֲPe̘1jI8n8:Zќ:u*9b7ÇSL&WEcǜvH0kgjɾK4=!IM&Ƽ#ZfϪz\/?[3q7$kNbذaXfӎWR?/ \M'"Yn]`Z`PQf*mÉ g]PGQM7E24M<-ahS7x+W +rq;VBbb"qAL0Ov qfpQ` x!Æy8)'6^{@UMS )h\Eg@ف6%k2зr d̘1 2e >gg I7N9C8<1E_׮B N:>!Ndi 8Xe)^WPnNfD=M*yw'3RAhE;N7lJ ([ntBa]P5~]<98yR\~g &Ʉ6@@L|ťU@(9*rUn B\iV-_oY>J X)U7lrmѣE; wO:v Vܷͬ>4FW=_MYsS4}) URVJ ([PA灬,੧nSaD~K=8S ـw DHlH8أ3Łf̎-@}~PjJek4е ? 9$Aՠ/*yصR~@@}f.|||<15~~hz hӼ궭1Rn@"] bZ*zjrG?`AzCd_FV_?oGp`4yf_JjSn@"Gе : DA@H^mzaɹ0 Ӿ8 M+;nGWԀRu.'ik$~`zǜ(X'g?lYL;u`kQǯ5۸+c6 wC.[ïCPjJek45  89X'͛<!F- ѭU7m|T|K:Ca,4"E BYO7Fv59[PjJek45 /$$8YP5޽;O#?1-$ٿ!( W^ꠏc uloPPv9H] aAХ NT Z-0n{HFsOEP@ 5tUe1߈ۮ.|"|8TjURu.'ik$/` ZGF{O Lun$pC  A&hT+>$yAA"Rn@S 5ծNu?ӏg BT՘f$Imo$“Zxqr-A$H{7G@b 9·O#Ag^4ooҿP-쬠̈́~A~hfK,oKRVJ ([5[yV+ 8#N/B.I$LMn ]y΋OA; 5Yh9>wLrek1ު~umЇ t^޹GU{ @\@"pP(`+x*G*QZl xဥJ#bȽ@)rJ^@!!qraLf2L$3>O3 /;ַoݷJ7v7" !uuj=G-?(&X;ʝY9t%Qw΂'8b j ݍ;h_CW?}ꙂK O7kΗ_6=n]e.Bdlm~J7v7ߛnSm!SF`$1Q18[xW-l(^9$W̐P| ͛EA#<;3[UѨ8*sQyq$H@qLjJ7v7" /!aMlxϡC깂O=uz'Gq: =H{(Mӱ}V5v~GXThͤVRAY ZTQ|R5 6-۷o߀=XNN̼{~Zj}\sd6N6Zha_܅E#վva222Xp!%%% EQ(!b޼yJݕ+ǎS=UEQ.\PRSS:=ztc<颮(g+JiOv)~r @cyKmoWK_Zފ"}ܸqVCH >ܫ*˥O:t\*lnri%ҪKA@CToEn-rtS!aQ9m긂cFc5ܚx+sxب\E$&hߑXIFBdn*$t8!#CGЧ(>wtҠw<[ fd*TP"5 ݍݨ9Ū p]װX,YAZhGm&EB^[! „ Pova>O gf3}ҋ⊳֗RAYI8czڔ.ۻ<}Wm#찺bO?g?a9mN?G';trڤzlw#!@7jSWu ,ɓ~kxRslgnw5gT_ƺJqfqHTon$DBBM=IE^xSSd멭L1bZGk@VMTJVz@Ton$Dvkht4ڤ-f}G{_0ޚJߤDZCEWoNXȟb[_JFBBaX8zT/Osi_“f:v&:݁( %8?`PVRAY nj?M=6_“_W88CSN=K|"E{1Ton$DBBE?I=U`۫=$d: {Exhߒv ͻ7d>Rݥzlw#!@7* t9׮g-mnan\\sW_pP Ƿ5ɡTw Hn($4Hx<. 6hN! O, [d._qz.nl*9.d wОBBEn/͈u렴TM5dG xO|AVJ(}K}KFB07ƍK5J=eL͊34}. I8XNR~K؍H}KFBdtI婧4y=nh@“'hײOɐq辶;<Hu ݍ)$?a2hnԥuÆi4JCɱcL1 ⏊CJBXO$>Rݥzlw#!@{ o x Ӧ=LEQkg­1 chy{K*V4ɡTw H,ОB˜.HI`p`,d1Oߓ:Ju1*s+AUHu ݍ)$|Ux Y|}i0X]<'Lgh|MaZ2E;?Ar#]7v7" p,x`ccʚ~O6ȶSۈ yn֕6C?Qr#]7v7" tဗ^t&9R]Ҫ_~x2ʝ\-\MQq'}CRAY뇄㍮]5|Nu:nxr.ѽGӡU]k^ғ>kPr#]7v7" t:w;8zHKN4Fj'.1c >D~NֳYTfWbmCRAY뇄G7[87_>3 NV ]A=@ɡTw H,C~Ԗ~iP[j“l[6fW;t!TLTFFr#]7v7!m4uTviW[\>}߿?V: 7l<9tRRB͛È 45I.ij~8/ؿqjG>"9.dA1p@nE۶mox~H8l< tj P?+׮*("S;z]Av#]7v7A) 2ƍ9Pff&+W?kvٳaz *}EQHnu!E3d$>Rݥzlw#ݥKvYgNvmf)wGæM ==_QN_&j~z>õ?Kb>\+//y&<]X,$LKqPvaør0.^ra222Xp!%%% (GC1ٰa `ƌ(–-[x駙1c\v+WQ ҈#ضm2UUjHz=Ϝ>}e{d鐥$F~/.̥Ebӧ>W.亏?uօZ:!-R/9С jiO;j~kvgWHS61>`-r]퐰Kx nzxL pY}93sBЋsEVv\%>Rݥzlw#!L²257^y%Cɉ'pߘqA9tzͻ6鳒CRAy]{'C3L?22vxJW%[7:'b>g3LTon$D; ߆S{_ҽ6҃Zl==6N=E3LTon$D>⨽נX]eNնx:ÒKt!#f` ~}^b"_Tw H> 7.m;#Ytf<5( 7N9 GTon$DA KJ !MwLT̜Xr+hܿvkK+"([w-9.d wеC%K|oa$+9Qp{qWu#n CRAYk KfHx-ciqdٲuO\xƞBnxK}c}KFB#e7~#0;՚IL;I9KCr#]7v7"kBջaHQXZ;98=\v ]q8CRAy]_~аX.:n (Jзw'<}KFBtMH`oZk6_kUׂTWSuѷG12$>Rݥzlw#!@ׄz8FsޫAZEU]`c] x,ɡTw H|Q 'nv&]npm{{5 Av#]7v7"kB‘#&tݻ9PVjב.?fݑu@pÓgz. hd>Rݥzl/ IDATw#!a+jgr#UUD$F4FaԄwܹzh3uzkU׀'%PQ14Hu ݍ]nAy{L[zL0>HU]E$2%1;SCRANaap.n@bz}}s0EQL:j6GTon$DAׄ ‹/9H^` uQ²ϖ]!8I*N9E<ƔHu ݍؐpuB6bbb= 5rQY ֩]LQZaG 43l*ܿSRݥzlw#!6$^~~;M}<=/vpMn~ԎI$>Rݥzlw#!:&&]Ԑp?l-v ʵ+l?++77m*NZk-Iu ݍD ˗0aSL'ty}L4T 꼖p>Nܺ5V̑"qrues< VzzTw ׽$ u#${9s zm68˙3gZ, င'VWp؟46*[S=fj>-]u[Oo.@:;;!Cڰazq(,,p;uDnnnn7[o>dfwo FY2nKuG`k7Ws2z#]7v7!]fw^6ơoIf;RSSپ};`u{Ebb">n'Q5HRA{II;炂?bo Y⮻"5U}saٲe cѢE9sƛoIv킭hbbbRDmT)//gҤInݚ8~s#cΜ9?~CZ'>C}]\.]vE#Gop8HNNf޼yV СC4h/Bub߾}̜9>}pw3zP+y(̞=FRRRCev7of,_&Ԇd֬YC6mB3?+Wdڵ۷/:^sw?5kpPoȑ#CaaaPZZJǎ 9{,VP\GT#99ڵk6lX5|b֭ 2Z'233IHH[n Os=^a39s~Ʊcֱ/*)))Z蔔}?Xh9صk'N --;vj%"LXhӦ !6R zҪU+^}P+yEyy9ӧOgΝ<,YAԚ3w\j%---J^*Xxq|&33χZ+ٽ{7vA1qP+yMEE'O&>>ŲeB+&&&&'dbbbb=,&&&&,&I>̙yQt<=D/m&;v,oWMLYM\xt;Ɋ+߿?֭c\P+Ġw&&&&,&&&&,&&&&,&&&&,&&&&,&&&&,&&&&,&&&&,&&&&,&&&&,&&&&,&&&&LIV1IENDB`mpmath-1.1.0/doc/source/plots/hankel1.py000066400000000000000000000003121340375245600201070ustar00rootroot00000000000000# Hankel function H1_n(x) on the real line for n=0,1,2,3 h0 = lambda x: hankel1(0,x) h1 = lambda x: hankel1(1,x) h2 = lambda x: hankel1(2,x) h3 = lambda x: hankel1(3,x) plot([h0,h1,h2,h3],[0,6],[-2,1]) mpmath-1.1.0/doc/source/plots/hankel1_c.png000066400000000000000000001064421340375245600205600ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx[-Q.EZ{ݘnsi yeK%dY,x0# f4$d4 F3#ۆn/_Z󐷈Zkmwů벪222*22feYfyIYfeYvfeYfeYfe=,geY^2,2KTfeYfy г2,/QzYf%*3@2,DeYfe=,geY^2,2KTfeYfy г2,/QzYf%*3@2,DeYfe=,geY^2,2KTfeYfyۿwkkqm|jGiYfydfۿ[Mooo /W;J2&3F|~/̌zYf;x׻ޅ-_E[%D3rS:"9 8?&0o(8Ke=>5yK[CNz[ E^ Tfc5X-霸 1S b o0 ]yꩧwgyO>$` G',i#=q3^D7שPgIXcSh"C[ oW`9a_$6K3p9߼;שsf~/_co;̕Y}\r逌-t~ӵRr>YAj.W<j{"9Y_>vY,v O[T>W ܺ?-OD3\ ˄NM z:AԹ$n֘|OKއW'U kM,Bf>P(b,2Q Q]9rHFmTAz}{0#6AޡQiNiы{d>ٕJWR{R{qE;avU8r۷0I=^ZWMgԏV-(Ae^,%Wd=d<ۮCief#)Sv_9#^=tnűĹ j_+n\@@I.ГkOx־68g/ oP# N"wxwॼ Y ]Oi Yf̽NJFJwJ&jɹ{zҁfv noza&I kA*DY}k$t?J%\նo$c:E=ہf8j{0ݝ/WT+['^C/tZ9ݣ$[w'8{M*}}%o3띒4nݻ N_!:{];LA5G\vHut:(/޾sm"pCM"^o~{+3@(4`*9og;E.#g T{IYDTtua&ņetO{.D~eϮϞ{y@D^h转(mިL82tʞrBd?fe/+QSԥwWd,lLfx2G ȹ&ɢx %!)$ToW5D7ǒi#`0缰[@D;DwI#\踥X|9@mYm^g`ne ĶXk{#je)`&OOgs"ISz I䛏E~plu\ wyj9lt5Nůs,*qj  2kh2Q9б)/}L$kyxyy+#iE.pvv^JM#6DM?O!0~Ăsz{ߩ'^څ"HoM/?vX?3AG3ny/c'~䤰SWh%?.y6 K)H;H\[!=ĵ!^U&>/<ꡅ#>ܿzq(сJ{65T^Ózn6i&|[>yDPwOa7:7#C{˝h8Iq %z;d#B3w®bL\I'?ZO:!;ڛ,I=n'kZ=vUG;ڜn:tP)=0SI {.|mz$^J4tG)&Ú]A9OLfrl6ncɼ+xUۃɩstFntzI{AC8AUBS%~R 'U^!'OA^v ڻ5K^uCUp&(kL;}&)m;_%O;;O7"7H֛:M&=/ޑh sͫI7QC΁`#t#hw{ϗM_f23<㸸<#xuk<",k-{dGD~W'^U( @NA{bؽ'^0{ ȟS;/`0-STlN&/K#;S y[ߊw'>foo pqY1a J"߅NhNھQH^v y0Q'h/= 컔A߼dyl:~j&; c⢧7^kN[/3ef'dRQӻqI愵8ɳĄ^ɚ  ;-{iPO8>ECM 3 U0 T #z6}eBQT=9^6j>U;Gݙ6$mT)1 ЇJLΗaOTIsΛTK} {DXʨk {"9`7x]үU{pL'{uq>P+:;1O[ve|/\Vm%S$vɀIQLz9= G75-6I&TcVh>E?0aueZn{Oym̫gs!e:nw`&Yu%nNK* %6YNƷ߼ wK;i/q/)v+_[3&z}{I"""v˼S۲Lފ,I5TVf>P(Y~Ld&@L@_ )dJB֚~R R䠫 F.\P*|2T~6N~@Fh/^32} rpYMHSOԭL\CO&JV3=RSY`' [qW63\:q$,۵ANj܆mH&sI8KClJN@r%*(4JIl9yO%Fvj.Ӻg{ > "`~K ^h#>&GJU&=$~*0C$m5π,et6(j,7wk]]̈8ƒW5z¼4M8ZywTж56Lbk>v! AS)3{$nAѲ[:0j; x9kPϛ6Wk&goӤu*^k6D4RJ'!9eEvz@bg+.ukFYY6bc>C$|re2Xjz C]?n;%9Ge>%9qEl~JzуD4gUfxl,˩r~W~!*!d$#GbZf!QzMNHgAd1KO/hb5FLKSyf*жWmajc:V*dרL!U` : #8(чfڎ^i 9//d@Q༇Yp<3Vz&+o@(VC;G/:yjbM-}ȹ8rrU'֕28*NE$=Ir)=׫}=N/+EtC(șle`prH\j2NN@pR6hy{3(qk_Eo!e O:V(`!tpurq@ ] =ҕ$ ΚT_ AAO=̰҄Q֡sjXIp\0orqKf`wt p( [訥IN-0K5;F; %8vj'iF[6qSk DsăZEMMA/LXg(!sjTrp2YLI48p3N3YrAvZ;twS+isBr 9/u, %ATei }"NhG js: [ͬ0(-x"Y"<`K^y|@nPn΃n)wF蜛ڻ IDATL$R؉Lst}¤[:#eL2pYT_ed@!vAj `Se`]- hu>GTPڠ=?[TI*Y'LPMNXM=A; mUSM7Jg%8 Hj6gݡlt0+\b6@ɜ% $ O7@ WaBJY t J+A\ȃ!eU"ɽ&8ۡ&@ "t`h,JX8%&"']wm'Tde3\٬}m^]ff/ ¶tuE<܇s: !Ӷ.HjģHI7bn0m37޶q4jk‡)u̲S-79١n0Pksi9Ot ̍\zϵf?,Uf>PT8$AhL@ d~AF2jfHʥb^blu+IתY`U,S[9DFDׁ]9Jځ-+Lvhtmĥ8gi[ }a2wX%!3] I˃ɻ,WFkLhj1 Ї ']¦r7DZQàxe u-F¦aHLA+n'Cp=Zmm^[ԭ:I%Fʢ[*)8_; 0j mC)r_@Չ^9)iS @7{r.5rP,#\zB3P{[}k+ohAk g6[_ 0q8{& :[Bp-5s?N1v$4\Ь_5ߟ PՁ]wʞY} :)M@6epjVL9O[mA _(\{Azll54׶^r[h<G=/6&4\tɛMA63!E_9d78LVH~{QZsխ%}%d\2M輴V ^j,|Y YKVm=_rzU 2mkTji7~ԠZbZ,ɩ";^YS`I4CT6Ϣ"[c]Ro ݳCr'a)GSh!S4]ʺaѤ:2h{t$5'$/S7,X/I>N=Gk.vvQVh Ȗ1MZ`f z|iĦ۸t]E+ ;;yɝԌ}Cz,Yf>P2 F-p H:Us$~3]jR$|/; sqM ]*~9nT0H^?2 wAj-jMcDh;O4@ @y8BAyݶ }Mf9cT'K Uf>P\Wf4 Bk;tzB+@m Ќk )F Fp.8!hca2Z8M8݈47q@dy=gSxG=smɊQoUvMG%.^B,Od@Ism S]pY5YYa M.[V'6@V)iسq"ǢȦWf\Ca 7e#fA:f8ssf˞9}@yfbnp`>Y+)M^&z&;S2DN 'n3YcK]7};@}QH1Ҫr2@;!ŠV"P,@;WE4l 5aRn-G>?%82y,qT  Pt8hJl' Lmm6 lP;yiR;Tm\@!@]@ w![wS0=6PMi<Tf*3@wo~37z Ѐ2q*xLB~94@7zq#t20 5 d Lm'sUYt& &z$<- HF:fɠ4U&@='-7sU :UHPv\븰h|`_,m ᶑkس8 gx2}&M -k,6􆃉\t@1q^5KY:aXD'Rsw[gݱ j`";+6]p zҋ#5[,l@ycS+tԥycoEXM`vn=&i P)fЪUhГג| vVfd(TXzB~7GGGٟrr x~_԰g$,djjoSmP,ˠBTpP=94@wmv4O"yv*gTzM€f$k>ܗ2T,BMF֊EadU$Xsb&'z2Ȧ3h DK,8CiG 3qdP%IVp n_znxbT|l:#gDN ̑@`6E3xKҝG 8vz 8XrgǴAsQРYdž9g@f*Ɓ(B]ǥ(V2O`ʭ__^#4HuE=sa ;e ^p>UV6}=9$mo"Ԃs|, V),:"Ǧc)8$;4Aؤ:jrSd'ai!c\3` լ @g9Y1dl@aξ Z&Fe3R[ktw'R,(-EtÐjcXg2BVN%-;U>487=hYtPJ|dН-9$ zQ*0͹HzK$&*&`u ^ %n#.& d.ra1U3W|i,F")`nP) )"j(TAk^mCM&ф{"'gq@T(@N}\As'aJg{SFp"fd5@:Ul2)8q h 4 8KMմ!ŅE tyWtě*YHBݐi-VA*DI[q,3@(T7 0J x4%V4NB'b Rp֙E@NgBAr@z֤;kGd90 ZDĠsǠd̫rXX!6CraNla*Cjv|)<6"Z3x!Z!/tiœC  GaԷC[2B)UxSG-b ̢$k@@DI:meȍyC`낢z%y%@:%Fli,H-82rd2Ȃ'LAϚ5*`'-Q1X|ɫb]-TSX"D'2-ԢVKٛ z*3@(qHA\~} mCiYuVXp҂3f6o ͂E ӆǢ&h3\p0E`^!ɰi "livhQt20k1Mr;̨7 (Ah3Dsaϔpia{ Tť^M9B=N۶cvA5HWe(jsJ`}"(X) Z T,{J"9D-M?C[S\,8ǦFF)hILp+TGhc[85u4#1{fXs4hʚYug9(4>{c{AHglp|A4a^keәZ!ڎc)]3neCC:IXKCCLȳQ(],vDIW:5D?#yuX@ߤ:iɦWL6S3HbވL+@oa[m͊9 >A68%rmcVk.ءGCjSʈ 0 @HRxe0L=sd zF@ɠ3(eC: 5A5 jJ aHiweâ9hkP @5ws㊀#xNX`-hQg!o58'1 >8mGȿ3؂X2e ̎i#@ (7 1re:&1/ fdBDk]6 -y|A>sAS$&akiPŐyȽD Z.A}FvvdrJk`84)OWTGD8&"D&a-X6%%tA3q1dcfNYѼQLykL= h0|̋ZߖvKZcp9[\$&p%T7rYl6 y$z Uf>PvfˌLZ]*(V*4Us؏AY3sXv3n}pޒjĢ З\ 8&\t5Z0l0p5kưq15!_gq̱spP9 ǜ-mAݰŠAsG؟e ;STkj7Tqu&Hh3G05a̝R^}yy?3ܹsm߆xk_eKXYcqA-l* ,Ra; X[۳ey<&@d-["CY5U}p7l @iaLiX@3b8E cfpcVU[5k߳)$a9Xy@"A؟;.`K;.tqZe5:Z-!I^tW2hSgxV[}1>O]u*lc@]F]-%I%Hޤk)=Se[O Z ]d[#t6 `_Ȧ/ppm8%(\ce/Gbp1FS84vG<3lG`lNOҐ@mʼ!t$}h@]3ͧj΅{Zp]v2 `ȅc z5”Y^;;8?? =wᖹ8,vl#~kkX/R ;lV4+}&`v$D4n}Ref N`CMl H Wt.a JH[_ `-a5q [1 SPd>a #HeLA|*5/ P^RIݙW .HK&^ڜ=_#mYz,Z-|ݷW -B>oCBې4--.+0 P6, hb0 "yKXPoS:`h@Cڧs,0`!@HFc=a[2$N 1-7p%ŊaE8ud  ꜰK8x7up\ÀSP `#l1Ј@#龸 CaEګsBXPaס(x. ]e#RN -dEvR[?<7P\̡l48>sW,Le :h{ ͤ T%U99deVsYI{EgmΚ;^ڟl'PrX!(#.tNL[\ `Ȝw-xp#퀛 -p [\#58Ȟ7`yܶeQ!K8̹7.uyMtVىc-݂t':_y]'*˚AÀx}+fDVE!/a(@i_JadK<3|i*= 9ǥ_pf4U%cj)[ʌ)˭\ cN y yHL9lP'c8 kp-ׇȜoQ x% x ⛾;?# ~G??~Oe<:w\PQU&uqE(gfq IDAT.94o]q6NF]Npʌ1 )SicLk0֎ycSTM̱S8m<80(.q%pȤq J@:bS!v!zy(/[ɟI}??`Gܼy??8>9Mog?Y<x'XnҶWָz<x#oq'`9as l^ fm/@۠ 4H:Cڇy?"nhh .p b8pypEi@\H֤%=‘r-r)F0[cl\džobC_gpO2>/^[`|M^=f^ cB8V@XV*-HGZDPmAH(u:@ϯL9q0^yρ81qqx ['lx4 wǛxˤ5%4l<'#p  u2qh0o,aԣ; K1z0.}{9f@,[ZqQ"?p˓+>6fexzy<4K^|e [[G? ~ɟϾo;_n޼'xk`[v7ڦm`=b}u; ob~@_`Ћpct x ┘[subzQ|qgwĈ lq-cslQ0/q.z5 \> Q>X^ k!N90up#2D_t<%pB+xkx׽@8?~ukx)A:+V<"5h*6uSlY5 k6cЃTAXU# +' !׷'-oס_x _.O`(/k'>??gOOOJJx<cXxY |W ؼ+Y\n_xЫCcto8 ZqKUtߚR\G$ObO**T1"To0%OfdlqW#Vـ?>>=0x|Fj > ͨA}jJfsԇKt@f+q8#`-(>ה( /9^(SW9G#Fq*=oK'WX}>5w4,MӗB#@ P@k@ڑck&N^7vhwg-Vh H/-:t*7}ufyoN¤2H=.'| t$rgE[oW.-7`O1^G y }͊ 2j¨ nmҧjZ%q׿W< 7ǀa \D'@Z {r'ןQqCd镦h{9-:.fjx7!# G/a%abЩBFڈҞA ,=si 66zZ%HJ{c&à%P|_PJy–Ag> 3{G[`q^ :Qe.zH\YG@Y#rhO؞+/ǭxa,lc t0'78})' JAc빱`uC+QɷY*Wf̺֛*,@ﱒV4P:I/]fe]8fhָ[ za~ 1ph%XNp'4A@UM:}e;vf(L94g38 |3`A z^ `x80n/nb@pxSN@X%NldcՆpd٦Jd po Z_< _?3az ,MRaUqm)قCW5V97;p\☔amqD[;Am:/& *jlL:eE17\(dunlpo g K26yl/KlqL6 7l4d@ qi-I>E*LR)Bϴ!4/W2v4!rdvxs G ihOf>TFPA<tNBZ::!cPr!MLD"+NgIL@ +t1@Fׁ:~Su.%.;D26u.C5J*fv7s_-l^v`\2[xn?sb As8Et3Z0ζ} MZT ò;We%ׯb,h>DT|cӍ5-HKh Q싴vhnAˢڡ1qT7;̒dCe'! N_kƊrA"SiB (_[5w@MG :fx )#c;D$1{ ؆(DEyHHfꀉNƀܱYy;-urgDs^dwހa ܦ[pDa!X0zv|2d Lٔ;%#1K.Y7HxHv92{ȧ wBbcrJJ:X,\:]R1#tAz*W# BzR鑖A! BuQm$ʍ-M;68G;q{O| Sߗ'隀4Y>pA\9c@uW_6ssTAfn%pϣ "91{y]"\n2MOZ>aE5"DV2 pse~ @ F%ݜCP B7.dgP66 U*U0jcߒ#Ү8[q9U% Xtgs' P)ـp4ջd@<%oi9I4L}m1MW1^Lc"b# Le. 9 8Kxd3N@?g kHjGZn" Y6$P'r6#ScGMX*v`@Lj=akrKCZB\Oh'V\lTl\뭰/#qdyndJjXEE3RuFEX@s/1Pu4tbqMږce$eQ!+F3$QmСɼ1 Vi}gqK&eH`,d'R$!FC.X{Rd[:&p$N6 0}IPcJ.EHM@4*pJ5Jœ@1sXhs|R(}2C֔-Mo*E9D\K_kN,*PƵl#xKCl i9l~6*@3uk;H൩/NC g亡y-Fc&I˚ܘXXpQ?q@!& Lb/kA"b e;8# y[F=YTT2AFԮ`!?C2J1yE~q~ʒ3c=^ncA~Khj5xb%Уf1{0T(F5a& n(; 9:قNi6Kٸ,"$d!}.80K*.9U皬$؂4%(/׋qSV\l0֭+&+|ڸDHbӑϏ3 rl9S)feֺA,B CkB HT>v 3|$1_:4sI;΀кBnuMuh-:9I=s5 N$P@"dlN+9O%`DKCa+\ ܒ(m(?^|g:ZÓbҺΐ@]\#㔚32Q h9Im@8.餓׃~$J2"U {mY۳jɠs##` ͪb;}km@:RYfz0?8kGM!sRl@ OIrHu8GLs SUþ.PSQـޏKpY]()kq-*G-ΒiŶY @OHMŤVhkuCbE^ `SzMZ"er+>ܪ@1UPz&ȸ#QFl0…Dw) ʥm;;#6\PMQ7ik@TUvtLVzq9)fh@ɋA+.rIpx"Б @OHXQC aTLX3l4͒s -^AˆR0+LAPS9Lwit!T45AIޓy7d :#Tk#v[= qn){p3ģ)$)6'-haIF-řa+:9 s.R0k\uEy`"GJdI!yC% yb5:X?fEF>wB YГShT lG̉qbW2ծk1c*[0'AiI;`ƖH{@̀Y^OYܠiw8#@ [_ab HoQ /;j9*&>ioe{O gГRk}elT{ein@ڶ@. 6X؃mە;ųg9>R<@fƜQ ߆w4"P$4;$PR7 f2 dWEΙ rQ )f.Կ~ܱ҆c|@`{J6#\  \}Q>pSDt')#y]%)*=! %*(opb(0Gfn-s>MvgYL닮Eg?6>@Hf]C=vF5Ψd6`HD$CZ[{{uܾP hA'r6'^WSM3A#; cɜo!Z^k3cJAYs;8I=D$+fyg8"KcNR;K [m"-N܁B>Z tRPܨmkZITt`m\'1߻;DYr0{K H9sN="nR{#~Лr X?[ 55 X l*-Ԝ(Ygw @OH@w)‚j NI1pflW϶=hOxO0N}7.EZAYdTA°V%AD2N0?5=)n/D[ r#MbAwTzBj @iy'(LCuZ`yU kTbJy{ed,~ 7*&8Ћ3TĔL7 zȊm(u%т dt]v-) U.T5XSSP[HQ )P4\πs7}$87.v>@Kw! PO\ tz feD[u 1-H|ϱւ}@$u[vx:YTzB|ЦF !Ϳ\; ܶoZJ4,OPR86Q)(U<8;h9h@5^'AOSKf4 ECh,Yhפ\E[hTzB ]Ih7AӂK'Dwe͜ߕoG!eK!Z$82-)yVa#bA}Ƃ@8غ6r=͵V- [}w{:GRĚ/RGG'd˫P=#! Vzeujat<CHkL%`>=w{sT:NlAyloCG Hn řLTl"BPZrvHpHĒ8;B bcvN1v0A9VdVH`*<=\NSSa/+GWXR`kg2 ҂4+asx!նng˖eLZ95'Q*I_wS -g!ڛVAVVts s]҄Q @gnc=͛7wi$l:ff@؂Zϖ1d֔+wsh| mg }`m)Dž*L^O } ^^"j87T'5d{ 5:絬SQߖ3=%-C> N9T|bi3t%uѭcC9|{˽SIB rTuqVFK1D]ڷr)a^'Mt/ٜ2o="SLBϿ"}ؽo/{hA҂hF+Wʕ+3338G-ig}xa?qJlfcM[f9w9 ˬZSƤ\7,u8{zHe9 A t Ȫ€^oO8(pf+ɭntvh0ֳ=y}iKOiK}hRuv%@0hɉjf{tqxНs@H/n+'!#*r%` cWy{n~AA40'$.AKvm ń>dbA7c~<mIH @OHs>,Nf! /M2".Gr*p5D Q,2Bu\r=ag!nZ)0;TFltqu JFA_[2ڃqJk!RQ\J;v d9@V}?`hKm%VU[ع 8%EϠ=Hh-pwTQ\i~#*\V;p rea)Ø)Y6̲JUGUߤɭ7c=G9Zɡ~*fDtj&vm{iv]yбi!L^t+H?i}}ҒREdž8r:EN݌_,?G>NTGN+!7'=ad1Astkul]E[hTzThڬiueº!Bۂ':d_]n5a@hٸ8W ̆IUM LglЩ3S/0\ Zvw@YUXrl 9Z[,s| L-XTTt!sQ */+_)Wj?t+Ŵ;yB*31]5Q \Шb5d毮`ZKtk:Jy$!6Ns+b9O7H)ÀرA@u4LWLj%%ig)",:%vpXBR^͔f_b8!Rtؘ۾~\ap֥Ͳ/1}h%\MiȬldm|tmXAvD6.`8cp B]TzTZH4 2HisZm9J1ɟ1G19,OpBGI8h^gjd- F !XڅA]sMNs׏bu^(R )͎x$pxOiDr-*+쓛4M͜զP"k%dʑ"ӎD3 ɉ]#2Ҙ;QAM5s%bYp K4 @ρ.HlQݿZ(82uHZ\~lAya:W` n%ѼL^PksӰgqب}N޲&M6:#+OYTzBұ8@Qd<&p~c[gƼYn"+"-(0߹ 1,{dH^_x_1l;qTL|^~X ο&GP\*9֒ @OHӏHBL5DWjjT?vrgRг4)92jr~q Z0\] %TOmwU37:P'-=a6!12z!NG@m 4Tn~B ,1ݝ92inCd(S c$=4\|xJgK[(..*}dOܞ֌Q,NgqjTR.X*=!54(̧p  T~@C4cGn1^: Qwl㗊<+12a,l} Ri%-],/gޕf 4 T68QW͂s. 2A*l@؂3(m6{==~-1c.ߊA/ˊpuRغzc_3sNg4.n+  N%ڿUV9Sil*sݓSPhO`ѢEdm!W4bAV18l؞4|ym8%N])3Ou{n#؍-6#〒n|h˫,X'+vcn.Єv؁73DUUXxqw/4aM,\#i棓Uf$M^G38/oYf 817 Wr6'gd\L1s[='˾D|ct"I)D Rضm֭[:,qX~=6mڄM6a͚5Ͷrz54H4rO<$zcLYp?$]28]qk,XSv,#@۩#)jUC:j{wܛZhzŊؼyJ3<Xd }7w?o`?ppq5=3t)jZ *XfT $𧂷}49XaF2xs&|܅C; =X@s{e ~$n-Pɔgw敿W^ŕi4N8ԧp饗bΝ뮻{>~4W.EsCW+-nZ-y"{ kEc)䁎F%-AK-LX,yI1捉K3Pքl4l/f$qXVL˵-weH+>O5BG @;  Vcf kG'ǎb1Le~De1yS.қU23ɔWjJ2sCDyYZh@- yyvܦs}0Sݤ;gZ@PzNT[;A3ѶWd[c9yaHvMz$m'GA+ufy c, ƀtԷTFߜ(e֝ϱaNgXhTzB q2 AP`$󔛹1 Ze?pσLFXg3`@eT{rK sޥmUr`Ys Mdٹ9jɴPzr ,I|zh;<\8\6P,SH1mu=-0̲0d_OȣM'!1dL@A8HRΒ @OH!c,j;,S"#8fsrQsQRXFd5͎b_YD߹D_Vcs?y`:L,NK}%`O'H\ ' ױLcKHKY6n%DXKq0B!#g"x޶S.WdO>SEҥGNgyn b.*=r) a4iAx hNwA3 =-fx]B,·{LRwh1N4̲ bV^e\(='M?NƏȨ70i ̂vl8g @9?'`<9L)ԾsLsC~[8)ZJY!X B]Rcڰ4e=G}`>U5Y`k8! ur3VAu$A\r8ʒv!wmLi Bh $ZK]7-Zp.гwiBjWE9̷ZjL%Goi4dz!; IDAT(;C @Msf5-E25skq jZI t<>R䯦bU'[9gVݽ&]-Ƃշ0B0U|Ϧ^1DnݠPɢT=t3IUS|aH'p YGiS֊dI 2?4`poCޣk9&|xh:Cb{%N;ND}:]|4y, @OH*v,)=$UUܖZB0ʜσ`;Clv>7 ̏ -x tH03+tUј{Ls 4R]{fx""JJP4E?M&{!0Ff=E7Q<4<28rE6ΨY_g9yE76Gm!d3&:*`܆aQI4{ VHydD2*{瑁π: -hTNGa+ 81r $JٖAPy @OJ*5m@]w\i8b0<Fd3P9TsEez@!t`gɤrc*s2ݘe9U75s ,c*rڄa{EBɿ+ֱ=\a?<` Tܤ"g nu*|:m^}Ngrl3|aL$Ccfve;3y ij3wtў;E%FjVâEpG裏WYv5< k.ڵ _ׇ @ڳg֮]?/nf|ӟ*Ts//+Xlټ񚞞OcϞ=ŋc~?կ~O 70o`׾>\sͼ_=^u,[ 7tӼzWpÛo{x} NHCv؁7(ŋ<8S,[ ذa.]{׿ulذ:fgg:H_xGO71|~`֭±;|Is9;o߾ݱihă묳GcӦMشi֬Y3/VZz ~;#kXj~i޽gqA_98K/N8|$MOO /W>(.]SO=;wW^333>kwm6Xb^x}Wu]u*+V$[l-[n`󚝝3<Xd }u}aݸ+sy7/ƽދ 6o/_۷_"oߎ˗ H~;?Rr`Ϟ=;vࢋ.' {o;w⮻w4ˀ //| Xr%ફI'tPyٳ\r 9|Ã_s=SSS;WG}qW{K.'> ߿?_Wr-X|9^}UG9o>,TPBQ* *tRB :Dt-=#җ. ]tz䙗_~r ^wyg,ThTЇB ~z~ӟ. W]unffܹ7x#:ػw/?|׿KQO }hkŚ5k;ҥKqQGa֭xw3N%Kp뭷b߾}ظq#b*R]CK!\pkvZڵkO~{>O~|3WGÅa*t [} W\qj\yc9{Ŗ-[a⋸;gg?[f:t̃.oM=v؁իW'n&]'x YBT,BtO.΅i*tB T,B :DtB TPBQ*]PB(.TPC @*T!J *TЅ *tRB :D2¥!IENDB`mpmath-1.1.0/doc/source/plots/hankel1_c.py000066400000000000000000000001531340375245600204140ustar00rootroot00000000000000# Hankel function H1_n(z) in the complex plane cplot(lambda z: hankel1(1,z), [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/hankel2.png000066400000000000000000000647341340375245600202660ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwxTEl:$R}`o JQA@Qب"EPi~A"U J@BB iw;ggdDt@GHHHHH |Oc 0G$$$$$jG .%$$$\)@KHHH(RpQ-!!!HZBBBE"h E .%$$$\)@KHHH(RpQ-!!!HZBBBE"h E .%$$$\)@KHHH(RpQ-!!!('Obǎ֭fϞ SNB` SDШ='x7n͛qi3gΠGXv-t3g4H F%86oތ^z{FF;wFzzzcIh4uVXOOOcAAA G1+ӭ[7T֭ }vBii)|}}P(PXX-Z~-fgCѳ' ~Ǯ\A9c`Дk^WVV"rHg2닀D$tUt8:ki4n% QQQNBDWߨ{4m4zwiL ɓiƌ4eʔ DDDjj4D `k֬iWDjU7ڇh1~Zmܸr>>>hjmhT. 8І D]cԣ)9Ѝ#Pū1Ga-Eۑ y ݕp1hk!";pˁ{h^o7W`pXf ~(zpW[2" b 'Nį2DgA!W@&9MA'@yM&5qj\-pك 8xІ ,&L**DfdљEThPTk\)HOhݎWJ4,[P*>h̆ acdٵOKKC^nyRu;^[+eMmgKJP )ItmFyXjq㎾i++V,rZ/6^[+e.,,Db"AaC@B1ZLĈ#̎GFF:M?D7ڊZu;^[+!&_&wsZ|-.v%$xb =h^7{*(,xXDtmY|v1[0qyRtZU;ܚ^^I@6TТuGqIۉo|>jU7vW?܀ @(`.@U[u22ϱ&1gܴ, E#cuhuaU;\B'|cc%7oM:(njf{4syF-U;I`tnDV}vj,`4iJH.{zm0s&eC%/3p.qp<846,DA{(lW] nMBx)SOwg'£lW] .{ƌS[!dƊBB~HܼI)I䃓_8?ljU7vWm4 ai5m2D4]ѮI;xD5O} ݾ~#gӇWJH&!`0 ǍKp6,BkkNt:d΀Gktxڕ$I|16Vt3 CCW AS[TD-Gmvųëv^u|kw% FK/_'~ x 辣ݯG97*V@i߂g^[+e6>>P\lcED-vv A!n(@bahM^[+e699Y_XLtL"Zpws[8jU7vW]$jU7vWtFF&MxxJJ ӧcf窛ekv `:;+if%0{ltr` r ֵͳëv^u|kw%=@bӦMfd2ۛgcڮ]Y~E;.WYQ 8kbޱW;l(E³ëv^u|kw%\vwNA3瞃/_I}yS vT0* LLwh;uQPiT*|ޑW]FA7\.?tIIIعs'ߏ={`lbMα*6֊cw""Zq,-- Qע6;FDqV=rS9ӧ]F5{\O˕+W~,_p%}GJ>Gs= ((ضm tٳgܹAy95mohv}v~e, Jq`]cxu23_3~%KA@"##1p@?zAlkΡmމ92 fXa#jU7vW-i('Rŕ#NHci1'd^5^Jd@MExW] ;Mˆ`D;&4VZ-vVT71.ͺ`ۈmx37_7d5/[zajU7vW]}%!leg͛xz%%vVV;WX]κ)MŌi>7ZE x^ƫv^u|kw% W["Ç3`WXuh+^tH[ݖuWg/*0^[+e$mۀ$*9_jR}U+6dg9PF)J4.5ZWW]I ̛'bvGѧi݇&MʧX]賻d\U;\4 7bߟu\;͓bx(VC AC.6[Y(<\Xky6}xΫnoN>غhLzd&ɓ"TfNmɊ +0|Th+Do!@h7Z<עlW] .84 #. Dkwf| 38 /Ch@kjU;\4 6n݁+jNLQ;ס3ضg=/=ͳëv^u|kw%=-8e|\sGFpl[nD&<Ü* ٔTB߀]ILv.]Eu'}[ENEֆuz"(>QIq³ëv^u|kw% еAA-bK!!"UZyV (C>$U;\LB D< "R'_<ĢDڳ t5b'ƢP1~M^[+e$ӧٲot>@n(Ug:oҖ(}7_x6}xΫnod6Į]06 h~DLetr-橖hl$Pj3 q1=3hByCL& +1祉b* P+Ͷfy6}xΫno6z 7s޼!ͷnK̓G`66YF&S?ux6}xΫno68u w|6ѺUYbt k90#x e,A XAU;lW] .t]&LMڽTR$8Frt_^]Pzr̳ëv^u|kw% w5"*8Hn.0kma{vt3^*+>WJp2 8QyE6#8خoyZxyh;-Z(k^ +^u|kw% u0~<3 !ܹ@Yûԇ5+}_AJI ZHLyH41No_,x5x ݕ2+N]&!(;~ /^/)lZd]I 6i-^h֯A{Ϋaūno6miтe uKhmiA5OF/?4mijyvE{"VJp2 xY6\lhxjC`35OnH)I+_k6i/nM0l0/Nhۆ'p[RXx]bm÷N:}B-^zjs&2Ve8}{հU7vW]I l$ʺiW][owox*<",=b0C,A^ +^u|kw% |=s{/Ѱj\_T^z퍖ZBEKVx5x ݕ2@7dzyÇ;PDp0c7m'2 Ws9kԭWnP3WÊW]Fedd`ܹ¥KLAԩSP(`0ar<orDΘ1KV:XT^fM,鉔= D_)Iy5x ݕht`` 6mT#9s=zڵkѥK9s|C&!,PY)ds h`ȥ:'C&Xzn).f\.k[P vRzJVJGFF;wFzzyR9s؆'#GMcF ݤ,\(l0OпM<uYJunnh3 Zľ A%aūnoK蠠 RRRdv;g޽@BB[Hu]UXjL,6u;v ѣ,vm{/"25K-uVn?. >1aqbͱ;1WWؕ+W~,_,{@DWP*4uTԩM6֯_O$M>D_߰hf|#"l"4J$}}k*,OwLۛ 5w6&W [= j6Dܻ7pF$rag透>ta;`ʋ+oO#З葷# HH'Xblgl]D/=`۶e3<TJAgY6OE=ҭPj=: G^ +^u|kw% $42ilʝXü̧soDDX!*08rxzEm 5 11w]t+趲ܚr ͫaūnoFJ.LfXZ.gK#jŠNLouiHwMH_^k x ݕ2@7Ј)ϙcY2z5Pϙ0rPQQO>,:tq +LC棩gS,87rNr^in'je󺪍W] .tC+ d,$$X^䓪cDl`׮,f;WiG{޶=Xٓ͠/#z\44ux ݕ2@[jl1NJ6e˫sC e;pyro{10wE2O߻}QR CeIjX[+e$CW^1&M^QQɓyNrtL9& $,= gs r'V4UO`_^{jX[+e$4l6 Š>}],# ~;kTgjaL0 ~~z>[:mtPSt_Z@jX[+e$4wv.F~c bcצy۷/va^{ދ{ Ҁ$G5WÊW] .5&!|1 ?-vZ _(AU-C,}΢}h.Cdv͉5}d2> ܀[ނysy5x ݕgߢjXklc,G;'mR^fYgW>޽{;;o,<cҀIV! pf ŧ!ֿaūno=hkMB-[iS6灏 ¼!rI牸`n\<)@OkehrOTl΁߃~48WÊW] .& jrC` ƍȶi$־AAteveq9M77 p߉*qcVJp5 R6m*–73c!~"ԗAZdt(הվPUBUO$0}d2Ez }QV ]8 këaūnoZH," 4?Gǟ3Ɔv掙΄RĔLS`G>-P* Zq8հU7vWmI@cz1u}xuw!rLO.Ef]'zyuѦgO\S/\h[LB>mV,Bcch+ǭrwlWLiUqhG;t:49<{hiQVJpm5 cӧc &ukx\~;oXOޜ`+1h0nZ;h֯PM >XϫaūnoV`@Mk j'*`S.dccI.M1sLxylY46}赩 n͸u=i^ +^u|kw% жQ W' IDAT|p,y2iaJ11,H\mC:|y7[ݺL& eݼQxh{^ +^u|kw% ж{Ec%'C <@;P^Elo˟^^GfQ+rxK |BnyWÊW] .&>}Ge 0Z5 0 {2֭?0:uv܅L:_H5|{[odH" 'E+y5x ݕ2@cٸHO7 :z͓$rW/gz͓>}sh( Է7T*嗁Gmsj( ,Bh|TC&+Uh=5Zlͩ \h{L,Xr_]\'']ׁo:$Ç7Xv1cXÇ1(prrJ< :} 2 iߤa#j&ZհU7vgL0Az4Qq  є)De:t(Q@џ6P6<5#-2? T;tŦS =(uǶ$=HᏵ@DD)}U:;54$ N+=蔔lڴ Wƙ3gh{MB#}lu}ؖy6c~Ftd2~XUeϞe֭ntu'[Ì?5tWÊW] {ѬYhtQZr%%wHMo"R5W^!*/7?>vyO٪sZ-QvyXL(7Χ'"t2״kcoTqH$ zvYdK.~Jɓf͚aɒ%X^ѻwo>RbF^x(-.\zHjDR]z!btuzCdzw& _0r5swg[&Z'# /`W.3gXoG*P*Yzp`0ysQUZ*W@@+7-֮Xu֭CqqXdGEEڷo_X&! x=-$|9y3ahoZ~<=S2=\ƕJKX'\/f{ jU٠ :55MrCw<ܹǞ={AaX֗XddL`*Dv <$bcbʎ9瞃CgzHDD ۷oou3̈́W._{6;bZ FdVUe ٥ f b/_X:kagM}uw Aa+=0^* ?_[%}fMSs눸kб7Jκ_\ؕ+W~,_p)ivSN%JE4j(*J;v,;4k,Z~=Shh(M2&MD .Q*UZƃVj>>o;\ƪbFr`@a3*7>mT6em>߲J.]d2wϟ_rݻ 瑎\y=<F kӯgtm6~u(o+WdBg,ػǢ]vhפ[zpASY8\yߦBX `ztdv^xsH*NBrI2<>Lxw/{nk]`8tB&Ώ3 ~~ߦ?n}7jy震~8s83X_ֽ?= R=2Vf+Aᯀ\!\&G!x͗݇//N~M"xl0`84h5P+jd+ei(^]ss0( :~:Bk'r~Eۑ{p?4ڌ%Bשpov&X$I(v萐ƍxwDVb$ O5> ?bg qU,QǧN+W71"22 e h Z4f_~)%)A`#x3dk8^{eܰkְFvi`h튦죠WΐdH8] V 5029z6وDjE\Z? ty}ˁp#z7 f ꍔyrxK@FU(F޲j܀)ߛ?W Gyx9|/|/@v q)%%81` JKRI4>Q^^"!_P@tL/;t裏l%hpy\IsN1;n:rR%ȇDDmN4`сM* =ͦu;< ,=y귩ӿyVPβc47rw䚕C(J=eoΦ)^z|抨8JOR7jC\&K7n.+#9h+ bԱ#6֗)jÉk=ṳitW i%i4f]g]YeY*ISӨ]l՗HivkHDA uF@ 'ε>gv$bߊUT\@< %%ҳK BSBvCETeoΦO ɠ6/ /3:]q-@ ":ƸcU[X5xPvffZ%v$uUĐA04,k]t,=N&$^kQ/ЙʯfS,BX2#ݻ7̞kP=>a=6eӥ~昛Mqqd[zu+E\Y#PRQ;qt% Is(T*PJ7l$j&au=dS,{w`R{e5Od !00`t5aaĉܹUݫW/l7 3ݟ1?{|e>ZlʚLƒ<]s9ujqi"vӏO)<31_+AlvT#))FDD+/JAA[od=z-""t/-f/\I!S+QTQfQ3){n{'N,kCsCRVYm8EƯ]"mv-/'>Ӊt:fvl$vl\v&;v-QQ*u4[^9b%am̞6oNzN|mWСL,A;l}Yip <0O8MwNx(!de"4 |[!(<ie``&ND8<0ohcdsq؃vIX$ "bU?̖ڀWX]ƺ*G Zzv)/{2yy:{ƣu @NR{z RѪ1113!BBcPړIYIR%(s]J,k\L_ڪ+VE[ndA ڸnѶmLXHqY6kGe>In)y~2imlTyر7.ez}v*Kz=h.. Wҵo;=G2y2MH@n6|-?϶@ti[)הDD(tE՜bDէRg( "4;ѐ^gQU: aV3$_"~!^֚;c?th>1b#lDl!r~ϡ#<ԙ YIyy҄f7JOD)@3LBJO'z)a W4pIxA(,-cq}zSʭ{{VgN#"y7):>rw- "" 8KQ({s846 R(c?Әwѩ"Ƨ-4rH͗惂ロliiDǎ|:1ƙ/[*(᢮BJq O]J:z ̜IӑAw]t4˄Zl'S|~iEf++-=JzT-bơ:KM1c:KmD,bchf_%%f_lafUVMȎ8QTQ~jec\-@K&amd,'߂w̨PY&ᑄ#:IIx$$yҫV䓧uGEOcxh25ޔ }y{nG[>~fe:{A9VO?:Μ9727d2:/ "Bj'P=RZ¡ / [N:#OgQ=FI_} v`石cO<K{]\}6tN f9J=hE>wr6AOӤHcZ\YLsN͡[jJJb LeY'z]Ѻ5QdsL¼yt%S)yTe)~TnK8Vo]G=a;8tMi+Ҩlg?# o|뜺hV`?1ol0[:T֗ژE_+gWAsEeej&TBIIi;vRЊ ߭ <ԾAA@$(> 5_V{4Tޠ2;fMDV{aJ벐䯓H yx&3 QsY*A z=v̪T@8yO()!h$ .Ёꡬe۶&1۪O"":0i-ֻl```s [J>.hpir J}Bc3k1b5OMejgE§ Ր(s}UۘӠt`,ͦ b,SZ9žKsWm2-^ď?&,OtAAOo||5% :q\X5sk-8!m9 `~J0JYB<˗KZJ7©SD|b[֦asjio9g7ÔJ%u8}4A(x[yu~v3*,&AGmn3Dm۲?ro;]AJKJ**Eq@3rJ c"/y2F_jql޸AԧOC mO'BzuYzuzi58D租،~F99DR~*nI|^|eJ$ֆܷt( ۝Y 4ȁW24Rg)::FF^k9sh^y9 w^NJk3WؓP[3oWSU9f-6]Mه7P^&17\9kmyJϫfBEoʋ7\s_knT-;Ot^4%*YZM`ŋ V$t%:*<SRIK B-ODttϖxcbkzuYG=&{r6a˾dbZr{TE,Cҥ,ᑝ< X:22z|+3O`| 2v,0|8 0.!`$p__`(;^}^Cw£Gm;N7n`HYd{,AU /`{hLs6WZ*)2@Dæu?K4}#OK< ݯ`ӕMVk! WPqU7p9xTomjAGDԻ_]JեvsY2Q@3MBMcyw((cɉ eIr\W6XNʞ:vt\;H8EZ2h 0.+csu:6__e}<8Zs4zlTz*]:ſOaalլ ^mI{7CHd$߳yט&t%CYHKE'(d egO|1GyxX3O܈R4m-KSN!"2n&Ff\.\INGTp#kH1ad?&!U7d?S 4bDզ{V "PIR|@UCTV%OcG> IDAT-Iӗ'4{؃4a9F)kTl7wqd z DL:?O~C nXS=s'_U6]qNc9Iv$ڱߎ7&ovܹF7 "u(D,YƬYyU*;ЮFNgMS_+NR#r=E ]ٔnv>s]&|&H7=!z%6lSȊ 46dIUNN4YChH0tdPȠ6Ԙ,*_F͖6[n_HD駦qR[߾=T,,)@@+ ?'Y@qJ&YgA^e:^ӗfIN:M+ԙjݙK) S(jtSmO=AΚ#ǿ_OMuqKJd 9Q))RVYie]<: Dչ!jmse1mִ (iNóWeA%aii6!? *:UDRqm  ^~j>OD!oVŕJDD/w#u%Pq*Q^ff(%¼J%LGzRulwiӀ1q\cj5QrbaU|PD#G=n3gR1ܐЅ'sӰ?WѰ13u 2dVmM,̼y/ t56oL;o8uTJECHH}{1zjVnD]A*ede2}y7>fE_4O9j(j7uxªػ`ܮObZy5+_mZۻxuBAB軻/t:* ew;թ~ͷ؎eqO{,矁GΟ_~5J% ܼ '|Qz!55j Տ ((Ȭ\ee%};CuLj2LMׯEmPC@DD.銸8}ҀHh25_f녫9WQVhY}ӧCUXL?`džg%z`̘H$%ir ߏ˗.5رcwޡYf)88Aɓ'ӌ3j+ݨcw +X]UCPQ &9HAkJʭ%`UVR'rb%Kj£ll8RcCJ Zy5x!~ߞ0bUV)tt)&Lp> fZliTVN7ڈs+`g{$W/h^ffZ$/3EC7e4X~ڷ}Ka?թ-̹nnە>zԞYP4o,Oû][? ]W=p]UCR(l3o7dqX # /(Zdad@QQF-ZGd ZVR}tMڦ&!--M&<OInm'Jb-r*!;ۑ˙ ɹɌ8A\xp! |Gd28t aWgo4ޝoRfb4-e6^7lHA#z=]{5!O> ~^Zj4i^y-,E+EdN:$xG󥤤/rHHl#c';wB.M'>e9\Zs^RL(n! 08xP}Rܢ3zUQPޮrŶ˓-9r?uȥKu֜θ{/OG37<]H|<:Jq])+-& O&:ʯ?Nٿ>X^ԩNRkSg’B\ғga{%ͶHil7s8a,nopyTIIȿlْ\f/֗W{L !6\9^ O`Io$O:%Fq[y齟yoܸAi}jJ_o|P5ћqwz[Bѣv"#mۼz=`qVTTa"!+ 2x Ls^z^LL}b*4j1 V[e@n.97>f߇ #2?=~"zGۅצ6 : o%`#ÐWvM I@[,?HL& O?mEգ| S8ss-mV [>XRg!~&2}:>}HI_7?=3QQs"ws(=T7*$ d6J{!{D4[g!jy12G<ЗBn2ug_OID FAIA_PB Qª@$ZSUm۶9RlWB- &qJUomx$S[U(f琤9\V́]N Cg%`>,SyZ݀Yfu;Ot\Rhڰy3ylL`NwC<ʵbټ9wϛ^ؑ-fM i^S_Hۚ&HbA}{_LݛZ4MQxWN]5U}қm@$[z@ +[,:ȟ.J[S? 9ĵfBB團4sLIȷ&4 D?%Kh6aIEE/ϱ][&ȣN HdQJ54ιIl8!ʈ-W $[-*)q}ܲ04}ѣ_BYvh/5J49.OgRN-r8٘=[\i\db"4 ;u]db7i xL!6CBŪ!) 6j47}<(xMja—Pn)[VY9Omۚ9}cm]4Mlbaa!L W/p 7C"8mZՏ?^ xoٮ#]nܸs_ bjOV;MrFkO5CS$~R}h)8d$QUU̜)vj ~;0z}(1k3/33gI ˖L;  "a–TѢEML0 hܠ1RSSb|`yr<}ZQ;=Wz۷͵$X_̽3IvNcfaPp#KEmfx=kf9,R93<EșP4dtMm J 앜‡RL=mCz-R1HXMFUOV[g\:&|92,Y{e+z\4ږ;i7 pe$ @tjfE7vZ ;?/"+VZV:}i:"22%&X ,︰,()<SW~YYբv z;uEz:Y#2א$tyyСv_Sr=+kϞ-ۤ0ض6o-EE f72fR"P!ffV~ӧ$ȕ+ź~LG "k$g[47k2.\Ǜ(r9RL&Z9&[;)s^kkQWyRN7@|# F08.4ED\t)32ȣ) ќF7jѢJ>/E㶄m$=Sp,INB4O!I ?˼^紅bMoEJ}+ "-M]#I h)]- s߱c@ںFAPa42(.mF1|. CFNVL\(+۸|x9zӚP9fČ̷?w^tAݐp8MsڷS_4}1@fƢ_p4i ,] e2 /B@g@wa#M>YԼT\8y +O cc*Щl C>fAаСw(0nk iF`H|?tX)7^zP@\B wзZ2Nv߷m,] Cnoi KHjw4f0Ad4^s2MY_o3Nbaq1- o60i3ɋnq5+a];WsYu–v<={云$'͞$Fi;$̣ja^qM$mv{ꢷfj7Ӆj,SF݄P{bO]D9wIrTd4'sNQcx-mڈ&O>Y"lVS #ZT$<ɴ?Ԃɏ>LJ42Bde_dmz+brYl@ (-^}hXش}Qk =z4pX?]ޭc  ?p>!N8&gAp*4χȌxY6>ߴD8G!^o6^|4wpo_>ۢᝬ9 I:F)AߔbWy3-EE-۴;&5ML E@, ­ (Z/Wt[}.QݽGTi&r ZIDAT9\]Ȫ[:)) yyy /5k8߬Y3X,jժ±*H:0|!!bm.aF`ˆ.u Ѿ=n=i*d ȭ]Ox@'&&bNBCCѱcG=܃Tcvލ`f(7ZV$-6̙bz 0tX '%bsf3#nHX4`,ֻ7<7vcTyMU7 v=ݹsgDEE9{ב @mƺ SL"[k&I7Zlk=z#^{ 8r0 6{6~3wbmJq@TX۸QEG"־RǕhXk ظ4||Lڸq@q8~uq]]ҍWFk񈌌ٳW,)Sp6lM&=>YYY9r$Ǐ#F\^U=VL+E=ߜ+V8FB1*ڵk-w?-4{圗GVݤa =1j(X2niNvYM-[;wO>) EZrs~ȪB.f[LSABS^w׮g88}reBfzBJGV݀e ȭ]OHi-%[B6d ȫ]V݀ZUzYujU7 v=!VGV݀e ȭ]OHiUȪW ) zYujU7 v=!VAB#n@^֮'4*Hyd ȫ]V݀Z =y˪[@ U7 vYurkRh$<.n@nzBJGV݀e ȭ]OHiUȪW ) zYujU7 v=!VAB#n@^֮'4*Hyd ȫ]V݀Z =y˪[@ U7 vYurkRh$<.n@nzBJGV݀e ȭ]OHiUȪW ) zYujU7 v=!VAB#n@^֮'4*Hyd ȫ]V݀Z =y˪[@ U7 vYurkRh$<.n@nzBJGV݀e ȭ]OHiUȪW  &DFFFΝ1cW^Aff}ɞvý-FȪWyy[^5Ёx+#::!!!}IY3gΜ9,X[DB^5Юb20f4k wqkoKiiiqAoq;v`ժUX,駟z[RHHH%KPRR: ے\b`߿?>#o˩v{ O< mIՆ$>m۶$O4h#Mel2)+ ~icصkTݻcXlbbb-ef͚_~2\^zh޼9Ѿ}{oqpowm9v2iiiСu/z[KDDD`3wF˖-x[K[liӦy[K9s={D`` ;DoK ر=zCE0gL&L8R\⥗^BTTbcc>ݺu+N8@lܸϟ$hԨՓʴcǎ zzY@:رcѢE 4m׿-ZL&L<QQQx1o|8.\(u-ŭ2Њt4o\MPH2ЊKwXb&O,4ŭJS( v BSV( BPe B(P(:EhB)@+ NQZP(t2 BSV( BPe B?umfIENDB`mpmath-1.1.0/doc/source/plots/hankel2.py000066400000000000000000000003121340375245600201100ustar00rootroot00000000000000# Hankel function H2_n(x) on the real line for n=0,1,2,3 h0 = lambda x: hankel2(0,x) h1 = lambda x: hankel2(1,x) h2 = lambda x: hankel2(2,x) h3 = lambda x: hankel2(3,x) plot([h0,h1,h2,h3],[0,6],[-1,2]) mpmath-1.1.0/doc/source/plots/hankel2_c.png000066400000000000000000001060001340375245600205470ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxknKU&^Z{B$mcԴI}N6*D4ba 4[Hiv<9ibhi`6 {une8?6Fը+QUgUE!1(2=%SxpotDFeQF}#0(2-#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2(2=*#@2(ܣ2FG^/}Kx[ނs|4(\0tCyk{{X.u7:J2A7կ~5~ fիWQeQ.ݐ}xߎ׽uxކw|w۾_a2`GWp Td#n+Wym7{|^{ެ~(xܺ}[wsOe<x;ށO?{ x97 ` {y&=0 <{RÓ~'kS|c_@Y i=G>W|c`3ADУ7/>1W9 +mNx|el5ŵc!'7Zu[&R}'M,7SY;AӿQݐW?ؼ&Ϭ76qH2lw[o\OgoPՌ֘zS:q*%@!epfyݭepVPձaK~zzAk4V5fZUɎM+x3J`-ވ曆Z6Q؄}]~`ȀYݕ,29.D[;3YT[¯Z03@,ժSi-+V>Sj^c>^Aoڝ!ˀ 7!PYuyJBeb;J}E`TQ.KΆ`BJa偖8ԬduHzۄQ^ 6{:6cRƠV)faČ#)ʯ2? ԍnQ%p#@ߕԕY{e&fdUU3`X̨Bv:bZ"yZa0,*S|DdžLpԊJ°2&׊Td-/2:y{/T@6LnTM pڱ9K a.݌ T+~]mWM1VgjeJ;J%#@(l3h<`k1.m6fiF`hZ+_視jˆ!jk;lQ5AhxUؠzXT=9iʖP~qcp٭^V9 h[[`D(#@(~!6 :f-lsb,u2Umךj׈f,C?*޴Ao>,ƛJ_.)#qsV {z+96u.XFőd%{6ۮa!0C9sA#\|s-'/Fhs `Z(g;vZ݂&{-?;Z0tf zb2'Z9T ~[׈JFQbQEa!­- UV9f>X6[|ĢE6$ӹDmT[(2syakؚJ$no;(#@ߍĹ8,:ɠQԳkr$ Ţ,7; |yAΚحv>0~4EG|CC a;3]BoB% ĻbaOb AK;J,Xflѡ(p:%j֠kPMsm R5N\kwnX͐[jf@uDc@--dز7+(ބQ6RQ, ms̀qLp;#:YU76F=j*[=h+[ !#@7OO|/x p5uu A ):-]Rlcj7'e0Lh.8(223hlc` BlLb|nFEc3Mt+c[ef!#@7ӟ4o{?>0_qŵO{)VX1zGbe@zBTOoV_3~k8am߾i]Mm<Z+'8ͦ=eHYytXT?Q: yGp~~xqM_X_x!dє^τ!^Z [11]cdZ~a瑄۬:^jFּ1 [h0[t606F5VoUPߴV N8} O+ɩ )#@7 ox7㓟$5뻾 pp2uquCCزiɫ-U 6hj}@Oo cajce۵TPܣM sLe*< T#F|^1VQM(~㭄MoٳQh2r/fx%>_g.ݐﯮ鋠 틱Šsl(LZ*uNnj2 ^YUN ֱҊJ يUⓍ7FqրfAo5 Xi{6v؅RidI( LF iOAm`HPp1 *SªVh&S<ϝ{nAe%V܆ʷp*;%ס'%qo^KKXPnףzga0\b3 L=Y*Tfnpw -7K8/FVOѰ*U3l!~/M-&p}2``8nn1eSڳyo7GF+,p,֤Eh, RY.'u [tJ3TOA:~mx s;PGWH S*he+QNL5̤s42P6F@V퇛P2譹{3CV[PWaEbĪ9^rԦehr/ }R5|Qt`޶RE.2Rm[CYMB PQU6@̪`t!y ж]Q#K3Vc)ޕ6yQTkaUIzb;JxjVQ^0K4&XP}gme@B@0P+v-ҀrM &4u~oU(`v.{tf{t.] IX44 Tr!U"HF 8tCX܀*USfM=vzbS rUct*7TKEZ̵j )ȭ]h Q,MJq۪ΎJ1QQaiPmۛ$m5r}]lzG^6s"g Dz"yW~B{'ea]^K!RpneqUiuk̵0 !}ؔZ3V_P)qM /Q 챣3H9$o<10)TFIR/Z.,QbVzXýRt͗3;nT֊Ҽ-lBy"wD왫ZJ[MS$8)5-,CߺZU7lQler)uP*Axg(?AE`"@X0RVá2ni+[FN2DveWcR`7GQXK{"sa*{`lhHf56m MD9?ĦPRu\1k}ސCԹxbJ/(NJܯ+7eH58˗#n[,2<ţݐ~8==G>|_Ə؏Gc|? = P8W`7IcPrf}GG8#;zhDGМGJXfWuj?hnZmAMSXFQι}Y|柞s(#@77~7x&O|>(`~^38As7i"®.ձAyo8UT m@]7Bp+E@BCVlt0KpVjhܚ ;3#(;*f՛fpq5{a3iJ=A y?p|l/UF zիW*3Z7Pbp(_7!u}[ՂZla <(V!Hܰv̢_nk0}pKH|ـ-ViD/i<-n"m.m_hz Ͳe&o.d?h_3Pk[tͭA+ĥE^TT ,n ͒M?N/Znlv0*KJ-S%vn I(jj)rؗ]6=u,90twHt: s?k):ҪZ) -9? tU&0n5ur!CZ,./6V;Ti]kNm [0ʐ#޿ax*auz2@sazx7z2"tt\J Miɢ>iD֦|5Zyް$\22-[( DM,ֻfnΚK|+*Et;X:(IFQ|Ak Gs 2ݪf %Xj2`9;.ˋCw IDAT"N.u\FKellV v6@nI-X|ČBT0q -`X --SB5 =4"uwy-X?ekԱ EU,Sw}PQ(yW\Dt-tx4o< S @L P M ZٚD4ڊa Ͳ Υ*22twгQ A}MawtL+ ((u@:lM1ouP[2kvoP hfFŠBAqxTU+;:m08eŜmGX ʌāAAa;0šd%j)EUrXy \Эj"dȻ]}S}X#zښ$I-."Ju*3GE]-ɇ[3;YDA"8do;pCަB˲g&x(#@߅ht"lie{W f$ʕQXTʭ8jfdtV JV(h863¸s;4sVofJ:l9?e|(_!Fj%i fA'0fLHVN-tK4wAtVx ظ֣9X2 8N%J+(,AvG2RYbE2+d .@ ۳$4}DoxKeGcS`7AYB RTm4[9(~PBhc=A MFU@KzmM`.x; #cOU^AŋA_ ;+p&$Uh 烞_TS};[lvh{qljz̈a[ ]B3Z鶢Q00H Zk@9[]4I :; s=:jXX`HFȾWTITU%aO :23n;(f]qnŦKMM*zm54fꭅUC(=nzԾ57tܨpc7"; ыhJؒüs`rk*H(=̜y/ߪ W.vIA\AE6 dͨMV!{M՚`6n`Z3PG}r=d&#@GzGEsAOSԁD@ˢFIiJQªN1hoڡ]XNe-fCR|H emh`?Qc ";:'˹fЭy9j&,¯^QFYN’A@f#_)Q%mwNYbZRQ(s8m&KBz%ۂey(bԠTk sʜwB?`:Ivj~ֈ /#@( 6<r$OIڽnoSdMk ʤ@9wrڜRfe, } lRkj13g FZ 6N68v]yq4'W)hW a)#@7//|>(~W~@̂4UQ VG{qi&SYY2* i.T]ԣhXhXp3۴Q5aMX1CӍT+Ŧh:tCF#tcoຝ(nj$sedʳsj,b)}k׾O%5Ѯ0q@D FfCTOh5o煶%=0}[y (,E?X@CQ F~$ZZ}I l0lu6: 5p:x'>D!?4"t˃bѱ!y(#@ox'ӹ/%/E^06{ɬY7Z9 \NB"mDlҔ=Fh)6{Czm=P%4Yc"aۜUM&bhBTnv:s3ÿe(F('㰿!Z~CQF~~!]o=3_vő %W r'DHR^;qO.<^]NXcYSDɬ"`98uLW 7R6,qTcj?: 8X`ΗzZ訯%@.Bs>/8m=XeI̛mTbVaU%?{U .ݐ?#<y>};;p0ĉ @B [4u(G %hp&DI1 -etv\#G+=gJ J%UYh/mҲ7pb)lˑ.k la.L!熝eKXM(;ؕp?M#&SFnFo4ZN S3H@˙&$ q8W,%5BiG32́}4l _x51hRC[V/msZY pܞ_hBdz($cfl)`;0!Ɣس鈆l PCNZ~ 5WGp%Bl,'؃@SȬ'#(ۣ.#Hm ӼqdP\f$ଷI`ϜD`=tj;CQrv6sT\@5ԴWzʮ_*ٓCǁyC@VzeA@x`L칱ת@z873fw9!"/PK5k=xK|$,MW~ Ȼ9gD8%Y`3(0@ pǢӰ@9̅Y#30PO 79@q#@wL Dh Ζ4BI%P/dвG-|%Λ>!ɥ|9VfбaTjDZ@ig9YFY~s0M&7S;#@ :gТK`Y8*`K30/s^OAX1 3bv)f@7ht34 }/hޘ850is8=PsbJ9:1aNf!ZCh"8vh񺛠\$xQ2#s BhAǨHۆ~ӧ`ͱW5jB=mDPV͊[ YFU.1x77 V`Q!g N݉j:sԐ@" TGdBAhك 8czu "pNz=FG@{9@sF7#$ ̝g}lf/q>wK8~i0aL3@8Db{ Uh$+!aU:C:Z\:XDPFYv X*=F36--! /+zWa9f|!y>ڢ+CQn_ I]Wg@,kBQ +[ƜRぢ|^F@N6p<. {y#N; qٶkp.-ueC£g:Ġa\O"[UҏG6b~ ;;7 /yKƐ;0{&p6X1gXsx@^ t!PvKœF^( Nj%ysKxpn379=t8d`߁&#:c@H;4YB%kr~&r,[W=K#Wv.w8PSC94bȓpXtpK`qFԼB/p >r"s6KHMfԝf<Y5r4Tlַܷ{wG={{'#POnπ~ `Soyu,@wn%$הL#u /wS[{S#]p5 |nj:r0L^^ԁ9D ,(,AzM\h1Fx1x~-:XK81hltU`5dŞjݵ(c?x;p'[+x>wr ggsOVLgǒ0YƙUC@*]#b`L'ϱ!,&[5x' :ﹱ3v:ӈAhSKP Ce87;+px3*=Wpp1= 0Rl%88F Xq6sV\c—KdCWPa:$J\SڒNI %i~qDٖV}D hr4e/>~kyf_땷e*p*_9ŗOw֜yȞUj#̟8Q\kG;8 ?s8п[ѽ=0.M1xΠ8%c- XqܳxRhbZ#.O|=3)=;%|7;Ƽ)+Ǡ&* <;sޚqFIiD)<@OYy IDAT Pf \0}Xϭ FHɨ5B*;Q,̑"+ŠIshN`(5@O$>੧ !=iyLS+3gׇ@_s s @@87m%/a2~Y= M=ҡgy_=p1#`vz`:&ΏżS`$kqH/O~ ͩ7qp0'O@8# ͡7D;oL ?Q`+N.i+AYhiF` :m0qNAq\ڠ+{G2y8AeY7ʉ|ϲ?ʌ=Lw ۿ|_8%So@_O1e{")L9! 4_By ;P!P'I"(Yhtca&_t@M] :xS`L.4=I&y2& ? Mw XY݄p__s)0 9Fzp8'SMbdw9Mi;BYuu^5k]/; )IO8f ً%:J{'8lYmEdIIMv~O3@q" tI} 23K ݭɃQ )pu2^2.@{_'EK8 O쒫1Ɯ’*V50'@VϮ>YPG RltADy¼ -K6-sgFl #@gox7]ܝc1 l[{ -n @ DjRO~2uƒb- Xtd݊h#o3=yxѷy9wɛ/qcr؟9LB[+yA9d.;+!Ej. eafѲe{mb6ovhȠMowԧ< ੧k^K^|_qgz bu1&أG`<A=XAk, 4_f+^nރ=hutq0Oɜ+ae;tĈɣf/"Q68{Wb4ᐉCq9HT83֕x;y׿GߏxG~Kx>| > Cai# ?8 qǸ]up ¦FGz0%|k>P^~~#z\&ʫ҉VhA8y./q`1)p82Θp̸2н pSpCx 1z?Sk3d 7؟KW8`e o TT0͑+0PuMOCk|9p:} G? "|ox77x7߷w%BqtTǤ lʏk`)1\_')J炿PhyCuJ4\8~Pq-h֫ɶ0 NX4?11n5 ay1{_w%??9yUp~|R^3ٲEOX<]f}7<9:NKYPK`NrϬL" -\5}_)^x8NKO~?!ؼT!3EN2P)z>񸏠+i0D6yDN>bo4֜9 +3tx5'7; pp <3 _eLOq~qo q5ι }gm:t P<:9]X59kinŘV3˂WDEbF;>%/|/`<+/9W\}CY.r :tdgj^o*irc VrrLZug5ymG]X\}]s0Nϲ6[̸ ๾3`|CFw X_c)nq =_ncs„Q1gHFrk_"{3 x~C ړ#cIýqa}jmhP5e$5@dz>=:4.! Ŝ5aYHa#W,ɞ#ǚA8{9^ѡg0b9;=f b=N8f1؛5pdƳ)Bwޕp++9.dW@?Y?;üQٟc]znHGi.}cPhQs1(ýA0Xt9a jQQc77aW`m[t.څ!ѶGs ̔ca5Eb,2s(8ORWvz9#i [n̄38p q̌; &mL< p݁g&a8>ng9 3큉c?Ն %9LMiM񊴉YtFG54H4$C6,}8K!`D(-@ďȏ|&`4i/2TfB⿸i3FuHͤ@s SGG2;'wB(0uhP2{h3wg=@ 'ܡs=xNI XP&{w8q 8`9f̞Y\ȗ0hb)W=fMed˃A*|*1#386A^#7s/|~}%?g `-syA0( P;Od69C~bȎM P^(2l QyqHFh鵁D>g8_] spXm:&ׅUS:2o{ k . =gwa6UfTMˉ1Yu6P'P'N͎%ptsAK;4GJ0KUAsK`nYX́* +-@կ,:.$Unvr,%ePPgMAKsd0o=f1(A(9'Gl[!q=ΘpḮstg9@g5bρGo560o02@CHSZf %Qmd+M Ig彡;%Kb;ĵezP`-ҰtB;WF0wm }`jЖG_ٟ#1AHKYBɪ ս9밐35$-P^E#@g.$^* 6ۅаA[T@s2o ˤju\g18vMf Q>lyL~8CEfLe"])3^ڠcĝ4sFq̨㺽ɜS{ qNhQh"b3jze/{cMX9[~.p{$#@(y.\<'8QL$)UjULx !HǪt֤-t8M# lHz@dϊ]@V8*U=02",}5j^gFd0Iu*SGd ֬L\3+ꅟmވˉA؟SAol% `IDPS :G +HE0h_diYH>ٽjܹ eP20Іi݉(; c(nvMZ %y*PW!\rg*~8s yַ$@K-n> 0˽avLϥջA(2{'F͜*]IG K]DA#"5D*T'I޷UU9J PML"1>J0b%\#`4F `(iIl U 5EKBssqk)9NkϽs5o5捏 >cy){]CM7`㠵'CKOzQh8߻لBwESYhTZВݻwc"mÆ X~=y߿g ,7w!h iW% á^9@-80Nd5gB9 c0#ucsYpp*ʌAkxHpG2; -t0Gpn =&7J_LtJxXpclBTNzڵعsIGp}a֭"s X=U6uP^%8UICIj7^һuٸbi$$F M:OɀqQ^>#\_Ʌ Ɍtu+#uRcaa,S+\ JRkj~ܹ2NΌ]w*@'dK/uJo˛e8{ |hdy+z{D6H4>;BQڎFAhR›j1$ju@G #(wǢܩgޠ;H|R-OZF|4>.^;椎.CҊmjXX.,1V Ms6nԤ@#ׂ3ҒTMg+vcO#kזDisɳ8e8{2,_f,-yڣ3<򞄣sT''pR sgI!~RNtJjs9' Ix9&K l} QmO IDAToHpt(/v,Ht̷E+; GBۡv|D}-&c*a ;~3Ij#S )U+"=QEs>W1hs c@N=(+TXiSoPw8"9;i W1a÷ ˱gޠqˡ \ѝ9,Ǵplh3g I0ΠZ"qRisA=;uP}=1BI k Xt|sa'D#1KI:;|$cW6mf1gesEzrh=NdZ]є̬ˑĆD[%Oŭ|;CNB ξĔDŭzrV6b"vzQT,cq<PD)$Z-@u[=Y AgqzMɬltRӖ| qHBEܡa$) h3]cmkk: %쨵'ߤVHRjI)>?)側U2ɒ׏gV3UZ7[xؘ\f2ԡFwkpxVx݅5سm֨4D8+8Gj95t)"\t2 >=Owp R)Xw#98TpPgWQMH3!V;뵕7P:S )wS В&4gq혽 c;6j-p@iB=sY?N9:)yζ\Ҳ<cIN9sh oHš06]9!O6Y騌*5\)vf=(-򠸱]Ƿ31`QlgPp: ^y<^8|-aY d\BiaXt [UlB#!B,P gkB]!g,$!4=eRJR8Dr( ully/cSSnxu Y?/Yy&{;!@;x3b鑊;'#|M㠵hS均n' #Րu@c@`V_Y>qn &+QSH@Ad2Qf=0%O'ynM0-/ oI`<]P&E'Rʤq}{: -!6gK"C[Q+]<ε.t>6d!&ГVy sCBKj%2#/FtNp*N D $c;NqT!S&-4N!hs ylZϦĜ(\gɴ !,nB3jvT91F˸ =A l*)`tPHa8+6 =!k?% y le+>K ġZ;.!^2v2 ;;H"@ ca9 t4;C0#@I=]>WҼD(h 49ʼBTK̙8T;SzL*]o?8v)Sհ5,!`wck\B9fXbQǠ%URR{ Ä1ç'vE#oRJ8h stϘ rm%0*].&_5]eG8Ù %Oz衇pYgGqIڃV~4%Xr֦ 0fD"0+ˍM}o =\)"lҹAkB]C,W]}jWtCNh%"V5tV$5L|Ғݻwc"mxqw{Uw׋A{keNhcjRSSOt53YXD4[H˘{QÐĠ5YI&W~%[穾GwR}Q9%%bwPtFnҒkךߏ㪫?|]t`IX>AT}=쉜Œ2%hg75P-.*58"l!I:<ʏ!KH훯?$9i![eZ k#`hG֭úu/B07 ac08Zu)RC-Lڬi[S#HhOdVoy0V4<|+msjz ALYvxzg!.1f`%ɵ_,ۨCJˎ#:1Y{>0.hxGR =)y:SR dMyP%=&/CIs<#3q'FETC\[\<|_b)$ooB%>_4 )gl+:H6?C,%=QCc2AJ#Kqx͖&uTB#2;H~K@+(6aD+O0Rz蒎5{ 8;+nR -ب2iDVp6TzB#o|UxU_, E1gϹrQ00+IW+IJ_V5]DW> lȈ2a-h(ڢ<1ǘZQי΃_[ D$d!@ b :ET)3@MI0qj,9w!&VR^_=eンhrO>踏9tuQSUIZqY\H klXJߜgjhdו_%"6V$gX*w:H 78Su#F錼FGQJyVE{32VREi ZPV^:(㔂V>"$GBC5T h2p%]7WU_{Ah|zkԯP9yNy#hƬJiJ/tyew)8V gxyC20, R0TfEq%y6'p'dlxҡ R&@٫`ʺ6GNd="p =LX^41(*cwS\0VUu/ [cYz\%JQ$.9YeLH?8sJ,+UxhжI' OM7(pd Qeǽ;Ht5#DvʙwNBɑ;!VW@pREDyW 滔D19찊x5yW-GGVK Dy[LjRU񥀏UÎ^y:JҡMl̰LZQ2xMU4ƛkԩīݙRƙ5d#^UC5۪ONq /䵞9nCxEQ=IY%۝#DjewQG(9 T *Tz 7ƮZdsՐuYjNI8R:x ?PCE|e6,!eهǐ,K_QOgi% RqҐw7ݠ`+ UPz*i9NfX?G3 i_lUdD*`=C?@BhT3u%R֤ЩJ=c/>s\`N廚iBH1:ETΛJ*@OH#.0 vr@T79 ")qO:܏PckoYz*LXh{C9Y0Gi"{TcJV @(Cm9b'ܛqc ì۫x5ّ1x7ͫ<Ņ#ا7m"Je ߮ 8D@}Jfr#MWTzBJU$pcNP'*21S`=hx#ZVj[sKJkNGgy}I|j(=*>^6%kMz+7]I&S1lwݵJ*@OLmvkE[Mqg_kyM7+ O_ݴhn7>ҫaG.k`sgWP u#8:"pth4(2T"aYTl۸O׮d BɸɃaa}t =|)+FǨ(C@y`WS#8όkgʰRG's˯fd;\J3H% J섀qN0zjW~JtI7nc[-X eQVfdc(Tg3*LT @)T̷!LD%xh1 (UX2]3RtoiCP??OTC)jFz^0>FݠZf. "pp<-@ġ8UJt&kI3)'}R'3)kE|)%]ER]tP^ m|8W);Ƃ2y%U826 La'DI;kMEi?Dhf(>/8ci/>F\d*S.0"$> Ђ*@m6<8p7bʕ88KPޅ4~Q_zBdM{6#&C5((ѷh,`ʕx} @hpL4˳5|Ț5ԉ脞9"Ǿ{%x d](WRb ɻP[*iaW81ESw &_MK=Zf 8 \qػw/YęAh` y&/[95iX]qȓǰ_R$3XjSa .t&uIef V4r EOșI{W;۠!`Љ*@~M"b-qr[D"0{sS%~fDL,^ N9:1LqAAɷ3ys!b͈+Ur5)׻^vm&`jd\ijn3eRA[HNYםvCtab]WS58G?Hϫ0k4 ,==1y3| # kq ֊$OZ%019o(ŧB `@ إӜqd9~: Cn7K#!Ɛ@ld=(44B=bʭ!5$WР_#ߋ"4lbvNS3>&* c x2ҧ^>ĒFwHs5iB 2_Tz !/T؍E1*9륋NLd@EHn&fZʛ3/5I&sSIJ\*@OE }*VnHØ*RTCiF砏A=L  jJy \%J>ɟvgԉbV:m'[TJ}UD5?_T[)xtD:wX|M(Y)>&ͺ RǸ=)~B<|uy%pq*=R@1Ci0hQ)(2z}^'gJPZi!NC"Z^Q_GITvM\|uy;"˧--=]0G6N@ $>\W0 /&EaCvty'*bZfƹ mQ@cr Bc%UR|4٦r?Rղ@zSwt b=I•$RwbD;Ie**߁d(o;QCuXTz ćs$/ 4~.f+xX""tqMA+8z4;5PY*5 J*@OAD)1 :u J;8oQ=>=+ojq5ɜL%VΩR艉{6ªϋlA)V~ia5w:e+pid_7@Oa%h,]&E W݆=kuao??n[@ K*@OA <(t΂#FBRj4~%8L'>4ИXå{qvXMus!ݐ y9Mz𗚧q}eXb鞴9uDǖ9 ЧЃ"đ.yesd6)>U2-yzؼyH۰afffկ~/2x;{v Pҥ5'RiԻ,_՛_p"9:m2 |tT0bFZ\{08 <^#q25D|DvŽ;o7q1NI'N:iQo߾EQeUYﵬ}a߾}oӟhOTڡ`ӦM8k[n>:[*UZbTz :mۆ'|'pnF\rdߎ;w\4o&z,_=܃e˖88p_ױb r)wDs~_Ǚgoqd?)mۆG}t$|+.W^|ESNYTYO=.y8tPX; K4M⑔uyÖ-[cر7n\YׯO?;{a(ڰa֯_gy'>#&/믿 .p^Ú5kN۶må^2{1Z g}6ݻ^x|Su]o|ؽ{7֮](?||_O<"֏v]kךW]va׮]]mۺ#-W_ų> Xr%{Öɺ~\uUx⢋.ZY#֭[[GW+~xWzE;ˏ-ā{e]3}s+qe_ǭWw]lV45Uip饗b˖-8s?W^y%jr--[`ƍػw/n&\8pA\|/kQRL+o_7nO< V?A⋘ó>5k`ʕp!l߾<;<<*TAWzR4KpbӦM_M6#Hwhqя~8?JR+Wm݆|ꪫp56Ok.lݺ/2n&xO^+W?={`Æ 淛o6m駟R~tj q9縿]r%+T=J*U:JzЕ*UtRJ*U:JtJ*TRJR]RJG)UTR*@WTQJ+UT( Е*UtG.}IENDB`mpmath-1.1.0/doc/source/plots/hankel2_c.py000066400000000000000000000001531340375245600204150ustar00rootroot00000000000000# Hankel function H2_n(z) in the complex plane cplot(lambda z: hankel2(1,z), [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/hermite.png000066400000000000000000000623661340375245600203760ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwxTUߙIoB RAQPqA@((*uUׂҤ+?ABQzh! i:s~ Ld̝pg=ɗ3wJpoB}PPPPP0dddddddddddddddddddddddd̡wp &_QQUgĈ/i梸G..rRS\O?D %7WWf1%q!Dp0׬㫫J̟?_6Eq1\\!DuEHШ4B5nM2)pGwrrϏ<]%o\E.r] wrKV;dxC >'00VVEIڞ%(.Ƒ\<\uj 2VZI"۶ms$E3F,Aq1\\-ӥ2lCjC PSSs QR-Aq1\\-K\ϻX&i{G..rR[a]6-72@5ZsΒg q"hy.B *=h9s$mE.\OS^IyX9hsjXnn.{=KP\#x@s)6J; Ճn)P\"hy.ԷP]QQ\#x@r5KqP)P]QQ\#x@r)9XBMQ "7ߐTFqsҊ-R4D.в\j~ERf!(KqmNgggHh#ZKVCKNNh4)Chs*@Zˣ1ZZE*ZLGў"!*++[L4@S$CZQTT$KK*Hx@q)]%/ߐT1wAk[REJZgP1Hђ-R4D.r\2dնmXr%555DGG3zh̙;#F;֜"!5''GghY)Q\"h.U9U.=vhy=hC2tP Frr29 >^6Hкuk-Vm/Bq1\\-vH~:^-)@.w1b233뾪\=d"aHHYYYI^AK)Hx@p)Z7oeee<3 4UV~z֭[@RRRpڜկ/\qy 0\_S\ҹsg݃"`{AYYhz9:tK:KLv^tСx'̙3< &O,V\Y{׬k۷Ob̘1R( !8xdmYbCw);]&}^ 9bɓ>&=i$&MTիW="5R-b QJqE'uP.(.Ƒ\<] vChsnnn*EB4D..j=]BfsssI6qm!!!䯦Ȓť!rv)q7*++Cնܙ X2#Kj%?޿R-q8h$$uы-Bqi\<]7=hanA;zZ(. 83x-­u%@KRbMXzZ;pmi Ў\l&KCRh,@+=h G..rtTC"]=%@Hh8rq8KNpO*{-q%;p G..rti,h%-,)>@Hh]E7rQw_kW Ϟ8dHL`` YYYk4D.x.{)w/N rgffԢ Ж 樨bG,ť!rs`GXzCӑCHHjCFq%,:b(. 8Kc-.-)BG,ť!rr)O.G{Bg7O۹7xA+IكvbP\"p,=e%EB6@;ZV(. 8KS@ вC"!HpbP\"p.>|h G..rq)Q-[*1J kR$KC㒻>5)S8uƢkSJz(. 8\GO=M Á,;QJЊ(. 8K/tST9$f%J2Xj2@ ˃_uF!((l[lxc䬾_IAVVAAAfe^Y[ зwg37Ngޟj#$$j -rqbQ\"LG|47rNo|~ 7Ѭ6CPP6߈;b/3 ImHՃvb=P\"TGh5xzB3͝oÖI[;nmC+gƶe甝l_0ej'-U-@qi\<@.W ڭ՜]f? vLඃI=;&'G2n8tUM!UZ{4D. oU| +j*z ˎ,#U$?;B{il;bg$ a [:u'1rH=gmHY$0~ [@FFwmо}{  (ϧ1t)`SN+r$;Rv)[JDi䭌Co[vMEnl>-%wMQŖ.Bl!Cg,X 6a6mĂ ?~< 2_s-tߐRO@ԮO y<.ʎm rޡ윲ԝ [:7YR$.rٻw/3gάck׎ӵkWj5z'N{nlΝ;ٹs'}a&1+]j'ހtzq:w,$ni{ oxE({\*$-$o8w:N899P\rҤ㋋ tRDa`.bº dhAܨ;Xs#<Κk AYgd k1x`C߾}ILLdڴiT nER1m4۷/{aV^j]rW_`ӓSj1rv LNY3`Kq8Kll;2@7gOBJw~̧?JWŃk=#P(b˩S4hgΜaԨQڵ\bbbصk#G 4SNImKu^5&wu^x`!|%U%~|vgUꐍ}zz:<7t'N`رj.\Ȑ!C8tSLA7mm)=l\:-ë޽M>tD :tbߴ} d-M RF{/55UV~z֭[@RRR]vLlc=DyE0y$&tկ:tZOn:Yx1Vuf͚5iӆk3Hv_Zݞ]Lis2oߙmmˡCX~=1EEE !GYY>}O>8|xɓʕ+;j(ItE+v6N4mH-hi.WǏ˱cDŽĚ5k̾B..5kCT6nA{ ?*R A!ѦK\[.⫃_IҶe$%% wwwRƍaRHJJCK'kY#Nz񞏅jJ0:DQQd>r вMq4%㖯uh4T*w =mxSYSiRr^ўXxG(//7{˽ܹs)//G8Rd.4 y4u<<:TUၷykC\=h!jZTWWݩEG!_E]Gt @&SnZ~jWV'Dg;a5ZK' %uRz`LBSGדŠA| 7}/}M/Yr\d^~eoީY ggg-Z/2ϟ%;V[| sSMus,Qpݜ"<<nbB6옲'b ,ۗΧ>mtiJȒ !xj+x4,[z_z/LYY=˔:uzhu/ Ҋ}<{CdHb $l^ƅ,Ag~2ꆽȒ |l߾ݻꫯj^}Uuƶmo!v) ơkL^?'~!G/ū%@Ż е욺7l0m[ 2ƒWc}%}x>>!xa)rzAgPP2K2:(_7_6[Fi%@_㠫Z&s84`."`_$شiDǎEU;_ؓ*#e{8?8D- bgκy% Mnvu\Iq eٙ.^`QƸ | L'lo<*j*$2{~NNj/|uv8;; /qc ?1|S߹}df1(Et8---E @|Szq7 @|qJ8Ě5B=G-<5VkYB(=hIH硍qgyX1befOfG*BiZGYu kJŇ~/HGjBW ]N~~0S{MmKH=Ch)`YNKKwLGw|^虵y|٥uhT?>/^Clb. `̘1ddd0|y-]23;,^[(q+߬~욺hh\jWLr&!XkgdUj.{I-cc]G]n/C9)2ͤ2M,ZƎKǎl.,uؑcǒ÷~k7bmB&uЖhy0A@ '4z Ж/fIp`= =Gz泛߽v[+)M,%sQ& =+qtƫ89ڐgE5j8_Ar*R+HKd~m˟V[q4R]]]={kcYsgf͚5|<㍮w$-7BFI>,.[DM`"\%@9 Z-Fy$7g ]2=!/\NSKu{pû7NL(+TVMR_ );^F2祣)nħw}ʙgТ%pI\"CjOZ*++JQQQ>הzXulhak\DпG|hٕ.z^\\tQ#N'v+.炨ȨE2GN"8@" Q]lXt_Ӊnݺ @ @t޽*}e㩍'ms~UV !ۘg2(A2; @Zl sm"NZ ⱟE01|pq)>X,?X% yBXjYcwyg?,Ab7Zzѿ 6[f\( F]j(k>ADGY#zpssw5r J2TWW۬Ss_sN:tbtG9=4cR^77n{P7ָ'_'fVM?{25kS_^竱EqNR{=[RF_. lɆX:x` qkF@I\򨨨>)k5jā$obN`.z^џEbOG[d,hr7[RS)QD^;DdQ}ɾ JN]vصkusNo:(J+?, ?C1 F)YT IDATB!JKtIAKEB0Ph,7'7b`@2髛xa U>GAƂ r"'t?<Ѧ}l%ȅ%EKyL7Sn/i李+3m- )\Z׋)RTQS.s#䑦wn#8JJ1ظ> Ox >ym R$3wc|t=N,9hzbLI'9PtY@,:/l޼(?wBH~9]!&.fܸqmۖM65X/Qg !Xyl%tfՈ=u7=Z0z|D͍BtiK?Sx9==`xicX cG4rE;#B˗ @Km*E5\zqhJu+꽮=+&}TTK;̟?_bܸqV?P|臇Dvivoqĉ}]If(("!A^k#!zJ#Co`; 2{z ѵ3f j m&h Mڳ*j**,@P;ߓL5FCDDvJr+5#voCHr}Ƞm۶ϕ.j-}JJqA0,ܝݛnLF$'~|)ei{OHIThb!)ATO۶eOEEj%)SwIޮ8Tok  "==!tҬ2/ z>9v1܊/^?:{[.!--CoRp^{ze&ɳIN\,-f1j(֭[ڵk8qOΝu,9^#$'[^#e23 6%寠{++vx .]4 e}$++vY%88իDN4*.w^q{r$|#j䷟-bѾ}+*"ĹW ]S:Wm6[պj2uA׺CęE [B<C ѡ..M Mb"8Q8k6qEϞ=k4RكLB:Dzz:AAo~% V]L_بc)'pd ݾFFv]o5y+(oz 3nNV15kְk.6lYmuuWrpziMB|S~FqmѩS'Cbb"z>+@FPy KR7foGJ w;WDd$xyM&N7izZŮ R/7Z˕cM]i͚?pB/HDEx.uO̯-~9 ^z%/14ܜ.h+vOM,wzwkyx;}c|=^Yb%%%%@;RIX9?~TuMW<6ek8swy{ۼ=FuS7=ŭmojrB.\},Y8<0Gv]S=rɩS/Yd oJM?Y1^g7!\ Y*]Nj'oML@L]R!gfAlkyS]-8蔔oNii)={[n@8ݻ`ڴ [P[o]5wIOO <\NDȾ=&j̥Pƞ/+ʄau7) R,f` r3ډH(kK_R* iU!J8X?>'S 7Ze*>a@gvym<9\,8.ׅ${77ou-5Z=k,8p 8qC/ҭ[7TB|'yPAE+m"GH>>[16v&I;w@^9> kWUiM:W m /$Zt[Z*K,~jq{~XʰEjjj{RIx%wqM:^ݪş kl\Ym4%4G=Idd׷\ŘUcĺDyuyڛ7oēO>iцI=C/N n 1kgX Uk֥wmX XҰZffЮc=&1gΜf*+%v|dzYuQ3Ok{,z>; E*N-*+n9. #FzMb'2sL˹;,n/==o7dڶm˅ *ooD'''ӵkk/U3T pt !6T.AA4ԝ,?u'ֱᏏcaB uu_Ņ|8hœ_WpII Tv ;% |#xzBn'aDEA``:+_h"̙FU6V_ŏ'guǴ^Ӹf}>5E5|$,GIr=A ¹snRSSHMM%""'Oj*֯_ϺuHJJۙv3s^s<&tϞ=&n: kגv-ڴ4()!aظB;s&<  t4 ׯ58N cwߡM2hGʌVY%?T*. fʴJJ5Kb9nnn=:)*2" BӅVbرWVV&&L f̘`}k~ YvĬYv+̮}w8U(+5MR%ݡĝK7u_[J]=V|}kqB1c@,]y cXD>]2,t W=5JgOG!@hϕ ;%2guGK[wbE$q$ap=v~YܳRQT!rԥm?O+VX:-6Qݝ+WZܞ˗/7fB)X:K+穹TC0|ZT.Wʭ{Nfrdf~9 ;RvZ֞X @gΜ^?.+56 #-0S1 +55]~is'r>!T&'QwĩmhZ;/V]šއ8Qr}Jðmww4RySO8K).kCOO<߿?>} &+%am,d.9ЙjC*k~OS^]ԝl>Mg6s蠸S1m> bhyޜS/Ԡ ぷޖwp0?NN:I9)]h5*k*9});INc%$'Ýwrg kJCs>+B/8)j j0z В  #!!2zqNڋjj)++ںB/H@:~ّ6F-tTp:N8 eWԍz^A?]7y/4D7`oY]XO6FE("_dj]5s1ϑ#TugUOvAlXyZ)G%,,l*++,ZJ\?..ܺѣG1cMZˍ́ʺ6.e8%xzHTU pcAAͥ[V$Ua (g]2ڔ/3# W$CUӱ|rT*'Nޕ%'}.HK"!33g8[p3g8#G8}ܜp #==PBRV^U^j!]URY¥KVRj1L9>8;d 0~߼\ DEC>Ķo&\yO~a̙ŋy7l3*c#in;Gٳvaor5;k m-̕+#3oB@mL4{QQޱ8222:thJu.MZCnt Ndd4O4h*B_,/2y+g_{i׾fb'~l۶8w1JǩH x\0[Й3gСU=Chk$CLќ,,Qs k<6{J 6ޠ3DGW6mzxҥ^M'HxJmVzjwbKqq]B.ŵ;e/;Ɇiʍ11 BC dS]$uѣo-J~~t7Ge?К2H~!sϝpK!KS~\D $~ýa^|`XHIwv􅆕j5JCpаPNoٺ!Ol"{'md4Fs\T*O{/'Ɵ`Kz hZ?ڢ<,Z5k0m4۶E _7n6|Zϧ6]z!(Ξ=KYZyy ^Fе+DE[=v\߷Avݒ%h˽j?]9.^7x@νp_$ir_gxv7o41)Sh";+]^pSd/5•{< D?l:&EWS =zez>2M 99~IM50B헩m~S~~t66 -vh [^τ & ؊؃d,krVI4AcLN{PTL2nȝDwܙJOi@x]K2Z ߡ="ѣu>TtqmJh(gfBt?@،0"^h֘G۶mپ}D !Yx\PY^IȔ:~nB8k23  n|;mMjT^yu{rkmb*pGX.||ԷSIO:^$P"_5ancʔ)l߾ݪc+3*9i7SA]ݕnK/{l~[2jP!ʬz"Ν;7y\S.p~pA,o}EHHPŦMמưKev89s#Np!N=qJӱ)R%ťK$VEqbobߒ}^/QQQZ&.r[~k,Uxa IDAT!00ϣ= RLl{nE*mFVVÆ #4ZRZOOWۢvUs및SH5=jDfIn/$DNM;EMI G{8IkHAc4"""!v ង3 ki߾=d֦TPG2|7:Lu Srirqtڟףxj:Ϧn*ɔ)S,^XA :ᡇ)]g7OzMGh<4|!v3 k1e$c{s~G<==5j]]]EDgwOJKq؝?G^MUV`=h D7s}^9r͓+{8ʉ|j]#8AgbJPkduo)ç~wئܘT3vXxiÈ-S]]͊+h4?ޮ. x >@6oLNN]]2q2@۪HеkW]; tmĚp_.ZnmWKKs<?~<555\Ү.Ƙ 8dLBvwޔ'1Pzx[#uU]mb rqiGm9ŚsQpm"!@vpss!jֵyEC,EOQQׯLJ#GR\>}йsg ŚsbW;z!-Wnd}YEmle ) ?k׮cǚ܋P*jhhRQQ .^Ch[ B~?jj{0.;Y RbĉQT,[eomb-v9wB>mY$ WEOJJ ;w$22E bGdd$C !==;vZ\rI:udYږEBhPXzSxv&  ?˗/`ҤI}D^zX#!{ ];@!pm"!4^M4!ٓSv 1fYvdhRwnYږEB0>CeʡR~8ӧ۷EyJ9셹~zX]= (4@ۺHhl$GTeW󮞸6HQ8(To3RM=.={p|}}h%dz):uTZ-&L'_wаPذxR-O5K ?UUUX'''ƍgW)%Æ #$$[6G-\J$z{lg}rWfԨQ|{yo0ZHuUj*Z-XD:[u"✭hVl]*i[ZB (7q8,QBH~ s]'|zއv? AJ?4prwso>'Kg$%%A ,, m6r%x899!** FGEhں7x@؊aaaY+++opu1CB}Px0迨?tܥ3 ~L?cbbdwV\6ڻ=耀$%%dB%%%3?~ӧOԩSZhO&!8^ AHKK%33gΜA~0dY]Xj!u>Zcy%\jZ*<>}>jjjDt`4j(Z|9]zhɒ%fڰaCHBj<=<))IFQr'zjU8]k.@ׯ[E|}}ITVrԖ`@Bxx,7nS8EQNN,.eҤI222dwV\}6)J4hzY]RUUEhȑV mA]b njb B`` &M$"1gܽ{ϟE(L.RY >K lB۱B͈)!DXJ\8dz&7[>@Y`4zҥ+.ByDFFEL.|GG@K=ZZ (:#Z.\R̜9Æ E,Xq ,@ccy\.B`r$u! 3 5g44p,k1Lwj.bJ.DWBVcr+1Ch9BCFFee%nn$ŰZ_O>X`.bŠ3g΄z]J.eeeĘ1c$38d:$4PT x ͰZQ__^z nnn +.Bz(JDEEwb/Zy8q6lZPyޘ8 [Eȩ +.B{Fs|g74JKK͟ &lY qox7>a5ܾ}~-|||"ذ"ǘ1cOɑL;a@K mt^ѣGR_RV`E,ygΜAuu.=~-ZܽrvG s ?III@XX  T"G޽pBt:k@K&x/@_pAtk.9vh"[V)aELRi>|.`*< ChCB2*+pR{m/,, ~+VEjXqôn~&.];! !a@_Ypwƌ ; ~:NhɆBHŋ˰61}nF! 8d3$McYYYhjjZ,?F"HiX(w466"++ td@jj=\nT*:YYY9Y'551m4IwKf!2T< &Nk׮!==]VBss3O+W2Y Uz^EAd]Wa)ٷoi;s V\Xv-ֻh],a1c.,Z* ҺTgZ(d!(|8sN> ///7ENXqc…Fbbyc\,a1c.,ZPs{E=<< t:QO>`+D9؝"G޽rJ s!t:dffO>$38d#$$#2 'gx ,T*38d#$˩-.vrws ~+ܺu s̑e!T[Xqý{p)Y]Ҷ{Cnq-FHh^g荶?޼+-[A۰A]9<: l$Ydwa,bu֌nVEPP /c޼y+.rx`ԨQx"duEPP.ChCQwj<61^[ZZ BΝ;'.k.֭['.,?P(Weus΁a^E@ V&W:zE[LGDD̙3r|gpss{ WWW9r>ϋ.ChCB[w?)xꊯZi߹܌իWKng.\nnnFSS9å?ѷo_Bcr8 Y Pu%j%3Op 8z~b0k. $nW‚͛;v@ccd5}M.BDWRRR(66z=:t=JDDVsCBB㔘H_|]~(''Ǫc_5"m~mgݻG*GMMMvϚc[l!4i$Ѯt͚5͛%F!OOOrrr{1mRbb"{I,D.,,$///Xy&544В%Kh͚5aÆvϏ_TRŹe?nUѠA~=k.r +yyy BMMM_رc^~e.DD111r+m+B|FnwFZ}sǒ͞=E0=/^آ\pA.:>>^k%''[|vZhzJE*/---G͛DYYӇj5vOR(E=J---]G(X+L!Bª*@Y֯l KJŠ+./7oFcc#|M 6t*4MaBb_bT* XkGTJ_ŤP(hSHHP7UWW ~~O &BA_ד)v!?;hw&!iPVm]l?BCCq# "_Dm۶Dž4#t ;wa͚50 ^(//Ghh(ڥ 2YIXWOu}M,(Әӭ[ __~=vV,.ax|rL2慔@a֭~*NG@;|k,GzfA#""%%%7 Xjֵ7lҌ,V<.J_T*i&ܻwO'$$ǔ)Srt! !9 / 8}]( رuuuv]_:y\tKPP֮][Dd׹c( 6pР3Ѕ>(o:F᤺ ::жm:O||<ѣG35TWWٳǮs l2줃`OHXY c35Ka w+@Gwww|PՈCzzzΛ?pvvƶmzyCh{Bjtoغu+Z-^z%tׯcܹhllΝ;OE*KGX,L0`+n2k/~ hZlݺÆ G#\JE*N8!+0 Ahd0z]II Z~=tp]V^M( nܸakzuq8dZ[(9a iU,k@@qqqN`̤@111g[\Ćt]t:-\P]KS\\#Gئ!LhZ]g<FTT2220n8̟?ƍd|+WB>дEL @.J{i&lܸ>VXQ__'ȑ# 呆ˍfOȦTR ᆨtfڼy.?RIgϦI\Āt"\nܸA˖-#RoURoM͒ kw "`l=`8tMWPQcrdH@ //W\AYY1g']>#HOOGmm-jjjp }1?&EhZ\nnnׯ?h[j`0~QoKqq1^|EL>?ϰn:Q=ʰeҥKrIg.R ?ǏGKK n\Cv oookjjBzz:># +DgݻsssCKK /GW.RKqq1jjjp^^^&H&HKK3];袢"YݱK"** yyym\QQaۼ.Xd ˣI.\شiΟ?Y\nS0l0{\viKYYf͚СCQVV___ma?.^ш^xaaapqqǒmrao`@ ))T8qÝ`q]@IIHbybРAvbR\\g|g]燒AŋnSNָP*pww^ݥ3?ۤ;nݻwCVRa]"$y&&MW^y 8y$oߎݻwUUU; ;##G`ʔ)ݵO<7xׯ qK9eÆ GMM 8BIEW_\]]1|p!44z N'Y%>|O1=␜0̎pAs8p8 40 /(@s8p8 40 /(@s8p8 40 /(+N^0IENDB`mpmath-1.1.0/doc/source/plots/hermite.py000066400000000000000000000003611340375245600202250ustar00rootroot00000000000000# Hermite polynomials H_n(x) on the real line for n=0,1,2,3,4 f0 = lambda x: hermite(0,x) f1 = lambda x: hermite(1,x) f2 = lambda x: hermite(2,x) f3 = lambda x: hermite(3,x) f4 = lambda x: hermite(4,x) plot([f0,f1,f2,f3,f4],[-2,2],[-25,25]) mpmath-1.1.0/doc/source/plots/hi.png000066400000000000000000000247741340375245600173420ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx{tU坆 K@IDCQ*^zeTjm+`Kki;رNK-րBeFQ**4c@AH@Anp%ə?@߳YdY'/_w{'EaaT\8Z0 hJraFX@a h0bmR, 0BaFH6 )Іa!0 #X@a h0bmR, 0BaFH6 )Іa!0 #X@a h0bmR, 0BaFHI _y.\HMM L::~RSSeAjaB#믿9sPTTի3tPf̘A^^IaD(8;vl0d˃R3 @8x vɓfʸ+<\F >lsΉN4)Dg͚}uuu &D|ĉOye]m|>}z B;uWFC_E>Xg?kJA7q5{ߜ9sZ|^FFFNԍޠ !q߻]uw鴇PAh4B Z]z7}>wLS n㎠څ7身zCH1555A+H$BP]wUo{;FaC2>Bپ}{ BtU!$6 a3-.TA]Botڃd@Qڅ7身zCHtؽ 5mC2Vh7#G Z]z7΍8|7@4$7身zCt!-< m%TA]B р?ޠ !p{ph@[IUouW:8$7身zCmVGtU!6+ F#]M hOXIUouWקr|QM9$JBz7Q@nN{ h+ X@GeSQ}y>$JBz7=Zs m%TA]B{7Ŏ \A2$7身zCGcqOEd#hXIUouW;IAm%TA]vos}@G$7身zC6+ {9?ޠ 73)XIUouW돎 ]ᬳm%TA]Qӟ={FRRp:A2$7身zC8J]uu VGtU!%aqw:ՂDJBz7$֍zޱ?ޠ ?Φҿ?;ijMqxJBz7,Rр?ޠ wU VGtU!@F_EhS?ޠ 4NJO}*x VGtU!@X@egNwش`Td@[IUouWc}0?55 VGtU!pT@4$7身zC% + |IX?Q]wUo$LK,JBz7^[Vfg-2ĿF< h+ ޽PWSV6Y@Q]wUoȽ"[׈'m%TA]rtMV6vA_#HQ]wUo}Nd}+ɀ?ޠ ǎ+3Q]wUo=v|mun:Aǁ .&8׿/~&YIUouWc##.mrrrxOHJJ"33*TZIUouWciA'f͛ǬY$7身zC@;v@Zvld2339~xöj-ZIJeXt) ^_0n9rdh\ڲ0u[FFFh\ڲ~_](ۗےҥ^Zuֱl2MFee%a")F%D2e +Vo/&77ݻ3|jkkcԩ 7nJCD"222h3ޠ A^$8<(-mˌ?sۮݤ-̙3ꫯnvzI8 {lC; 0VGtU!XA7m%TA]pΤγ$7身zC)-l8?ޠ FPUouWcaMqQ]wUo}HJb펳Ȁ}} h+ ٽvSF^$%{D"VGtUPSÑ:aF h+ =ǁk Q]wUo^t ։F2$7身zgX@o=8=['ɀ?ޠ cSTtXIUouWtvug,HQ]wUo wdPHLXIUouW) T!Q]wUoBEGE5jDJBz7xt߷ٟр?ޠ Ht}A4$7身zG-[xX>`#P`%TA]CnKHQ]wUoۃc+y  ɀ?ޠ c#1|x.$JBz7xrĿ]HQ]wUoe I)k#0a%TA]<9;w#9T/;-m%TA];޽6@2$7身zCbk7K ) qum%TA]~ {wFGHjD~_$7身zC{pϗ\ ɓ'3c (,,ロM6$7身zCc{"DOS222~=z4pjqPQQ>ƍ_ڰ￟Tjkk={v穗?TA]~hm)=C =/:2gmy O?}ʈC2c N"?ޠ s?A_;?2ؿ?<xmznEE999 2&[IUouWĹ~.g_ٴ\s 7o?kmssss;MYY'weѢE,[KPZZ0R_Pq[IIIh\ڲmqi붥Kƥ-?%ߗٵEuXlӦM0F#“&M'd&##q'3gΜ_JBz7$ե Wp# 4i< >^)SvڸQ]wUoHbWFd?CF2{l>Ù:u*guV\^JBz7$Wf^WZœO>0}`+ @tU!1@N~F$dh"̙wܑ ɋldOR_3 ={2eʔD4`%az7*r^ܹOsɣYIUouWx~=/ɀ?ޠ w}t СJBz7:gt豒?ޠ u_\]ϱ$;/nd@z7}sd}Cj?ɀ?ޠ uHOQ]wUog]g-Q]wUo{I |xl=Z+ ?U"\@sqyM%$JBz7}|r$3.d@[IUouWqH:"m%TA]b iDO$d@[IUouW/_gåv h+ qxEѤ$8i!VGtU`0I+NfZHQ]wUo{+&m%TA]:pk_#M$JBz7t}vظKd@[IUouW/_]9ބ}shd@[IUouW?<Ժnz#s“ h+ ~H^}Kg h+ ~W_u5+6lQ]wUohsD^RRKꥆd@[IUouW= дmdT~#F@ A2$7身zCܟ.\6\uU h+ >gqewhd@[IUouW1͊2e7|5B2$7身zC.tGIڽFDAd$JBz7ݽ~zo&m%TA];v- 9sc$JBz7g(IAd$JBz7޽w۸Zk VGtUWCE\wde'#VGtU} X`am%TA]Zk[ݳ'=0`Oɀ?ޠ s>ǫA]z''#VGtUï~C/'d@[IUouW3?4_^LZOHQ]wUo8{M <+V}t#(d@[IUouWӻwuYclz4HQ]wUoh=~a1w t&"HQ]wUohٽwcĈzW_aOSC2$7身zC|'7Mo <0azE>}x(++c̘1\} 6ɓ'7yQ]wUoharɁ;Mo,]V:^x1v3gd VIIIdffRUUŀNyQ]wUo8=)S(v,a^3]$Ѐ ''S^^p{͚5̛7YfR ZIUouWSݗ,?=ks}Ih@m6m$''Ǜl?t-bٲe,]҆¸04.mVnkK[ 4(4.GJ6 >֭|9%{-n:-[ƴiӨ$L$E <0qDzM=((( 77ݻ3|jkkcԩMw뭷saJJJ$UA]]ƌq{nʔ)oXƏ}4K>D0g8v"uso VenvVGtU~uÆ\ޅE*Èd@[IUouWq#̘/_][9xFJBz7@~~!F#c(* 7.PG$Gж?ޠ %[dSOAu5L`>ɀQ]wU7ހtvuNIӨ m%TA]ѻ-D0m7s\r_!C2B2$7+zO pU۹Fwi⦈d@[IUouW~ewoX_;زsTC2$7+yFݮuv5rFm= $7身xWVر$?N W7t Sn!(MI$GVGtkk_vc@'ܣQs]{gB2$7+x?[ߞإ^y=DE h+ a3Oýz9Μb ɀ?ޠfsݙQ,qGkLII <l HQ]z? sXnjΆW%T{VC2$7躇{wX\d{ʔSF h+ a~Y;9.ۗ,ِ h+ as9~[|< Ѵ!VGt}~ە93/w+[G`J.o^$7]VV6  =w'<+ae(%H$7]\ \/9C8WT8ܹD h+ Ax??;dƞ=C n1J]wc=O c~aCrJBzo ֭tկܙȏ#G6N3#h+ sggh8[o2\@ÆJBzk{] gd#+W=5`<$PÆJBz{"{o\ V_V?3g} ɀ?ޠ݈ӟvK>frGmrӱir >=qb3 )+ ޵enܚpSahطlayؐA[IUou-4T]ަp~5rع[\ Q]zֺ%3fn[׮r<E-G+U?!%aF-@tG_P^ 覈'Ntk3g~>|qw7GrJBz{kwп6ͅgΣG3u~7ݪpnqf$GVGt[CZVZ+ǝ97޵  ro7awmH$77޼-"*7mu"}}E?Yùҭ;օ'Grm%TA=><;EAo+t +W@./O}MhӮRÊd@[IUo{] ?]@ ) .ȭ vwLjyZ: ӧCBaU hPq~N^[Fo.6zRR{N IDATs\y%M\߻-Ϫ3WF2$7w MȑA᳟ukAܩi[Vߺ]Ps-/aB2KB9UoHnvVw;;v>}`( .n}[l믻m&@K h+ sF|֭nyt}_**ܴɤ]x!q"lq?hԅ¹~jsݮ&%ߗ0!VGZv?rvv{_B>N')-s|w> ]y]+^|хn n׏U&$JB(xG/MSWWxJycƸ|~Æd@[I3yG.#~>tDִ$7-(85p)KG6ln %oȬ,oy"h\fwzO~Æd@[Ixf꠺%9u[/#Oz-Ӷ^ ']gf>}\ -~CnTyl7l4Q^?R(,Lr[pdI];}WUEHNh;ruzXnU[cHGVn:]={\x1v/~x"xf"iid\rɉ0gܔEUN$ɀ~̚ձls;v!-ͅd>?p;_ ܚ%UMݺKUU˯& N\.ۓ)><~0>HuLŅPZ%n|i.MSIKs6?wMrWU5iwډ޽~qnn#bOJxh@G"&L@^ӧ=uuuR[[ٳ FɷD!r)[:z~ߎ>6a7ݟ'c]]ߢӐ ={G7ݣǩ7Ko:)q;T-QQQu])//gРATTT!C(?Zނ}λo<8@;9 . R?]#DFG-; kG~[D˶m۸+ضm[C(fʸ++pBjjj(((`ԩA+b'/W\AR/gΜC}Q]]r 7oj>#ΝK.]HNNWh#+W?g}6EEE̜9}{tZ~s3gXzu: r?[o|ɶ~|+_i1 4o7n}lٲ^x! ӜUW]Ezz:ӧOg,X#yu]O0o޼LKߗuqA.ZG[KQQcǎ ZPt^^i \2R<#6l xYbEEEL<9 Öi};;ʻy/Yo}R^z%Fa˴_j/f̙X0>'x]wRj?1 ,/6 %cϞ=OiD"{ 8r~O:hVw^z)9h[n%4͛?L~~~V-ӸW}l 7@JJ /V0 㓄TIhI0 #X@_~G}2Άb06:%eWUzꩆ} C hӲc233D"AF6:%gfԨQ̝;)Sz4h/aFHaFH6 )Іa!0 #X@a h0bmR, 0BaFH6 )Іa!0 #?7xQ*gIENDB`mpmath-1.1.0/doc/source/plots/hi.py000066400000000000000000000001471340375245600171720ustar00rootroot00000000000000# Scorer function Hi(x) and Hi'(x) on the real line plot([scorerhi, diffun(scorerhi)], [-10,2], [0,2]) mpmath-1.1.0/doc/source/plots/hi_c.png000066400000000000000000001343761340375245600176440ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx˯JVY+=wվ++|?wfmf=awOO{{G޾}>f=YAO?y~g~9dzgϾۇ4lg6z__җ?|KEU(P([G$ـn$/YѱaC{q${w,r/+K;BpNՉaG~}չ;t)N,]_sW K f+U3Ys! KRZ JrP +~*@$ۛFAĢ(ņe`P H+ā80w7oA>&_l3'_"[__//|3sg~*|%q>Fyɲ:|+~}-OхW*`Y˧o_}7\LYLo\q5h%L&I5Р@1K`\k8>GY? ߿k?R,wek ٲܰ7, %S-,= `,W x^"KeV돱d/)8RRIAMA# TVX.Ʋ%VJ `6` ټ̀OOTW~?u:LƶK,Ã"/'_47&dX:g';Js%9]>قhW b@-\-vúDKeT`1VޠcoA"7wHA~ 53U> ;U(GJiebjTjJD T ZOOmvu'pN-H=$fp~"CF`= +k7Wq`@e1w?74F,Xj,5|Y o|i{yU $;[~[ze8 JD41 4Zh3` 0$Apl椌YKp9:8^>ӲM_~#~H;fWAxam"#DRj ҀiДHk1򭂝-MA]TtX*Jה1o# bn<i:BvO!RҰ0,Jejp{@Wnhi吀4EQ8 h3hg|'{Hc-lNNW;dD&<ر)>;iP2RWᯅG% hRI+#G b,O) ?.G XIJ|ʮ%b߀}`olf 7m6P2pT ŬV Ce";5S?QMn bf@?F8?H589Lr nJMM@!@D||gճqAn ;w$VG#N |G XAQ K VzeǭeZvb[#YY+ C:h[filAa R+eQ*5J-Q+hp49Owytq.̀~ # KYE^P<,Sw$zA_$GoodskL=$D-qZ"%bW\! deu\Z6Z귖Ѳu[ [+Y悗^Q bn!#684jE*>R)TZܻ;d-zP f@?>)\c1}0E|p"l )up7vI⹉VnF@DzQ0%)^"K*"B:~hCag8p>|ZacKs3sAif@قف9xaJHaPt!RiЊXhp8 ̀~ gU5gTsoDi\[d$t?tU<{f)]J3ۑl^^X[n85۬UX"u\gyfṅpXCg[wVxa.2k s1Һ6Gvi+84@ BPkPx`/S*PQZUZtD7<"O9siʢMƘ98)p kBVցqH PynEKye0 6o[;+YsaVXs5݃%m*D*p5Rհq :ZBRP@W=En3bc*>8g0>Y//;8!ezac.0J4މ=RYS\q:zcѨ54ҔB۶@#BP87 {RiKk[b2cHyFho*(fZf5G04~@jp *Ҩ4e N3Cb sǹ~%S-1Bn{OuOʙճM럭p|SnϪ;+ GԵgH #~)k}ҍxzT+cg쵡1 l AlOyn%o Vh6pi 飑NU rKV 31FL Z4дP;&F+T},Nv]l6l ]ȾbTn# ӵP*J {ċ(NG;ckj3{ǼFwX6g ̍ !wB ԨOC\,1h堰6J1MiIjZɄԂz6)Bd 48?,)+ Ŝ$ofry}gc?|j,J#7\sݺ.A!B ,Χ܎J: ܲG*QvFv|]^b0Cz-;0{9HTAg!,UXa!BKLlصl|㓮p~:XK׽y#\f@?2HK2? nR~hFʲrI%cUzS.{mb;SUsSS98S%!5UUǢ+.!ݷ,q7skjfG}-u[.ga7;   BcRX !,TXňC44WIBKsЄ-騬M2?0i){zIqv_ЩiO\yZ֙8u>))T9|ZG qкNO:M]ϋ!'*gE*B`р- [v+(/} V ~k 7rǎJ }#ԺŔϰ\bN!oyl}}v*(V *Ԩ# 7<==O#8qypQE͈M_'ufz rr}5ϟ<9}=pSHcjZ9uX܀`#4į %tzJ(8&#܈˭niٲ(===mQS\`&i$ٟF{X7"}B`fQE)ƞ̀~ G;1Hui ٺ1}GKM}r_']>bjAZ|OaMՁiuEhZhP} λ8,@ւ\^:f J-܇m ܨV)7np'ʆl*KxFQ%Z\,уW]4]t yn[[ay=~99. ؈*~#3'H^sw ZO1OAnl#ϔnf SnByl!v*F[J@[ǡqpgcu`Wt z mƻDʽPTp ^vV o1bp'-–ȃZAdÀƮ1v%^Ǡ+~k}8υmSZ}J@ڈ~%{k3`S>Q]e?6*4/7qv?Q)G<3NɩH)P~4SGnXDqbp#NZ쿽e ڶ5GKA\GHn@t zHHv;iu5렪jV>,ZJc @ w.NÝ[.ي'4h7ȬSH9G}duzPJ;/iބΪ 7,lZazvG!e}L/1}A*S<[HKb-II+ |^ZR1u{١sans&ihFЍ"Ұxfm!m؋= 4c2=,QDm, 1Q8ǔ<|!ڤ'l;P{X;ܬ̀0}4G']0N1hl'OP#yj~hDA vWUrrOi9u,9wyt\W@[ ZXKѾDkpUKY>F&L `[c[[E|(rkЗP^׆ *:@:-Qsƻ>P0^eDuG.Jti% y`>e6#ɿu=a׾5>Oŋaa'M{8< ,{sϲt~x%:ps\mCKp %%3pxS*T/X+ b1Ru K l0b[-f{ׁZ|w~޾gŵr2ăz+^"# N% *Ch,P 3HH!]˞ݬ*C5=|ɟK_K???}퐻92d Tn.w Ilbj've$od;2W?FKӔ 8 .|s+D.\k߶eCZ+/ F7n0[[tA6ؙl ;vO׆ŕje؊Hhe/Q~Wiiц!_ =%]XGtx3X]=̀d+޼yr|+/Tq)n5rh竌ѺwL]&˙~*:Ͻ} ;GAL].%V]/ya|XPPb)9 o1-i^:V=P\.WJl*1adF@# ZT"XXNN颢u}_onNf@O//뚟`iH3FpJ'TdJXwL^fsQmfb#/.,# ݍ/N ߺj>,\)0oZ W8 xP*f ބomA ۠wŅPjb68 RRAqd4y`Q}q >>ˏ"{}Z?//)uU$8A~Gv+#c ͏c3**:e`݉C9 tQ ?i<mw,k)43Jp'Jicِ[T߻6*:F ]m#%pc|(*`@c-h(Ʒvbib1T|\S MH^E]lVҕ b,WJ19*QRgtQ6AnL(SPEDir?m{n3bρ{l]Жt1)hy91cHVX*Bim( f{VCX<}' _a>@:YtPNNO S}s(.#y'ЖrWNv^<3 gcpv^n8<|9niԄ:@02ؽfCkQ1+ b`-b ߶Gۥbة1+ssfa{m2VGp'2H_pdTR1 ea CoCO=_[ٱy,%=g G0>6I9F )i^cv(9s_(A)'?Sq ݀ 3 |C+]VIp~H*߲cg dii w ^她ʬ).(0݅нߧc7w񴢪·MY(TBh:4FP. V[Gf@?\2=Cg$5}(wN(*)l:%>4gu|#a%`pZz,}pj7`Vr\Zdaaaa!֖Go-UÈBcc1<7W\\٢}r QW] "3gI] %ZR` Yu֭$@ȎsȕQAܕ}?mS,ua~?[cՑ=$y'˩ JUrQ80![+uh"O64r5bJ,{v /"+ . \Xo[޼1z4 IDAT53C}ό\6k s@tO1(3T+hk5UA-ԕYBBFpAa'MiЧ6)0Ľzi~nc*{Jy1f]1o ̱ezIByJ |Sw쒆Wp:hM{`)%-,[²DVr!-W \xf8oo*AFXV˥u#j@E?B4 plߙs7dT)RPׂXE&?'g<8H2OIك|])Uvv,<IƉ_{;N@'yݿ6;yLESuvq$6"M^4&c` Xl-rg6ȵE(F[aw%G0BskKc4kVj1*:*Hu/`ڒF+vCqrIFny0̏5Dyr9#9AtL.>౓n{ϧqsߴ jDJh#uhP(&Zy AR䲄gZE+MnˆF9VaSPB=-P)&(iA[jBv܈v?dJ8 @t(~HM!K182+f@?\?ad$\Tn&=Y4kN0xpvF0OaΏ8U)?_{'Ǖl츀n8 * J:01q ]0.\ZxV s,/--lhTzu[{{hUXiZX1Z|/"]!q?8 m7CˈcOqd+ycNO؏t\#H4\78JnRR ilMP ELOmY}^Uy&=t+{aRR m1ڠ5C;wvPڇ}'OONCTz΁5|C6c1㔺΁SC|r sKIs|ӟ3ع sPg; KZ WQHh'fӖnLCkj05bajP=b sU$T°Wڃ=!š#(^a( ~h燥/jiſDu]|U/g6o3k>),;sXXHZN:c?9W'KQh;WeHʲD^j0W7%BZUii`c촡6TTDw tyX`wq]o6)1H(8TSVB=Qa%M@B-Z q#ckt;2p yys'lymS)^"Ɣul&?sY c}~>g IN7s}ϟOd&v`atdIB:Z4醣76ş#,{*9z\k# ffU9xkh}kZ%5UmFBB)GCkrקpBb{x%Q#c3f@?>%͋~Ycrs\)eX΀ .J.dtqXQ:pAY[JǡFap>)_N8̖VTF#z%a]\c+b^U>t>`Q$\Ei]! )Z:'Cyw7 fK.DÌ=gmc-є#9EO%0Ur$\Vgyk._1Pw*zD5kDLIKk7uB,d 1С_.SwwlՏzPܱƏ`b0r c@Cc-^bKbY{PMTGJ|s㧴B!jx"2!eP_,GAH/;A{J=OϹH޽pS0S8|w@E@9^wSʰYKͦø_`C# P 6>Kt]py:ˣ4u7mQHx0o J>l ovj3`~ᑌnHLs\N9{NԴvdY$O @˜{#¹O:ZΈqE (jB]ptiƈ-V`/6 kGA;6;9 n Tݐ~k@ S,e6=ws7: Π:V.o4Dtzx%=Y|f@?2e9C'Oʓzx ,F9xs%g8W;r!a\s^.Nppuا)U,@ +ߘ\ E+jz56ܡlPN=5GyPK~ט֨PB-KhmnkZJOk:?U%v(cɮ;=}0h-.|H7Џ 1/(,c |t9[c/3at*:똋dYgN!eyrats##~l[p-ֱj͍ w7{e*YK k(j+B.;QDWwdx,h8jTzP:X%jhQmm$:o4F 8 0gK/ŷ쮭Bl"}7U%@ztgk~gj_0ǬSr^es|`| h8O=@Ψ%T3#2 ǔs ecFp1I}q^)[4hn r(%h)^=@.@/Cᶂ Fx~+;c;G ƀ W#*+A>ݝScpQ8g1p7yjAKp>.jZ|:nH[jqypς6tTx8[AJ{c ]{wn)3;(v {R.Vʳ«M&C~mGEMGaf#1i*ѯDY,-JX3HWCc Ʒ6=e.-HowoHr-g86zׯ_|f?WS yQe<RcpN7ր'uq$+&p"1(ѳezԢ"99 ?ةW5ԵK#Դۺew785E}s;"Q;WQA_ށ^dȝA̵^+u]*^hQ*JHM[`iJDB"" swdj: Nvtn8kDCxf@O__n?s___ӟ4oU z^z&0GꟵTiJz*/onJ{[Ns0ȏO|VQOdfhQ !~ 3818#n;ƲoK}ɏ+ Uh[6{9#zJR<4"w>\+J).J.C#~2QZ*¯5D!@~D()1mcnj̭U$reG+CqiZKzcKiT֢amGCWBE*S҅44>!jS'-]z_=@z 3?Y~G?Fi3}s|s;Hf&Tdgd AY~b}KA=8)0Ozw'?aмZ ̱[@5W `7K?mJIJ`}ʾӼFA ݢ-Cyg0 lh_)r\(pQz(hIqP>yPKh8<}et^Mc@ #X{IoH^mqyan3kbp>`>a4=1d:S%''%dX4O&ax%[xL_aY'try"G+jM#2 IiɈ% 8 ,C6ǵ^A{3WʲCH=c/t FB@0>1:56zkʠk,Ri WҩJ}_`n :g^ ՙ5O1(܈'e2'1(j93Ѻ bj.l?t+H%N.=_+[GeA ֐G\MpulݬAdt=Ne/VJTJ}~^ "Xvaߖ 74/^:XC:UwT{zNL.˟ogR%-zT-P6|qBAw0NTr禠W;ZG;'Cs. Cn!_q%O-`iZ6]e`)(Q͉aq+Lr1.\!= wj!k`'kEv +A,EHOwyht\x/K k-*I4_- sal̀~9ɦsb\~^Ƙ%%;Q!\"oh -B3FyD(דTtDW'퓏mU@34KQh'wа5B/tHJLΜvGh0>tC!Q~W?]W B0,hF%- %B 4|wz%-͑J%WG])ɓ:Lf@?Şh}=ɵwUaN$=9MP9]:ok:j}@ ^hˠXHۇZ C5W%&] _E}O;sFTȱ 9 rP8*{( B00xG8GXU={IT`'i~0ln2OT WvMg-нu; yLE9=Xx X;$n1oOP"m{J@k9:˛;i n+1X*g\kTWwGRE*hk6>$L0B ^MYW W VB0 Ym8K.4=o.dשgI@1H;~;3;XK}c9m>@M?J='#xl$*p>4JVwF0G3YYfχ 0yp`]•En zQ,o,m%BWGp\Kl}RiDEk5qpnj u ?vU4cXaOѴp8I[xx"!Az03 f@? %IgGYNaXZjky{c+۩.#A 4KdkT'*h@ kU{5[<]\ x8WChu_:^B/E׈dl3fSM 8'yµ1o4"j#;p-HR\$ӱ`-iWU ˹FqS0w01-]D8X) mi}kc]GGG r~4(j5+]csuǠ+pla8nH'vW}4=dgO|w ~z?b= [z΀=Y[fRm8rXyCuqݑ9ߥ<-1~SF\չ~&ЏW'VGCC9MAz{ T9( J "KRc+#^Itڪ2zZtөg](IdP}Axuti#FEt"8_h6srmSmJ='y FuMӥW]>Js8K衽ˋJ7`O|L#Mjy+`$=R.{8@Ki`aߥR(wwxC .0·#|_tXVj)aF=u>GK7D9Gl{2T׃`S 6짩C?L5ICY֊^nlAvp؁1U*!9q{pJ$rb)R-F}Gf%-PIl,ON7ؠ$]oE}0جs%ne|O{y#rT簞CKR6u|(d{>QcgTiEu pnA䷤Xt_4zw=h Z) eIs'Zt rմRּOB) IDATR,t`_2蕮#pyqk>jK7f@?GN g'tڤ;}L}σ'N~H9Pع=mMA:%PFOR`k灒N;h'6*jA81~'dlX0YN=Vd-`bH pQpoWejz#@ZN›)ĄF*-*Z \vy/''b~@{JurZmc-{ސ=͔#<0.nwqq:O";q$o+3tcºI@"_$NUkЖJ"&98>C|@.]Yau aD**,.w p (PbEBwuT#ip/WQPŇ|c!sTu6)v.N(XM2?J )GKTkN>&PsM~x˃1HK)r l<~<{Uxww:ԺUPETe+}JdrYY?PF:WQEo愶c#>:NGHn^B_H!AO!nkHN]|Xn 1̦:GbRE6M48p<}U=!QrSL]4;\9>s [ \=GBc~]WӨcG.WC @>0CAhBwsz 66F8۝ Djzi])]u>- Vq+#ҵԠejS#ē.ˏRπ Z|}aLzxT&GGTIQ2ET r YFMFV:F9MGO}n`=V7ZڥԇĩmL$q2\w;4cC;n tH* }N*C8KD=P+8u>q>-6VQM)T@-K@ =tE?M46l9hb$1t|-ȹd\>[ e0}L6? /z O{#IAF%PagΠ6B1|9p߯@*i Ud-wރ{2z^IWp&9#gCV #*(*{X )K >A!}%w뤃u 4N9i̮R@>i0.$T2=ެ'vNqPs?s}Ft}8?ScPyewp~7e8,MrٱFfk6e`6[VѦE:@sD8x8GeF %jK-ZcPnPP6'I8G.vgHΤ־O0Wc$%cx`'5JO 3̀>cbC.,gEfUuކ#s#@ba ĖA ! $.b,%.sXd$0Α-l$S ؛#d,19{^ZUȸddUtW32R2z/"SYTJ}P2g n)7njm$ &-wLxA*|  #x"{/@eI X:ӡ`MjX{c:X"P0igdMܔY7ÁN@32M%ِ7M%4 0ɿm"}oo[2ᅶ8@.!ׇA![(@i,e4sɫIk`I$u#Bx#9[]91.4ܲ2ס+Ϋ砠orH00G #GH{aN@2);\4K cTg%iǁK{ehi@: }jtvo|70+I>6]Ex[l)k~j`ƿھ5zft4 @7U}-o}$ZW$ /TqXwy$0kTXWfíX::t=7Wa-,0rpS"3eiLMB+Ũ!z_51!+/n'n$>J#sG>Fi!t}梱znZ&+OTEBz`͑*hͶ9f0([dg.!@:L'L9>2eEdž838c70y8%S 2AaLD[:Wޛ!=$/\ܵċl%9 `[@:}|?H_t=hB=QpM~[`":Fu o2~4a) L|Q\<*Y %8G!$F O$D;H8 %v {ȸ"kV(6t`=5 gY"T!US_xHKr@-gv}KPg_pQv 0v6< bFuTA@ZreyH.}T(;xȻ[EsMIW` s{Pϒ:~Ia-$qŇ(Ħg*>&=(nmaaM}>'I]*@n2v)>DOX9Yϖ%xNx1K[ӷ*ΈжN%oHƣ8jia UWFX!IPP5-4GX怖i_&4DHCMj?8> %kK(Cr4 n+R?& IW3XD,b= )dTEpH}z#$N6{NQ6^QЎj:[20E"E0lpֺlQXd|+CKB:&u(_N@qד'}ryC:ΩW}aܾyʊ{;>}`Mr{m߲ɾWD(s\/ƃT& irc+n:hg`8pP96̒C9UYR@,,d ? rKh;-RQJ:ڗ%렬"%Ľo:>)}-}C68;_v- )ؖY!dr J)̻d}b:3AuU}t0Wk0;}iFa-1-~E*@ZZ\(i3Lh+dBr7n["Mάa:K!T1{M^ߘMNewIH΁]zLRԥ,=+{*[Gp_oiZ?ku5Uɭ6ɶ9'Y`\o;6~8i^S`ESr+)AcF gFTtjw/t9ݽkKLz7 3m55إ?'_t}| ŶP7g,A8rrRXop C :@!/ÀLp%Om+WLCVIDhZa'LngD{LE6DI0oRlX+]6I5/+?>tI}j {z׃{H@7=ͱ.1(kfkԠ[1 2kJ[R8 }9,BZ6}]@&DHO\L}y 'dZiu`d"h}D2(j*C/:tΈ_:r.Yzpl{K.S&ie#>wMw8JVϵىv߶,wulV'Ca,dW. {&t$Q־[QiN% ؓXG!M!A 48kH -)&s$u5"E}vn9$۾ʥ7zcW} :-WDMxlrleIA:QEdKTzH!i<~'Oʒ8lLIg$#_"IbM&AEǰnfȭݧ<^ܿ+ˇK [8/W)RM߻$}?Aa=>gǕ9#Qk2I}Oˆ ֮N2 RdbnʲAY3+B0?__}1'>H{=ekeݮXR[몑~YSwmdu b2w+yRjJ=&SϹ謗^Rs QUge"0F\USBKHI/-۾??'?ɯگy@~A:l^v/t{mRř!&G$w U\֥MKo˲A$ŲQkݏF#Î}P%BChz?׿NOǾ& ۶J`u|_@'m;qZEcӟR;YSPj9/P%9=m}Jzؾ>XuDah8RoByBķjz4 ooggw]U._yw;g۶m۲{{ʶ 0)jyK*eol֩k:k,z}2:FcKy~~|#w:q} me߇~{ޱ($VT=r]@ZjV>9)}qghKЙY!wv&R:o7BEG|7໿w}ooSG`e|=h}9w\1|Dʓ1r=;vcF1Ȼ/ "% [suٙEK ɟӟ4O ~'~b/8|_~>;@K !{c*z1g_c|ma͚ecbk]N)̖o;nį{>+K})Lk{W]K ooSԽ׾5}k`[ 3R~$ts:󦻤che]EfW<Ћ=ƺAnr:ɾޗ5 yY@v+ $.YJ"ŇD6dhr¶Zõ'n˷ɓ'K/-~w~/~SH>7;...z|$M{E)g:Szcnd=' c>eS UM-ẏOd)dz :jBe@zn+˼Co|}+ɥ{X,?ӑ/~/P۞nKa>֫10l˃lMEuSH:9JO.Le5ZrPc_nccknz/}K!";K ~/wQ.eM% 9@~^%bV”PwPڠ&XK_ ࢬ%pZl (rz-w} ۮ^j@_wa6s@}K^=n o~:9}LF՟ ZBRkPy, j9|SV=xRVIGz^뵨^Rۿ_3@h":>0pNXWMS"7="*99wp `nJ\&?:T/9@]{BިWd>l)*ce>я¢3j͋~\ 1 #ݖ},cUH Pq=/'^1+޳~rY.@!juԠGQ$ NJ47c*x c+)>JCK O}S؏Ӈ^0Tnrޭ6lWc0W)zPND5Bv}&~ăOBFoX0cAՅj_TZVޮԥݵ.׫s?xzyoO/-/ c/ZC?m%B vf(ogD86C fmq8ۤ<2A4JuuI:( :\2.,I}M\rhU88&'&uA]J.]~1`.䱎 ǿHBQ)9̪ ")S0u[&(B /=cL9FerSK:{'> Ix±c Zݶe^?>\!Wc`F3A!9s3SK)T'^-;ܩ:NVa[bN1 ]ْfI&U.!=3᥅lt?Tr=}n8cݾE>cI&e՜ZN) V-,[uA)NQ p:NjT:rXjكڪzu:24.MȖje _Y_G2`$%6!: "$ZΩ̶=~cuxAZd IDAT:Ω|juun}>)3M-Q80f9UT~=@9*瘧35  Ɓy@Z{H;Eds0gU ` jPpK7|6ނ&0Ġ2&ԠǂkRe,mCJw.I=@KW[lx<^΁[5hor}MRW:>퍇ƩV5ġ2ZA H1! `)"b*SV4XWQ,&Y %F!Mnk D ㇎B3u@ifLB4` x Ȼ>n$ʺH0LBX;&)L$ S=mا_ q{8#DnHBʥלy ;sۗ {8bdjyeCGXXpV։ͱNsPϝuC+wrsDiB;s@6SЩSAI&Nm%.:9j#Q=K3g?5;EWлOo/Gکd\ 79ֶA\7r\ ;o떭^I2ÇB1 'DyBT^5[N-Kx%Beu jAZYyV;}zڹ 푇L#9yL%$5?@wVIA=BGQPO_i XudC:^6\>F:vF9Xm-$j/WhoUYS+%:(7Lf. )gĕ{=#G*gƷ.b5q f-(EkkF |ُ=$G?!q=P)?ґ$-oS{n V8U@wUGKc;#q.te 1F5`Ԛ(ݠ98TIh6hZ) yPհD-(epDUgwlp4sfs,W {+h;|4Z#4Zl@@ Yk#9*nK\ֿK̺w5n7,y| wm=GnJyVMslqz~fl$j2@5q鶇eI✅`cu.ez(=oq]p^VaR[ƒDc= Y1 *tP9SeEǖQz՜BYQ'Q5W}y O縍5߀5#C:?__a6q}}g>&Iݠ<}g9V=cbUsgr9P:Dip:BW*hG-qsQ5i5ղŰ²nnEXbnTX˪ |"  /`mGo$N,U *d}vXZT=f*__.a@rpF"8ws=^Jb:??yN|أ`m1:|a+ٲg`:~sas*YrŬ$ ЫްG?QO&piҶ(=}czN#yƶLS+pEp9kuP2>J2$Di- X3np#R,-ؙWǂ{H)W6i,s vj1m6XY9G\W^98'jlUr7ǭ&ʓƯ?wGr?o=6מC;h}+~| _-?ìV-o/xq? tZ.C̈4fm*z0眀o0LgH >H ʷ+go,QjY XйccSz8lOp^t u6ǴN,Vn]f*A˯JoYo76LaJÄu9Zw4|_(Abwަx nJ`u%Vš+vK=ZjKÑrS*SgVl), v~\Tg!%+P.a,žT ݧj*vnkև]JX pSS0iC`s Ƅ6;Dy!Mak+I4g6ξvrÙs |m!Mr^{yςUa&9- Z1N=Џkg;ú0Xk,|{t@0V:'pVr0:; KJ=9ش G s c)pzr\vpƚk:D Xƽz<蠞U7 iXr̄9dyXfj2UTLhPu9Xҏ}JՙXbͧNS9%W<}?Ln8@Эת)QCS/J=TiJ'#*!ōF'%p +5JPn# G6k(C$i %נXrI׈\{*W&sZi9ư@92Gr$q4n ʶdtJT IK=S΃%Yt8˫s*m鱺]P.a>kò)IGSEQ&@CԳ&R$ ]*8 ֩h&1h '_GC'3<x`XhDžr&g^==WKuPpkae`hgk3K=xb mSg?EjTrBU^Msi<3竑WkKw F_ WEK2i]9s+N;l2S"4ljmё9DFx}mZL L,L jP}PCxwiDzBp*<ùvL -ygin-"fujR8o0wj yΐf ӶT'99(e߹00+CaoKRp:^溊uOE:j!vM1ڝCz~e,A5s-9@858XIs/%Y:E- 50!." ..9c,PFݲ\x{条1ȍEn,ᬷN=CVn|fqJ9B#ӵEuN+wPAx)WˆG"<4EydGFyh,\;A-"n:1p㕳5X{(^1A#?]'(gM^{&ò29P̊IhILQFA޹v)FGn:ei puJHTEګ]j7UuΫ)F(%@&B{g ھ;)\`y < <xhుG6\eW z ʢއsg)woń~Zb΃i;u˂}Z Hk]g#{FJGK]({wX6`Vz|қ_x/6#-Ȟη2&RPE]!L#CSC|CW`!)4y{׀G"<8R%K\vA,9νz٩e'@SOբ uU)g;Ak.r] ey5J !}¤Sao%d8!#v|9QTV֘8G `2DCZf s8in#kX jnkDP 'HsX1kΏcj\wpiY;diХWѷs^Y5S=E'9Ӵ1jQ;Gj+D9wڸPi5d ͑8*ݓ0t0mY+PN-to}Tt]5c[3&(-z䵆8%J)^g)ጿnrTFa1zPxas ܸn)ҾGcrky(ft k\ ͕WU\ ܹYn{/LΡ=HkOP{jpنhg}emk#*VY@W/\V;6s!sa[F΅ rHtʱ~\[/upn=[!Cj;fmX\_i_^ip6uBn-nʕ%5gнǼ](QίX>Qp6WJw-Khqm&29A'爜bN;';az#P;ec k+1"ϺJgk}pw2l&}^З9t( ۝pN?;t]T>Sq.>`:jwm]mR+Z6Jj㨠o#04pw,sF@<7BAci ;18TxAF0KnFnqP6W̕^)t-LH59Cbzkc͌m*+MqBgk{MLiLA'It߱Ur,nH?7z:iz:G;n6NǪ.2mhc =[N=[aCk-Z1 PTTg fűY,|LVpnB^-f5C >9@NYY|0zY*o}4B{m&=!ƣ\hl0mTJ JZO%!5}+_ _KoܵTw?_Vƶy5ʸsP.sCܢ0͟ycaա7f+2︘,yB[8VЭ[)ݭsTR,+tpNcϡ@Ĝ;ܜ Q-ؘ)Nib4&=ѫfQکA\M{OHCh#`Y! +R=#~NvH!=/mm|+_l-quM=kJAX)ݶ.Png cN@[uvuzNk(xehs IDATZNsB;}ЁvKB`fA FN0z3:xYWA 5l̂r=VYvҨ6`m6V d0Sep`V&z;#Xo6z([Hs'$@V'`؇>!_*'~=ۿ͟ɟTa)J=yBBwQg3Hac6;#nbi9[C57X\n(δ|Kſqǩlg ṈFyra9j{FgOvN{,m Y2v{p7ҏ'ܔ~FA]`$QNAwcxȚ3Ԟ.`xeN68{a yc0,`r r ? ](v.\3q :bea~֗sGH)/ J\;nXucuρ;o k䮾z|v\ AyF=uQbAܕ(Su}cb!iy?[49oL`眉- Kl_ nm7a$*h=k=c-ltεmp 4z­uSuua9&g ԩf{cI:ڣ3whXX`\3nYC;#, -&h.L*'M7ͬAƣc]w$s2#`&B_HhO$Va9Vhs5^= zz ¸_ 2kDG%ׂsl/`cD\GE=TZ)~eW'>?Wa t[-C ]c]ᦚ8 Ά +ɥ7^=_bp WF6Ruá(ݙ`0:0O:vM#+bu5Vt+oaJì2`2%'" /uqtҘB.ҏEpCaH! czPMK_Cy7+ 2eąLX3At7(~'Z-bYF,KÕZ.R ϬºG ](B0pnN{"yl +KfVkasl~KVI}0Pye|2CTwNc+E|C`\ ~hG IΨp֨7 [9Ŝ,kOAjq)v!a="CB|CY0@eЛ ܪe)K5܈ %0\bn;֋L)H0]8m.q歍Lט#74,XbtE'+z޸FAҁB+LGXffjqVFqPJk p? "g,GZKzHp=Ӹj*Z]O!c,S^WS%VL5Q9(voK~JyEղY7VzZpIn¥p);5>4ǂyt$;b0͒k,7gzNA[ 00aNa|LrLϹD-SXt]U|X S{{WϵmTt]5L_vdr_xxX~A5 n5JLu6Gx[ж/ck&ͣZ:ܸ0mTYWj Ϥc55lP<#6NE_XfrE'0 #p-+bDp" L8E X>Otc-faCkP1W~^,GG6@\0a:^)jZ\~HA5r 8rOe]-/YWyv|zη{#O1.Tv)IOPE7>/e3p >䁠 C_3cA_e3˜t<% tzFNne.3ߑ3JDZŲYu[:`:0&[j-34t *Y*scI$˨5<.`j*r 磌Ӹ~ y.)~5J.hԤ /< kR0^!UBTҩ"{?҉`6J[,nTXOn g\< 6k&#+NޣWȵk%F:1rspSi8 K4l,RLŢE:(D13Ț)0A#GHzL1[)kVǸ5q[%ǎa}1o ivbO}xk<.ɮϞrVa)f*؅ z!9N=?x$ Lg={l F`F/1rI5†c Z .0фq8!g\ڵY[d+Utc46UEԀ1"~ ?chaU>WX.H20MϻۣǕ?kbR!;ork)W۠=Oתտ?uVlú;Q ,S3Ls!#%j<y{NE>bz- iy$@:.0kùtjÉ8yn>Lzca@7qbL 7i tԫ tsj<ĸ$w/w:ީڽm QScJ:}}"7|=GB[-aL5*Z|\k}Զ/r Jyn A1ҧ9@^"'M,sPj>uhSd󞇳`ȻL5u&.#bЎs1ѱ4Ln;MXd[E̮o$̏&.tIq j]U=uC)eJ8뭎|y\Iڱd1Bs-|)dt~o@;]:d.Y4=QTA+fy@lޡ' zcykk#1)N]^ӡa+DKX;le nmJe]֡Zk$^̇uho MT5Һy]஥]P`"]9<."m-k։S 3u):WdplQD6S*cH.yd6^5:I# 8:7A.;CCyϺHӢ129A #aB7GVg-4lT\WN9GLPxaС>zWʡ<'y! \;ݾ"4&ݖW:=g~Odd},7>fHggktNI+h L :QZdj`f# E6˙^36>n:1pt!O;䲃g\CzfqyӺHə#lD8.3iam¦ҩ#@+ei adӸ:17?ﯡ)}TPMWC,o;}˺1 %;K^fs_޳Œ1H? ) KX1H\d H(JY"h<) p1`=سg׵硺^{=۳a7^k5@ IdG,|NLuӽ6Țx_QI ʺfhMD7QzB-Vs) yrppx:̎CvbbspЃoHۀRXj?yĵPD WǙ C/ 1[ 1B/Lm V.!FB6ʆNXzv`7&(s<\hP[Q$J؅,A=ah`Wq/<5G` UEVҖFX+"yxRO},df&b[d0awLZ-챓8JotDI{idU*8|rNes=g$tB1iG{AU\A,W@@8-i#l@ΧAvz=@kiAVe.[@bP7֦ }/qie+QB0l [[FƘ-2VPM)Pt!.^7 Zwv;/CZ'|BOʘewC *E y1i50{d`rD#3o0"TFI+'>$ޟ|+%9?D>jvn!~7N8c$5/)ў`w@л X胚9ֆju[!L`."~sohJ 框D炽]}cRlH]*H-(LOFO1mVe( :/_䕯|%SE;^ɴtٓ~avG^EJ8}|=cdx,O+&S;l)鲳O WߨW}4aq]=Mּ Z8+pFS+}=%#݋} =GkHm l 9/n qK`P73MV:ou MLq/<ʰ*lq+j$FgܙMOO<o3i~;F￟K.q%vr]<|LyHNc"2<&1&rBF"g R97xۅy:]Zr_y%Q, 1+!(]>vjS^8pF^Z ^7.p;a:5ǭ/L$&IgS [o_b&'n#z:çmhۅ\\=O[>E1Yas-kROq|Ndۓ?RGj==Ц=(<'@z0Zuhkwب)NwDW^_ F*[9h -Y$rM:p]B+}' 20qf@ T+~\Lо*jt(G%4Fo39*?ѣ?Bvwvf< 7=A… /x|S5S}ݞVcjwLȸ<bC+8$'0}x8)xKjA#+73Ap=uˁ :`'+q5_C:|жJ]tsJTJ2SxK-7ߔk4b01G&Ӓ/v ]*X8x b0||H̀ 98K㦕4f˙IO?I bsf9L?YaF _wRVWt~«ܾNFSsKszP nHXU\Wp=UVqq>(hqQл%n}Wa {N90SN9V"5!b́ \S|G^"#<~f~>ݣƤ&\K}V^tz;/PR>'uIѰt23ךU53H%CgES41ـ%$p@iwV8U[@W*#y xYıeht :0t ;Nu){V8H+ԖE/ ~^sUsS@j,ၤ&5R5TPRAGs9j1+=7]GBŜ˳7M;E>g5Yz\9(,y{8ǒ­ 5,SEfq>?s#*+x᥁^2#g*5k h3+t]m'ƮqB_!24 Ԗ!Ԋ[>}NΣ<^+)3dy|ĞleE$D#ThacMX]5c::"T7, ŝ)pk[\=cq`N`uںEy*!4q4Аkx`cJ~0 bPcIh6)QqGi{#=l)lNdpfíR*EED^\f> $yF$'"1};!jJ"~8D'.>&=kY C!S`&6D L1{0,]=2TʂVYCK si!z3an#_$<,c?!hI ۥ$cᨖF<-o?)D/,$*\9 ɐ2֌+1K&*[Zt"Hz6'UvQO?_IQS쒧\d= x%\'qROk=O"DOϓ(gg ^lotѫ e`A6"Aꀨu[X6 yUJxEY,<`#aƋ:x0L5ԀZq UO6+x b^vc}8Ҹ> 'yENxYk&L͖ϼgc1juL{cŜ}m$Ggʈ?Be/W8 d kKYV*^aʐyVY8VԱ,%u,cK;KeCԾG8t|gVl@%gNUⅸ 1@%AQUG'Yyyd1Ozևx:oB%1%ϲTH(-&k:GU_U=y 0&}\<@Я8|S`R+k9%A9 A.PM"FCzkZak"*QǓL70!䃵 ~uDJE &^3+ :1$/{LQaRi"֘8C, gI/>0%1}|~wid?oi;c?Ց"M:r3FVm ;XY]s;VkuPnPsU\-`9qa9uN cYS*+bYƱ\<CyPgTHVZH%ؤ5Tcb3afbNtb瀞%A $/:/73$<5Ouh'9(&,ZTp:D=YLz;0z z$(QţM`dX]Y]Yt!>H&M0y8K3ZcClLkbYűqHM&:o[øJչ8>iTA5:jjxo"DbF=q+yݢ6Ųp"<<'K/VټPόX)e/Ly("yN׆k;>{tŗ$,[xN@ 2̃.Jz>B*=o#--l|e9eR,b9E)aKR=p^r!ZY@ жD} yCdHb}3',FTF( 1*6NWn:?_.RD%cͤI#7Uт#M#8Ĝ-sqR9C 33uE ME-EmE"[,rL5ذgDlu4;~Xص较(uanC v*hm1 _@|<'V_}DyɌYFԲ* w%AQ10ZMj7]nMM'ǥ_Jy=+ -}d%I=j$o`Пk]$Dk#t$j5uEmzh89D6A"[,> 6pY#٪cC"^ٶca'Bm!n=xyG,"nq<튙:Co!`ΙX9{Bll+qG$t'"]"$cbV Y$=>7_MOQ,5sû Ycgvr/cz5Լx`kHF=; @NXA*Ҫz&PhYT <,uviː 3FbQY89f"W1c]Ǟs!΂]Dk+Hm2n!Co;C/aPWQIrlIYx%A =Ӻ$w%rWueIMG9;"<>|d|t{(.I:4 h&B2D8Θ1paq*{ [" ̎C#8蠎TFkmĴ9e-[Dc {G>s=q+1+Wi) -0͸Kt#xΚXևi$!dlR>J;>W^O|;o}[|oep6mȕ Mߚ8&,Mk0l_?<t١U=`yp(+=0C/=VܶmaFN= Į^i++JvYWT* E`̂bR|CpM0u!Oİ7OU~r#ᡇҥK_5oCwT*ZKKK,--xe]e]vvv؉3<st{8w??^_e(Q&CI덋/o|V}G>}k|_<:~i^:N~TZG-oy ׵4?$"^s}X]Q5}{߉գ|`kk3g}zꩧ?SΞ=gOFka /_Vaaqq^򒗜hgΜŋ<裏^:><lmmO^:.gx"_WN7x=/c=[}k'>`07;nFY[NҥK\tDzӛw>ϹYuu]Mo.n%k_Zn~q…^O/^ oxÉկ~5^җyu=裼կ?o{x'[O׼5>_Q_~$[~?C$?0vGy9ST??˻n~/}׽u'Rx9בӟ?)ϟ?z|^_,|K_\|7/>Ο?Oo{'?{y睼y+_yb=_Pz׈_v>Sԉ{wyueo {^]::o}[Y^^faa}|#qXk'?ybu%W7MXnEO|<=f{$%JAQ6(Q K(QEI%Ww7L~e(ql]y  ox?vy;{>psw?A^Ν;G;~wQD1J.񼅪}|_瓟$kkkc1yᇹpv}c |A&~;_շQD!~%^{'s=/xvۿ/9{@`~%J.k}cwٟt]z!xq>yGxի%n\KZ_2/_殻Ї>=-+%GKZ;n{__s.QD.QD%A(Q K(QEI%J(q$%JAQt%Jܠ( D%nP]D7(J.QDKS2EIENDB`mpmath-1.1.0/doc/source/plots/hi_c.py000066400000000000000000000001331340375245600174670ustar00rootroot00000000000000# Scorer function Hi(z) in the complex plane cplot(scorerhi, [-8,8], [-8,8], points=50000) mpmath-1.1.0/doc/source/plots/ker.png000066400000000000000000000330301340375245600175040ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxyx[?G%[nDZ/ &!P7)Nh Srp̴e-0mK f@( k$`HbK;eɖ|'%ǻ%=?HGkG߼~b' F( ˜'FHvFmF(ڠ5FQAk4hh4Eh4 ZhEF(6hFQmF(ڠ5FQAk4hh4Eh4 ZhEF(6hFQmF(ڠ5FQAk4hh4Eh4AB!.]ʽޛR4fQڠ>-[24&)(k7n$??ٳg'FI d0:~^{} ***(--p`&崵p\4777vٍ͋g܌ / RPP4ގiJԢs1JkpN:::f֭Iv(Lb*̆ {7駟jF>6׳l{mRoD>LS . %Ġl :yys&I-O P ߧ$^%)d}|}lH$bQH'YחbA'!{=\O6OtB.aH8&G9"Ydm _jҠ]ˠkkkQH'Yק65,~cض-ٕu9'=w8U&I- Ϛ/3h0{M2Ud}|}aK3Ʌ A<9.\rD>@>հA;VTAKb$듬 S [t_lГ釖H'Yק4 k҃$kTÖ iH'Yק4\$kTÖrH.rcꃖH'Yק4uCBa)s@߄!=O6O5liйVHnډusHb$듬 S [t{!!LZz#Ydm _jҠ ac1I- 4C8dBKb$듬 S [tWWtuqHb$듬 S [tVVVAU^d}|}aKnnn&= 0ԃ2{B/=O6O5liyyy[Up8H=&dSz#Ydm _jҠC k F>@>հAGBBPנ91I+LgU ;H 81I-[Б5ɴ1I- Z&ׂH'Yק4h;b74ݟtcs F>@>հAGhg8 fj j{1I- :2mAĻ91I- !!L<(H'Yק4h;0 F>@>հA!$H= F>@>հAa&!D9[z#Ydm _jҠ\r\tP;Ad}|}aKnnn&#z֖ZF0 suW҃$kTÖG-!ɭe4&2Cz#Ydm _j(k[ln`q1B!CT!=O6O55 b V\ɦMb^0 ?*B$(9 F>@>P֠{9.]ʢEbgee0mBޞƆ][>']z#Ydm _j(mЗ_~9 7o+jэ;vj*Ls CϯHµ)۪{׿*#*++Ekߵ~ZZu5kpӦب4-d2^{_~RSS5\ÓO>7 > 6g$Qxt}ŢpOw'F3 oQewT袋袋|-VϷNG]t}5&x),9H'YקJwq G#bMMI,f N;?۬Ad}|}aK }①҃$kTÖ|dvm8N楏-}d}|}aK;2.-hwW v?fhAgkI'Yק4ha~R:}>?}ŠZI- :ڥ cH'Yק4HHY0}؃BAd}|}aKddXh[ Zz#Ydm _jҠ#!!XmmۛĂƀo[҃$kTÖ >UNRI%'@#4Jb$듬 S [tI3fX}T8me;Ad}|}aKfY={T8]5r? F>@>հA7Gs5su޻7)3hg1I- ::$S z-=O6O5li!Z)y)N{W7;H'Yק40bvhAd9z+Zz#Ydm _jҠCtk]M %1y-=O6O5li!!X ߟX Zz#Ydm _jҠCBW?t8m  F>@>հAG`~heyj&0C.҃$kTÖP;;anAd}|}aK ^-hݠ1I- zׂn6҃$kTÖ=8$,/viA ݤLſO1I- zpHP[ p'!=O6O5liЃCBC!z&H҃$kTÖ=8$CG|o:ڠ1I- zpHɑ A;fAd}|}aKf8j ѽ;5Ad}|}aKօ0\7 F>@>հA}ZYgZ}m-=O6O5liCee`{w d_;-=O6O5liCTTX{$ Bi(=O6O5liCb˖),f\X҃$kTÖ=TH]U5L܋s8AKb$듬 S [P!!'[g;yj&lmo[ԥ1I- ziІ K9h b$듬 S zݺu\wu|;ᮻ>TH0mΝ0L#[Ir/9Z^MAd}|}A/^{'x 6_.$>h CKb$듬 S :O@>Pޠ_[޽UVfV^ @uu5~H?t%`O3U5.h;wTx^Um|^}Uej׵*֬YO[л% 4-d2O=?Xd Nxk'|r恵R%SX$iY‡_Kd|.[-+]vbŊ~sCB3㏡g*YggHsвmNv9 Er$YקJp5ܮo¢&#Aل;86$Adm _jҠG a (Y/d߮ "9h S [p3 #D&i$ mgI- zN=:GOgڧ3$ ɳ$kTÖ=RHV T9 (>Lv) Cr$Yק4BB/~L֯D >sd 9h S [h!!yݺgRSI9=v$ 9h S [h!!X-h?9$Зׁ$W$M|}aK-$(*㏷V٨3o>ph!̰nAdm _jҠG #صckVrs.'H$kTÖ=ZH!a7^p!ӯ4I- z,!!aCi@'|M %"9h S [XBBl8k]\Tŕ"˹B1J@r$Yק4豄"k& b (7iEr$Yק 5{rJ?7|3nkHpy͚}‰1y_Ù&z{\U4IF [naŊ1w\*++ٶmۤ=֐atio=%Dg¿//G\U4I+Q7{z/B >!XCB.V^~wop~n3)e$O|}C'XC_u'SBt%Ad?FAr$Yק niiᦛnb =vXnpSrK ٔa4IFB >СC\pqxBBO[ cp44Z7׉4IFB G~;091àb+Zr$Yק 5~4ygv?7U- RSS=l!wgIF =| cÆ zl޼yoH]f+PA+N_w{ȝI6O5f\.}Q~_sNnv/L #\wu~!.q l ),`$M|}0^~=[1qxCj[q)%! sa*w&@>HDUVclٲ{"!!X{t,_>HA̟̤t/Wpo9Adm _j$ӝJyyy/&Fַ 7VFErG be\{_ &@>հ_󋉅Ҭt(]#1;OEIqEr$Yק4艆x˨Uc &caӖM!9h S [DC2J1 ffwW+Zr$Yק4艆tu~I*%c{MAUCr$Yק4Ʉ.f͂a8GL GUa4I- z2!anz|s]\kvl {\U4I- z!a}Z8l7̺kӱ#UAdm _jҠ'F̄Ț}qe\O.ps̽ǀ ;3pAdm _jҠF(-6}ݸvR7)ngfYIC/G*9h S [tM@UCr$YקJt]]˗/N0we=I'132OCPڠKJJXrQ} r`fk!d2 ƙd^^MQͮAdm _j(mϐ0aw[o :8bm2AL%PL^SS}&@>հA԰j*֬Y##x-Y_R%p D555M~W}ka^4]ԢoL-VUUŚ5kikkC)Lb*JWW},++3o3 i^zis~1M0ͷJیȎ;&}mƴ8T?OU$k3Md-h?LMM =nHXAB x1}٘aWPjAdm _j(mÑ0 /j/VC L45v\Cf%M|}aKNDHMd1>(ow b G;K40=Adm _jҠ9p8f΄_qꫧ#\Y.Nz$4<{El4@>հA{&ptwl%Z3S9Ns9z"y6dm _jҠFt3@aʕS b2NgpT_SMX4I- :!a4쳖Yt՚N4 b1{M]S`$M|}aKNtH8sαv] `2hmM%2) hGtN{ I6O5liS[:vﶆv?IՅTUE׶mIK$kTÖ=U!a4O<sK/Ye%jZ08(έg4&@>հAOUH8LxU(*ĘT1`Σs(?p񇴬Pr$Yק4 3k}%fG b à*8cwqC _Adm _jҠ:$ '/[3 Cx)cΊ9莯mw }?Adm _jҠoKNjd1s0yNv~o'}I6O5li bb˘  oo0|4>HY '9h S [tB¡2ka(d {3ALyٜRu YdY|@4I- :!P\}5Y^7Mv)0|Jw)=q[4dm _jҠŷކW]== A#AſWppf83*騚f*K|}Jv`5K~x\םG_8=dx2N&;5Sdt8'\y_ KOCc#<Gz'\G`8H{@kBkw8=RQDaz!"6Xħ[qݷ(rEAvݲ笝 ]>w;ɕi4k'Lv):[;96؄?(?ֵ@ HcG#5m5Դ ܨ:O৿1"ҋ mOsFay4ibͻ89aTN8w{TVV˔ S [U_.Bo] {~;n$ڏ+#s?}#'gSUFyV9YGg[}n)P{=?CzwQ8Rm?k>-5ƀ 3 "řŒȜy|9,_RLna]`7t4Ps@k~7#>; 0וb)ppA>_Qr pmԒ&@>հe .Ov4۬!xsX3fܹ{k>iP"kj 6͕FYVYGgd ř7}u'{iZcOL_˙wqx:O"|}miЪΝ&oa=7d|1MCC]ZCm{m><; 1Gǭܱ/[2-E}Yi㾟F3U-4K._|1eL ӴPWgwVAIDAT[/vĴㆎEIoqeQY*/L/a N;VK1&4 0~IC4A~ jAZ_S RQ?d+ڶZC/H$$ƴM, A 5X#=V8ZJ?Q"=-4+z*eĕ;aZ?'Kil#^@ׁ 3gfrڎӨxiUӬSƧ-F%m[#=DOtkH8 /?Q5۶YAÏlS@(0f2f6AQ%/-ٝ @q~#_s%gSU7 =DOtPoLZx;==ڽ+MD$̌6Hx}S=Yd1j>g<,pIxFޚ鎁n##Q_}XQ[liB‘1 oiQ[]0mR[vdõԽQG:I[ei5TͬjV[fn 4߰3) L2YmOtP8A/B8l];t˨񯘧:fؤ6V7qwn?OFwf'oÎL|oS5E5oAK )ٿxq+XHK2sϝa"AS!HVZ׷Ҳ>mONǷG`NYM46?h߹?h ~5S22=36hiRCc bLZtJX :;կWbOLA$AS&o֭[ Ƽ8~r: 89I>^'ݽ:pqe=w]HscgK^Zico^̵{N!bKV퇘l:;|pᅖYPXivx::줷7 DiH;6!70M@˘|,+ѤR4}פR'ҌjbK^~^zɚJZf}c_Û4MuA:+;ꤣ2`]pȯw->f[/7ˁlܴc hnpaw}x|0a3<.]i! =ӓI; w 2#ܾ x!bKV퇨*lh/BMRN't,Zgif=YzYՉO5}R RHHS]]S]#1g8=,D|i#~;tw!yk$''ᄏsH8QLoW_߶c`O?ݚ$3mZM[Š`m2]1ݽw A&32ħqf9qepepf8m}c =NGO=t;8y#;z:s^`S]xR]5|\M>'.Kfʎ#zgK7_Omm-eeetE.DfָN;5M0M`x눐k7c#gδZA})*. .} [% ==9@/5 5UviלNP^#߁6&dPPpto3n=l3I]M0Zj)TR]+׵e KF^P뼤Ru(N`}$QQ7FC>뮻l222{_SJS޵ ~G傌 HO{\ǃ^nVo.ql|Gam-8[pނø:[H8L z( =./AK#px> /~| /].G饳Kg^/]4x%^!'BAя:344q:ΆZp8p洞N\xxs8 ..5.-⾿ܦ(ۂz0" vDMհA777'"}֘Vvp#&9{c%%[Xh0NOliyyy.!H `۶cV+yfk1XǬYwI84hڐ>%u+*vYf\] ![D7(.,#wt}aK!YS#-HxvY#ͳR0)l- Z`ǖ-KEζrps͸@qV6 "]jҠuHL xfh;Iz:q@8rdm _jҠuH847ǚ[SIM;ԁclk(/AH- Zqj G=_t‚f| ֈq"9h S [ 'Io/[g6Yע9X3^ nc%M|}aK!8FT[k›o2 ֈsυNS:X\6O5li:${Xfn֪E|>X/%KYwAdm _jҠuH8ZF鶈Cvs,C^j)+xHK- ZXks!Q  9XAr$Yק4eH3m{:** ^Er$Yק4EH~8`i`_03Vx S [Ȑ02mz:*Ye5Y$BF\rɀ!pmHK$kTÖ-&$ll֮}XVw|V'p@>հ'޶!a[l0m>aX/Yx,aI6O5liж xC~}o9œ9^n.!4I- Zِ0C~ؽ񊊬!S.z;$kTÖLHhs@ ofeܹc 1I- :!a]E54 $듬 S [55q:޸Q:aMihF$H'Yק4脅 { AG3o5m8,|d,2`ϟo[kZLf?I- zB!adO-[wޱE0 8XC>2m*H'Yק4QC^ktE: V)Xf|ypِNJd}|}aK[#) G][4n5b?:gf&GHb$듬 S [tׇZ#'#?N:i, O`d =O6O5liYVpQ[Gqaa\%$kTÖݜO>2 F>@>՘B㈘FA@>@>հAv19E I- 6ˍNdP$듬 S [ˍ Ad}|}A|wq8p z1zdP$듬 kkkKv 1(m<-:aRNJLv E>@> Zav{ovUWo8ڐH0Lv E>@>0LOv!|{ӧ_7o-OMh$듬 dkkko9(~-LAkR__OVVDc[AkD裏rgOr뭷&M#=NhE5FQAk4hh4Eh4 ZhEF(6hFQmF(ڠ5FQAk4hh4Eh4] 4IENDB`mpmath-1.1.0/doc/source/plots/ker.py000066400000000000000000000003051340375245600173470ustar00rootroot00000000000000# Kelvin functions ker_n(x) and kei_n(x) on the real line for n=0,2 f0 = lambda x: ker(0,x) f1 = lambda x: kei(0,x) f2 = lambda x: ker(2,x) f3 = lambda x: kei(2,x) plot([f0,f1,f2,f3],[0,5],[-1,4]) mpmath-1.1.0/doc/source/plots/kleinj.png000066400000000000000000002270711340375245600202110ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxg}u:yA"01(0(ek?Z{lk^9AZK-lk-EJA<9LtJlɏ-H眞>p u;uKh D" j8o? D"H$D" TБH$r:D.PQ@G"* H$@ED"(#Ht$\D" TБH$r:D.PQ@G"* H$@ED"(#Ht$\D" TБH$r:D.PQ@G"* H$@ʡCسg?~i!gv[D^^#~N }n:>O222?|ZD^^LMM0EH%]axꫯz{{RbYX qW3u@k|!KLӾ,x,zIW2Jbbuc@\&͢5^@crIN!.B}9G'$9Ξ={qAxIԧ~wּA2't]fqi)Ϟ.yaN,;CmJL.=tEoԧ&[_]&v"ů%s0c]qVw Q ֯w|csW c.k2Ѹߠ%X+ǨݷĆ<iJGȏ%?݄s_R 8EbprebMߨ_ۍOV>Ft?Xy+p 2{>]|n ס/GB /~y/ogO3_"pʗ$}jC~o캙ҭ|~]m1Ȝ K~qDgtb퇱X|7zb@\r6Kڦ91y;o˾ &ǿDO;]x(.,9|0g{W9tD04n|}{&^wD58hX(>{k?|՟ Q@G5Rd XD5;fMC{}hV) 4gQmGL}FNcEkj6i;|c;`RN8qSbIPRŵE̫O𷩝|6.I?c.;*7xYM_Á뎳O=R'D}bdUogGye$0 lbuԮB͝w~, מCy:c\X ck޴Leڊk4N3_ekyuwKƌ!-74<3] L4-VQ~܃}b}š,}_g$nó8B 4Fb[r{g<|3 FyÒ;g$J^;L=unY.r.^O1eq_$%poFHxϻ?;h=lLMO?'tGeIl {[~}67 T|Y dݟ,ײ2"I%)I-ISnefg 7H׵92~Ah ?Ѡ5*C#pۈOa(i]+1bcxpi'&7,-ј I9Jh&ѿTG"A<˧Q >ֹO|W^Qf$(wpQ1{xSͬiMU5t1?=!r>D =ؽw_L)UuގO9}$V?<4J_G[>aIm\vgx4t>:jJRslKQYIbLv9bc]]|#Y@ڨr$* V RSk | p+60+icVw3F|ff;һgMͿg tW$GEdIۡ;Nd-400x~@19ѷu4SGiHƆO3n".mvi|w( (uGMlPkHT;Nfnu=iٹ{# fi=p[vZ_Mykt49!K߭f&ΟyD`ppAFG188} 4ta rmM$6Fzk|p7o1c$"D(%HWG._&1kR7S'4p'?LM))S鬓IW akZRڀnB@hIZL'R-˚CobajsBr_f,7Ya}>zk}t7zȹȰJ2MBSmѬ%Oh?@yRZ97r_ޓ|sE4J7+s}>;x&;dbbs/ 藸j5F9SI|;M!Y /&ȭf ]֌L]6^c=v#lO7)5/-}'XVţvbؾ6.F&.V$f^&ڇ;jĜq\ҍb1ReSB7WWkz*I=AX"j:Aʋi)_h &qVښEB|RvK<$fɹ.nS jcTI{Ȱ=tIZ8_U.eG}?ɋ*ù^+ rֳßK&fg {yEǵ.aso 21I&<Y&k*ɭ`Y3һ[O)QB.:#9?^.c-eb0uTz5scAאKGgxF#HЦ5lnhXFZ#\ʢfظm9EBF7V~p,e e_GLICHAZ:mjT0pR+tyԲF-Qة9@^K̙W򴿍s ԗW:`8]%g`SvxxƍWL-,vFHDCtX7-#$h-"H(Pa:E*m6g}A/]t0A4A lĠNz4*K̏ͳx <<+cnԘk+Sm7ѠeвJ!&>`1Ihd)PMjnbHq44TQӷA.[ `7uD˅hfa C݌v1N=N:"L ¡֗bXbg2g6=Hb6&:fj:<'k&wѩ824ˍt_}H!0zƠv>%rDSj+n1~ Hz˲ƿM hSD ѠfÂI+6F@賶mAm47Ǚnw9&}2L ;Y_#?p &mqH mN٦2 $&&кa&ԉ*>;]-sPPNY`"VgxIwE8QGQz^@+ &4S72Y0hH:7F\k Usi EF-s{ k0eU8<0x*s<)I&4G* M8en3Ok.Lsf"m~<~h+O#kY1,'V# L AU7m q30-;%k%)e|.=qw&piͤgvϱ)M^gyFud5a* vbA#*(QK(,b8AjN ]⌜c$dMEOEE%|P h0fk'+r <{ !=3r?ƒK@EBgAAr2j!\Rzd٤spHIbmx#I%L!B}h>]iP?\chnelLK@[%Ζ똍]ʦ!r)K[ PB6 A[Y bqf o0בpcTLCTGPbuO%yxm̯.aCl*.&ƘN <26nHx@\k^m^6ST5eN 65`doA៑LCz V;$^r D\Q 9h1TȢT;(5e.iݪ-<6va b ۇutS0IȖ2LиU*2 ge9D,1^ryE"/Hm/N0/)@x^9@B$Z71 "UDeIza29lD_kuH*ɰp-O\ QMB  9 r 2޹2K+&+i樍lW4ǘ^aL/d\ԮHhxRS9Zܯod{1M.9 UШ   &v0nѻ'<yNތ7Po 2[ϳlڳN+qvnɵ]גM͗jlus, T*oy'o'gopAA*U"ۙ2M60%L| .4ђ+(q&!~Ja+2 Ѓ`}&% BTMdAI #yئ!-^ x%YG7'(ŦfY'Z׏j{uw1Ŏ1}5VoYBǑ''%vX1M(' f`KƾR'uq:\7 A~4Vvq4ng`Cq|l$q`WyT-[I7_+GwKvb;IOOr]wQןy.E"a7lVn#OG'<տ{aZ"t-u<%@!IҨ@#k~~g4s=UC IDAT?b]F Ĕ&h:CHZ C)X!BAZ t*0CQF :UVfeΡ!g k AĐA%a0ihN[׈bSMgjRN Z-? z!R~v3}b+`RдM5HPtW.i5%qIWZ34.VbGuf$1mVױZ5Nr4YS}|NSPal4uH¼Fj3P<I6* q $«pYG_Kuc8g<4bw< ۻ7qSyDw{VY.o{^n~?驳;q xGazd H L4s3\)BFK8 2#=t!)|pѢ5 J.QDX \Fj@DJQ W4a#\4#E\fÀiePIe,`IL1Ab Ó: 1Zbtj,:%UdQ`Am}cHQ&pxՙ"*(VA(( a6 !!>2$;;]CLB#>zg(HUF==Mӌ_ɡ .[8aʱz+t .M!;)+ ׫7V~_-sQ#?(_~ߏ {qz>ܻocͿ[z%.?`7uO@ PM{U° MJX7mMT ' &H&q tsf5Հ}T"ǦB9 ^ Eeh2Ot9H`SKX,F} !\8uDш W.9 beBCaT!Z( [aY 3b*M--j4sVFШ&(j oVДb%~R3&QITp6NK &*)W pAP4B1(a$K[4崁7R;ȋpXӘaE$QY̆`vk!M|T%'Y6dbdЅSzced-BPMBiiت ʒ)V@mK>Hr8AK-ǺCu CJ?'?.odslX|R;G~(_`0K&4'O؍6nd$VBMBFMkI0B e 5!!W_q+LeBAAh(O!B "!F\Zkf5Ͻs7A( BjIh8ZӪnϝ# T1698pNt;v+@蒄DJh2*S vP=k!UPid=NW+AVv}b)L17dgT!6[ 'l؈LEu3eb^6)L=`mP<#T"ln95P=M)6.;E4A3=F10(d#݇x>ʓ3_?xV a|>D*"aN1rǑw,şMr#N/|7bƦ :::ZxĕȄA` q.-()VGPP%V=R!b+&$MeZs'ZZZ1-M<+qM Miq<=ACԱb*e"jGQ MZg 1J Y.􄪁Hla j#F҈M9g1E98"4 0CM됖[s6r4Sq !+bh,m!j`VV |n0`ޖ<9yn{a^ȔQSmNN|-{]6Nr1_瞷,2tϟCE1&>?$#Q@@hn~ˈ%Ve/xS|~)lGcd5V@k@4BRqD5Gxffs'dj!2$ihW.%P2xCu %岠fFN}6Ʀg?,xZ ɜw9Iؓ#14rCK5VG4Z̝85߉[b I|f+7^̽j*b+dw{]uH/dʭx6I0o>-GW,1.9W}=Y$pҸ$0}bt QcAV@(QHB)І@X! pBy(kBCbiBe|J(Q%j,QǤCh-1 ><4YK'iZ2C7XBZ_f9JV4fC =P iyn~)@iD!` X`ybe1e ؐ4ۉ`F8$!V_dEڊC )4 !s R@ '}ܭ9G&&KQiH2"Fj\:V}ucPQǸT59L\Qnb&,I|͂K&Hz[dUo܈ .yk^Cj(`uz\J u{O@"C?cb~*k,$Jn\/UMkOL6J!<[R ET BS{M^eqE7W{hnf0\b1V;.熋y~U| /IQ@_<7ONuwsIez˹8Ww (IaL44m~\6 I$cvBXA^D+\d_`[ऻL[EW%W9FZc*YWA$M(b ,V*jXgB DHi$XB!WsX`"X6a,цyYs&&R"+vmu>F"AG ѭhJf|MR88@FwesJ}7K!w<۾MI -nxf#˧wp')~{q&n_<"JϷ(/PB7 />>{~+\9;SWe:r7oQnYcC4[̻e%cDw@a/-(/gHZ(L!K}cu$(-Ph|13 y9o`x@Sp5\Q10mxSuWKizE&[sgERE˺a5 |&)B@Z:hG!Z aѫMzV)DidY{,%RҵtzӮ.FЈaAFDA8iŞ`̌ K`0$!!Pk%uVon'?Yխ!V8Q'o̬/> ch&F^AJAn9D' qDVСӁ_^PL mycOj̇{#|`FE=N cddyүɔϬ1xbÇWq1{M]?.7f\sܳp>Et)5 c+Y@ S@%(WT.18m"RiVv!CY0WΡS* Na@mSp!AZ{HAva} }am d(rjUMj$#yAGP2Ed\W1#(`+1a!SaVS0 Chn8E~̑"?7%666^:[a5v?1>[=c;og?7>cpWyrϦ=W۞+l`͎:54C͊kqMCp 5 $P+PRP?T)1EtES!0@5rH\TʐVMk〟Dzb#BlqSפ W=6tRVJNx>u>4$4HJj)!=0;`,2AR+4yMfUa3 [0jn+h=@CP$JZ#HnC֎TtV6'|XvM\Yn=F,&]NFx/?D[^&g!+p G*)//|~g2?9U /[ X ǁbؿ9VlCaP& va-:LbZ", j \juJ謢1_BQBՇr@Z.ҫHFhVN9*2_+U+5P 2T&3z^!&#SvhƝkqcpG! L*-09blT*d SLLִE1/B&FD fYЛqsobMC[LDh0$Z*@.&z_!3@K< h@C}:"i١Y[bA[SC IܓTAH ]0'Z]g]yfyJ;Tl>`x%cg-Xv0&0Im4qnClDPA $aD)(%Ղba O܄\j>ڋ)㝄2X Se)M>')b-;C$@1FFKBaA(Ќ0b݇zS-L&mDu=EyA;ED#Ƿ7 ) hx@u >~n=I_&?x1~ktvx`B}kw!݌ްO2uw Օ9~nW5ꡄA(g[/%N(\y7)N zEg/qYT`d~2!Ԋ0Ġyu,uSQBW,.LLI.!T;H@^ hfbYO&86E&7HWb~!0g#O7H;G:9/f7Rƣ$F,k8`iYX4>BFjҩa>İ20Fg%D/ f/.Cݘn'>zꕢiM6ftTi򀲱IU&<6d!bSqpr'`+p28:wv>t7+7?ғ]dX1+ֶSšI;T{yf౫To2dz(#-Q{Bh FK) G)Y ^9X;†- }$P (r@ubZLEdn0F%a Z TH=O^w\)R3b\g%н){Н5E̠Q4S]NpCX+(+(9,дu`jP` aj )Q24LtTCP D)fYڞNT4bBI!!فF 'I fxH|@9uP&56dtAN=VfA8Qm:,~o Zm~*_K||7!,-9zK.VK>5cǎ|9WwXLHosd |vxe1Xu~bB֨*i 0N 潔87C]z Iš=_%h)U('+!|` U\'6Mji0 (&JtR)a<<m硞#7HCB&੘PMlAuTsۆER[! 4R$Oaع"\.$T Xٟ̓7t LQ a!1 ЌG9M @)B n" zw@kE*@"I"hQm# ) ʅXƠoQeR̃_*R#rG<3Lx6-Yt&\CѼ`ͨ|ia9yXs_\~M{k!>oA0Δ5ǹ?:[dOzN?xkx ј'D`K IDAT3#ؔ8(#4 <t`ԄHC,hM1FcDB !u4MݒtehPmG%_w >㬂<)mb .&taQ; K֐̭"&`[6D,e. NaL`(bFNðh4c1m%FOЭ=o0#hu;qPciP4#Tܛ*$ۜLBItXFARnK`NM(&%t[ᕧ"lQ^3,5@'\)8rxgM&DQdBf&`^(|P@(Ldg.[x 0ڃQ%ABw]yo \h@ {c*F.p) ,Є"rĕ}{RvN[iQ5M!`4mԴ*¨QE(jVPD{jDJt70ژx?ReRXNB4HW у)f),4a5mӰ3# JC1F eT* q& tD5z\+TMP8f!Eeq 3N@{Ddְ"踓h!b yT !Eh&KՠӌuEeh|GqvM=ċ .EaΑg SSR2x_?_:ݯ/35#Wy5ʒ\D#TUmf4[G5إc;]p;87 $Х toYY8%u 1lB`ƚ/0lB ` v@آVmjZq PSѐ۩Ik #jPY!;3w<*f@)TJC[a9͚l#r9HҌtu?dXi"L(aV5]Rb62ah0#C+3JS! TRJD j5JJP `"B#~¸J_E GF᭐>LhH6| E+D;21mVHոE8`TNv<#9KR_LVnR]-kS3?w09N:E G:v=E1_JTA6 ˔d9(ZM_ӬkGgR3?Q/9 Lz$L=2tK16.uڡ+4HD@*Ą &% 3@4әAA jZ8ZIB {5aAEP.pu ]MԈ6)Bt@H)X',*ͪ%$ZHA%$+$*JڂJnhms*Z d IбJ 2E3Eg9% *j1*6Y_qLVбXA 3ACܴExFb'АظI& )h5I+ PwI J;HGU!繙40nxbI kmv_}vje9K<:N@z _k@c>яtWWty͙3g_:uv.>&'ɛVx9ӴGc1ҌiE2eknHMZiɪ-9(9YO8|__ʕ+>|2ٿwkok-}ͩ#/ec 81 \Moggꅜ vng+t'S*R3>`y,ep4k#;1gHbI3&@ǽbS((t,&-RP*߈elHD`WItR]*:6BTFA7  #<)ZMQY42DU&&( /!|'mA"xgYhP` .2i`g&ÁEihb+E .!wU6y9+ 3s8Bs%t.4/g|M')?~z׏r~9^׀v8rW^9r/}Kxa}QN>#xEƛt?Ū o^<%K_fysFfv]VS;o`vA1>a|$őUv#7rqx[UEY}=ƜW[\kc{(} WhPٝo 5 V $Z w|g#V: r[\UQ`!bJHS@h;ëlHX}{k,$ؘ͹ ֞8 naVsn/PO9t&aig_Sr/>۾,o`~yfWR C+qWrq\r_ub90O tjÁg%je[=[aXȎ',~Q\^?"-ZNrЪnn8Z kB7S~HAZY@ 5=DBwXH%)w,A\ϒ4-Xrr,-1Vʶc\5ƂI7No{J#n̔(QfLPQE;Vl$p6F^]E]a Hxh=sVBLvx 0{|x&b懋_HJ;\PiKZ7H'NcJ.Xothn-:X98{oڷoo~S??z?.q9N>_y Խ |p%y kGI}֩>v%0qd]%mWqr~Mף]Ejݨ +j =YFp-"ψ-=&}{ ]C(H"kuq(Ѥ6[0H0 [ZkĒ)qb.$X F4*l5cf.Cjk@%F~V(MP DQc6(!k DaUc~tIJf|6|;܍!92C܆NT2D@IciXaHeXiKL3j-.6;m"WO_yژv߰xb|9vwu}?]@c<d,3S[<g= s]B 6)y+ƀ\aBAA`"a MB`PdiN)癞b@s =~%^JzGlT ;O #NJ[e20"~w9B7nTKroD6m0`5aAzHM *ST+TlRAǃ:!yC&XXZ"L1i`lvajAVQ (RXnjVx3H JP"xf@-3@veu~ūoW)k==(4![iE%ƵxXthR=r^8O޷i~f'ٗ}7>Qn, btL#G;~/'_{_5'' ^} j:P|؊ieT(!d}Zgp5Q&{s4ˤ;/cvY)֤B(LĻ0 ]<!a1KԬPqjI݊^S[ P̣imsW|hFOU.5aw4FH;- <5QIHds[IkZc0VcpSa26?* hEuLGE=&zj- HH}sٍF)J?h^}{뙪;vBB8D!Hu,rIBR򲁩< Eӳ9Z/t8NCg Ɵ/c_~^Sw)N4Zmb.qѠFBB+*=SqX(DoϬ(cNm"Zϳf+ߎbۯB _;w,$(TcA'hi8ExS3i-°ɽM?vOl꟰_8C96\NVnĸ BHB(< х 8Ńsrizpʙcg コƛEe5H< $ԧa{^qtVzL{7NIYD:nD=Euz:nf&x੩)Ô^ Sv anJ>UB FW 9rه% K@J 6c鳚i==@6K -@m1acȌ! QvΚe1FJ"E4DR+m(<ǁy1Ccf=Ϝ/m곷O ~o8\|a9}lOЊ`A+jz$׆IFb2Wo'sǹ[Ƞ|ކr'ш vMT~cz?O=gVʹǂ'Y90St'@8!pvõ)ymY]7-Y IDAT9w9/1E@E),-YXMzfR^EUԢdiWNP& If|x1s܈Kr[;Eĉ}Y)Cmg) ˒pmŒő`II!:dlPOggHɀ.#]γMAWl ~t ѺQ@y\pF`8aS $PÒ`+`"c0>z1 ʘMWt<,͎#9jR2(daꬁ)ցudPF0ƒjДqpk;{*͢\el'᫻ٽyC˸㫣ząKnfU5K:M: w`!; KMn?xo}ˍUN7R>pXQo#7~y.fM7F5eecl=j9٤uM9O:u)Mҋt1lYykp=\HB&)<& ЙƷ-k8ĐIKJb~죔 l<#óMF*#VsXg[l]:CBCJD}0\p )H(AqDT hIi)R[`[e^MAHw8`+ÒvIӑYG PC0$`R"Ib*g@v7(n:N\ٳwI%%ޫyr@#(j7 VǷj?\>㻾m`9o0b /Ǟm/wq~9Јi12$7} 91#pG|u'11$9g}RXCќgT< 6;)hA %-l#tAzD~R ؒ! ?>4(}R;t\gy )]ٯl3jocǩ!ז@nBz%)4bcCI:Ph4262)m2'@=v:8Hinf CPJFJ# Dg6 -`ncmcm$mm;t%9l64-nI% ]xa0ӀIU^LؘquhcB_6gL@z ߉TZeU xRjc /ϻ$/{ou?w<ߚoꃜyO=s/6'fSe~nq>!sp6[Xy%q+Z<2=48,)5u.C:B;xX,PIjuJ4d~WD*Hˢm"uݙdR /}|G}b[hspa}spzms=#ah-@i5P2a 4hYh t t0e`DHOꔶͨXWY9(2jZݐ$T,ش'v0:I ґ qy]LC#31Ȕ jbCo3U` :Ir4"7oE{}og`ޏ;I1!ۏ>`Z%WQ;iҿY今?~#AF}֖6 ?tA7@@<ÅcЙ٦d3S0<<nH3!;$ku2@!A QB:*8>iL!bxoOB@z:*@HδZcQ&R 4 "F;fZB!B.'&^[)l鎁iSFdmh[G6qlsمQ%h`fq[9kRlZb+?d#.j-v tiU<ㅖ0Xcc@"kqOrSp?{utZQΐ rXE*OrcF=AfӉ֔hld[\*a)w4t.AAg#͔bZul#EYcŞS.+a9Xj KHc~cc5 nm2^Oo!SQ#piL}ܔ%N)[ٕ^GLY~5xoh gJ-VD| y `3$'RA:qeAxQU=To5ƐIYyܹ+u+gQRh$9[O?ၗ EQ (g YpDYI֋tP;Gi!Mƌΐ_d M&>t-# b$H}`FZH!e]*g؅dצRqԌÙkhijɵeة\@HU!U`Մ2.E2ۨ|ƾTnYN@-lr`umFJklN}76}/xMiT} ^0q i0eI1 kC3j_uY M#>y̠S RI}E}M<2` APZC9C p+a=i2(gA(!OcNsΒd4LH7<Dž0SMWYKz:v9Df0L#t0q-4⢎ .fS|?1<-x+j&vV&F1#CFä1cb*9c*/v Kb\֚%Xłjߵ=-=캅S}OQ~>KU/_E>Wҙ d3n[qo!Jf7"86`{pH,}Y! T-ٵA7S SR,3xmrд0WYZ"ud{<A9I 4ϲL!p6:pfqز[풮C{AԄT8Xql.["2YLaHqu$`-5fPeM:Bx/f,Lj2cHØjHDCꨏԌ c6 BمN\Fp~y'C'4os&u[7' 7 V g*/? xdk_6L!rHm&'[}>0^E>jq~Yvh,(.Ȕ@"BXG* :;0V|բL u?Bm(Pv#i5􀡘V3rB(m p G p]o#GpbYJX&=5p]=+Lel+rmM!\2e)tjah`h"@h`L5$!Rh lGbhD7@j X̸d<8[B6اY3.W슨 &8II659y9 ^_9Fžbdj5^wrg9!`_agŵ8'_c%/Yh`GWi֡!Hz1%/0ej $)[X,TmJ;@i,^)+@ ueC,qe- `  0FM8/pV3PΨa]:$Q=aG`9=BO[䬡M8  @&v֕dU )NDXMu[dR7q4L@:N^i"Ҭ.+pSǘ&a$h cCK+ۑ|(JD'6Vqƚq9eqt{띟pGloW8j΁-|6>0*'y_.M^qxkcu-yX~(r %l{#Ы3خ"6ـb@CG`SI `v x @Yvr;0[*Ͳ@-좾 Ζr^j",O $$#1n9UIdrЂ9)iGEiba7G5HVvZ1^wdHi$h55ǀ.qFJKԦ.iT25d$a]|Ub#d0 L@rB'A!-߸לfGS}O7RVo?~;M?/ȯq|1w7E_swiԮ|9^^ ᷸=7~q~5]1;~fL,犀2T ;&G-+!!ELJtNNle9;ff'8:Y-SǙ;xHVebLXpkoԣ?qu^]O>3 l7e0. @2p(EL %1DL>uB.eSiI4^۔CKKe:fҶ[vF]I=:". )a +[W$%<) K(|]i cڊpH 1ˢZ%b-f B p-!Ui[fk21WlWLg1'=%-Od1 ZeERғM(կagdasTڼR5 '8/ms7ᄒBCgRS|M8y!8esbzIMR8W0_!6}뮹'^|>T2#{/>%bq.OGYxlo8u.Pds`ԟf0d$ y*F  ")AR!0ZX6SF73i㵅-~ZT Fi.. E2dPN [ª@m%0*Kh.;4IEO+ g9V eAK2  2]fVA - J|rV۝]O-Q,R=& bcr`T8m4wG9k86Ko 7sx0AIQ"3u XRh$C$ڐ"2*CFJblĐҎ87/L&tǙj=n&Y3XCXVQHAuy`n,z6Yπe 8rD GJǡ`hV Be0Sa`URoce)~%"I/3&owG8t hI3Ǚ$!yӹjHxnc?^XB?v vgIjн}e\ݫ,|QF0Ҷ %:kX91UTI"*9fAOB1{ J;:e 5#*zfO LX'z]a BDQArݮ=Yg= ٺB,)@8$A1L#L'eҊE <ҭ׼@n]sɲ_F; QJ5pu_C; RVRn7 K5f^|d `6z˕7k1t#F⨗R"BP,jc,j:DNB#SA4n&896u+Qj1J@[R|l lh\C0"a Ө΢EV@+z.9SBGa6QUXTXDYB:෱ JTCFWxzRBd*/О%ePk@ڈcjx[AABU蜔Xp6_gn6v+];N/^L:)tI?O0f(qׅ{m;៞[K)fYҝ:0uL OAFAy IDAT7 -x(:+)hGhJT "mX0Hw%ˆF$AFu%( zye ( ̪0 38VQV5l#Ti*P2dR`({eUB CF @Z```!!˧\\Z}` *E\ʪκWbf0 9qXއ7(\wm7X D$g~O*̯֓| xGWiIH=jI5=[bIVi/N q؈ĢKf4Ԑ mmΙAZ ôlc( mT;q K?# VpA  :V8a:lPfBtKs,.#l"ҍ֦!GuDef/j$Ԩ'Mׄ IAMm6fuhXޣJ{bgwoDC%X՘rOsic~|0B;kgxϿO=bO r??V~w_Gi\[Ktt@>U0HC$`$N\56l(. 8q$K XIbEDBf 8 Q;k#!OvUA-6hסJX%J+@/4QZ:Ae:tfh "EDP6@(CDGd\P\2QTlf` S0)$LAT6QBB A+015Vu%JeL|2#}y&!'Տ4xu?R~?O~y3HHIP*ZML)ORLܐh#ޘj{ %dVlnQjI9B rk 4PZQFºpŒQNhyh` ucuԭU^puD7P l#C*+(;HR -40i΀A gOyp a" AqָURxYd\ԱoS=U_t}B?0"̍Kz yZ>@ G¿6G?p[7\ٜ2D9gg2VǞjCV0$P #hR#fMԢF]`$i: Yš:4B]R  v ]ĮC،K!Fę~Նg4`MQm!2~dg[)o}{YCL&b7quw\z^I (9H hšX"BVRbIU25/ԽRQKVf1}Hc"6Ty.Pȕ0nZ4@|FsKseEY{s5 A*azyq8qړW_|zk߾g=gp*_/?NZf4|L_(Uz&D}FdaRUX;Sv>H"N IhUlgvʚ#H5U,t9(9(!hSrM9c VE~5QHA|v)'SBeցTO|bUz܎g{U1!{SHըtHUg/`U c4b4`:++iK %!(5G F-V^b!(i#$FIlp;@m/jvꪍ?EZ9j}Ys6ǞfwS=9@Ѯ_@B>BwڧB #-6zGS6` ^ =np딲.%4і: jHQ9!EO7f}{ϥs"J. eA-t_ > bЏ3*|UM~ܶ®k ;Ľ\ϫ\"5Rw s%)4xEi1#0QӋ&x{sG78;.{C5=Oj) 6L)B }% C j8G 2!q\sj7Uwҋ8YU $0R2MРC5,TUeԌ$2AgK2_ Mٳ&DbPr$z`>i12w2<qN \Y)2bGL&G+8c{뢡 ԇ)65.^\u}sBO OD) }ݒP PF)M<rsQOHo4-`-8w9,jAfBIG=5< > ;I<OzgcI?mC#Wxqc_ߘ}@?(8ٷswXdu}7;JUٙ5Ř5 9~#r0!N6v"Sy]gB0eya.f(tуrw{P N L38nKJY})ðhrX9>mHDs_Mٿ$doQt zw0~e/BL q<Ɛ]Lg4<?v~MoOW7#'K\fc8qtԨ}1˅ح(L$vbrpC`>$T&y'3`lPaBcnnUL.S҆6!d(+źRnAe'"1M-n I baj6WqMr隷:6hD6:ИF-f&q#&eb֎ĵng)Xy7v^WwZ{^Ivfdir_ILws;w 'E\W 2Bj#30n/FjՐ0E#a$cHNÖj#.%J}.Rk9`ی ]ΉeP-k=9EQ܏3Sp5nC[u-S6Zhقh44 d; {inD{/==KC=<kk :7|3|;{mKco9 zj#ųwHRmA*yZ,r8rGcFAq!4PY ΁sJm(nQU8I%z\4u]{^^W/“5)G٣KB0c8DvEME!YbXK " Ly@uaz-%xZNUt VJң5.Rc(fmd0vmIεa`½9فL )EkBVZB[IZݱ蝝=l Ƴ{{3??G>N>Tʷ$dW%Ʉg^5o/%G DIdT%| C,C0@`ܟ0WRF8_fLl,27pz2m;tт]At'8jnu~N묁p"$m΃@oZh]3 :PS4ңTCmf{FZ}M}#ƕހ|3Z~__}{߷$/ӷvc̻uYZJ.S-%GIH;r2rJrJRk^hA!rD23*Y 8dG|y޹N6_a{]-p1)VK8xG08‡42Xz&pLjJ#;݄8TzKg3XZz6~~q}l-oy NwB~p77|^nԕKWC9:ީNTpvUІO)BYJ<OW֠G>W QU<aXCl?xF|'ozӛn;yOOsI;?qzww/"ddm Q]SEtB{wq{'.ak1Fhxr^q"gM !ါqQjK%d! -1}?7*{5AI$QS# q8 s'iޏE<7ww}'~'Np8}4x+8~8Nرc>}#GpUWqޛۚ}woϝv[=˒, MhBG,0B'Rv*Eq8E*1P`9 2jIHVwߡ|ϼ[Û?ַ>ϭU>{8{8>z=M{Owxzy͆מ ,xh1]6!d 0 ;| ظ8>.їTNy GUP舭T  9?PaW1 ^鴡]4*s oN1s'">7/j>~8ZN<[N<9#k 'NַuvdG>n6ng d=c,#^6-"%eQgK??.ӡY99, Yصc`e!,tw'3[lzqng>Ltb<"c"%1P`M(8d]g.~/;^ve9%J5M m*N=Ӎig!Wn(<< EM '> Ǿ۾'~';Y\\8^{-y{~~mZ}{W}ӾeБNϭبҕRTͺZv^dP7 d!2+ȎmK{欌KBF;-9JiӖ%+ ,;Xs!Yմ_+ Gwsqn#-ê1,#B *f8gbggGiݶ} /_'~n~c6)ZCf5aJ&q4 jȔd/vs׫[bЪ,*c֒uKݻX͹c<0>#}vOw٬> L8Rv" 2x+gxӟ5Ȥ$^ZEpعԦ+z> =A~q,,, "0c9]CN9!k4ٶ^C6 7 EXќCR\8MMq̰|HigLNm.T'؊#Jc5EJ D}|/GXZǣHX "u \ʔ$|< ^O}MʲxN W*8Mƚ\>Ca5t2ˢH"lMsufMf0Jk2Q T |aLZj訥/d`*.S;Cf{TE-aGZ .u%#[R]nlYi1l9q R^VpJ bc4ɐ+l#̗OO-b׃+'o{NS֝ʺf7wmt,Z"F*vn!aα! FSQUCVL̈k tPkP``i`@ ~ łևCo2,O kJfs`-! B=2O#o#-YZЎAKMaf'4iJlK?:| 9ŋ?ﹽSo𓱩}ݴtN`sӥhM.LG|O N `bE%Et%% zNq=&3#iJa+nPs'g.`2Y9$,p|@U& ud}|-\R ZX[r#-hIrA e~7sfDȷnԧ>0xQ>\E ' 乬gzqiZĢbs rYc'\lc3]$ZP Q9V3r(բjjQL#L?Cj]A E^@2F  چ9\GEWrRv;E5FǶ\DW Ѣd8vSbU!;8EZi R $u#)r4U o]~n>@{~b |pJ&#n=H{}hg!~0 ID=mNT˶bHELRSHs;Dޥ ;4D mClFڪih'JfB ,[D6ȸ.h;%Vr[0(&*O.)ih-:EacGað9KyLi!I?pmzv:A4y;K_ |xovzr@xQŃ!)|qn*b;w@ҍU]Q C (&D2ڑvLaͭB"벆¡5*h!F,TYAhL=naUh["\b-pc>ಜDM)kS,_Cyfpq,L0Ḛ̏l[6mZFL̟#idK-rVA?EDB?bp{W2Q4M04$j5BU̠ CPG(ɈdM("yND;H;@ˣ- ѻ|!qZyZTG IDAT9ž^!f Cn#K1W8hGAsJ!X2fKNbRH0E68v|}|ːmBöK= K&uD(H, vwNW_294O&i\Z>) F]`UVCDsBβg$=dةdj(h3/3!f17DD58 Qk$'RH PV(:##=5SsMVH璶E*DFCԘBf]5X3RГ 4RP3"{0UK؁!  >Ch`bl}B2ҲlѤ~J,>W{p|7֬5 >~?_L ou}4Og?tiIR4|AgbrfdjRH!fXQ;"Qk29@IZ@nnUݐfVu|"햃vjv9KUtCLk$O'!:FOcULf(CEiRЧ` 6y\d2 2Y'U%>Vتi[O 32L4g4 No'~"yPM%= Ov>j/>1)BU_VG:7ؐkszQGLm{tN c4gd#29GsVN_rV$gSrv&gHn Oe,`Lv1H:^kWub/ W7Z\Łc4_S0_SCpyA? {~hB~O]l߂^_!tR1Q [ӬԒ=ťrN?$V X4D3$4y5Rf hC@ZK$]?Q|z|i5\i`OW==g<ǴAk PDCZB(pisRb-S6k- mcl[:%v-L474KNCjdX mV!ͭu+fΐͿ|?i`$_ş/o+ƌGǨ0楌clXyU8[w_ٯir}>[o-uξ|bbqk{!d4ql&0&t.5Ć9<(`DJ!95*v2B jKD j:F-n+Vi0xԳcϞzxV^Srf"x #C &*!@6s#-TAZ`"C {v m`Yfu ti cAJArAhO Wmیq%j=ch-sOje+|?i9ǯ?gqtOKwveqmT{,CfkJ %`DK HfM >#h!HJ6UD<7`3ɛDݖ<I\JhaSQu Z7 T [Գ]<puO&M^ Dёfi--i1M ‡$2 ϐ = ==IǮ@ h 毑u_r/LCiݴ{7W|?qhw>^8 觉X'i./}=|7[ys5\Z3Ywk3+<8p:S36ڜ Ah@ib!6 )w[P1$@<{Ush+qN2vhnR- 8,N3g18v11VGok,x=:Pv7DsDZiO;-dԆE oج Bn:t,Πt 3MWJIG3=mf`3XNSjfycr ގ/ݞG{m>0A?](AEu7?wQ/W7yu\<"^ˌqF#Βy!@.A| і9't]Ŷ"s*M@`Q٥fK5߅Ky_~Љg;_kxy׾^˭Eq8{`c= وVC&0nS[ZQj&e;Ɯ-{SJ0k`$uhHёAD] uH-25ke4T|5=%\lIki±#pp8LdY߇Qb*r$]q=DۨܤZ2b2i2M~6qB%k3_)OIyZ7WuAqt߿3o1|I0A?MD8?6ke~h{ƿ19{͜=f%T#peR*2A@QEqB.Gnڒ6ŸQ-\ bcz;ڡ.`wrPu8l4z,yDqz>ԙiSGM@GQScbrm !P8 ђH+ X]2 =J USc֏ͼoy:*3N|dS5HL:wTfiD~%9iig|Ⱦ:}@_j_5'0 !?yO|RW7aany6oxq^|-'q⚊V"K,ŎA7ڌԲgRGVP :)P6"Z Ea#TQ I0-Qx2<8tga-ڥ*:Uv#pc>-.ztVGc p#^ɜ{(HI&P 6 ]e H&jN+*W繣̎MH3Μn0MV:mLBcUQbSXx'DTE0ԏ`\O~ |raז}~wgi'}\:!ٹ%ܦal#ѱqJ6LTTc&,FC?TB[6^ &DD+ryS=R5]Ep’[vZ4rp~P]>ڢ^[nZ=NqȹzBj pVϒf` 뚝Gd6QqLOf|Rts_b6""kqN "QFդ8Q)QDGqL3lqPBB:m<&EUx: zM̪hUק-LIS=p3ΨT#[8SoʒW,+h3L,.V,e2cm'a5Ew8M/AKE%FV$ZJ6m` d&`l$ZE%u=UAp"yrV~Nޙ/T(+BwؿZ#0…p@RV]}z8 {`<sgxobe{V-gۑJނ ~ d-fTxLz 5Z%2gYrkxWj!JpJUn4EeYtqF v˜w{sʡ4+3̰qerY%W% X62f|S ?ea '<{0}͗E*w p<YbV?en{YM|ov3vy$U v{N%#weȡ}6l喳qX nr]"Jt8$ B==%&`̪V@׌jTTP8Xu++2EѝxU5[ÚF^x.GMq{`E\AdDN1,2Y+YZX %ĶE@m f?T˪XXXhD1A`jxu]f6 [$bys=֝{@O~0qWeyuv_cوrtݻGG'6y͠K~9…\2N LlcE{^ qL1m^w M QҌ 2#5Kd I(M5M. u^ɝg/e m6g1z9.[[5 =?A͉'g83⺑k"VDy12p9ïgQa=ZՈ(q15V ~3OwRbi# }<dmk9E.-¨'r<-hcѡ=A:!k6"0!nAqE$#&GJ"1>K5>!~]r"*CD9qiXqܘKrST%s]am,ְ Yw JC:K)'r -2z( zIKM$wl":(S)jJMJ lƖMf3͗&B3eL'/z8ŋL(DQ$ĉaȠw=±\_-c3x ,akk7W|EM.S'Dԫ»gZNYs`Q'hHn]S6rV>Nz٠M2t'Cw Vdg<1 65(69?إfD b\5^_}jA]{wƫ*O IDAT@A991imn6Qv:aVCȈu)|5GARW0ހ 2hnYj8ҬWtې5.%8Aum"ڌ_UU GAM11]-l-QQgMХ͠lm5Gc}K&l2zjiS@΂,J"¢F$'FIZ-cj?%Q M %N ^R0TyC9M5ؼCEf S!9t"D/N,ry'9~?Ix\r݃_,b 8q];sM>'-GX^5=:U (xjFN0ܻ^LZ=߽k:19[/dȆQǠXD$KCpL[X*h!h "vi0AC ; [=Gge}.}lLm-Km,x1MH'U])-QUX"1UY@[> 0nV:IAl .AC/9N u'I*&&VZ=Is6.ÆI,ӳhk'7^HG#d33H fł6Kw7ybA?pYdr ׼;7k/~=gW^o[/?O6|xtH5'P3o?,˨ 7n>3OQ $܃G7Xxh)JMΘ %xO$e&4v"cfq@bH!@ b5bsc8Ɨc ޲>C jdD*cIdZ:@%^IdܗD} I`@Y$`{tlS< h`KPQGBhTbP55IJErEo#8D2)9 ">󴙸oÛ1}p]SuLtT&d -.,.C8 gԈz7'41/io^Wz+oz{ 7txlpK/pd疋{dFBg+N)$p6–izq ,!/xR*RuEn"f$2QPiNjVVt"|IWbM#xx/#f`.+a@KʅlQd){6ZBBIDzs2F18 t〺XDd }^ &0|T"B-AZ@vx2L9KH"~1mdB1E:g<ի13ݾ } 6˨,!~5 2ӐsO6VH>I3[9G &sj*ot W0G3ô̮.gL[nHgwYxQaN#=Go$7/f)~E˝w>s֍o,# o}_,[, ;!+%*6{'>w}_ ,YzI,Re,7Y*07ܺ&$~[`n[x[?{ nFX)_ cH7#Uh+8ztC]>ȸL;љHPi4퀷*$J\6º ;x'6FrC ҘpMT3gAGZsY@$JRh(i 2`y0 fgLsH鹝 SQr_"ů RS)%=ρd(eOmc8&X$l* !` Lw|&?v%u1'2- @30tMr(\E_WhKpK 1!%PK(@REE25,G&%K]̲ ŀP X{.t=osp{[tr?;pVR*̍"AIU=Gdi)l#fb,^O~.S|K1nX+'oS;w}c|C機T8P#%}JFk4Ew ϫ_[O7yb\a&XA-!*5఻kQ̊`o7(\:}IAb` we)6s0p!1$;H^`+}<)nRX24ݢS\9ҹINr$CE,Y@bPc"!}SCQ"LB M@]ŋ1G%M f ꓩ)y2 `A̭Yfo' 9&R~!⛿Pڄ7ي"  UKMix9v M^]ҡW9?{mq$ު'?*~E[XASR 3 ) }Y%I`܅ц?߼@sgK;[5FqrB!s(5IE1Cz`m!PUv0W0 c:=(E$;aH!if2hGH#,b'9޴|LZvRptЅCS$C5@yQj,,Jz DJ"mB@10FS"-GU!RXa ۙi@j9: 4H~3>|v+3/eO{ʛAvIJcW~8%vhVʿq\dB+)t&,w.2w$g='n6ƣ|'G9ާy_bŔIowN^_XB6M^8 o<^B6Ǹ#5CSO>XCg4P ư;,x}9޽dr 0 QƦX6XA)U ucl})ق})R4&uD(5>&B #- l1Ŏsؼmr-ĕmXBe 1˨,#f ' Lƞ(]m)li+R@ DDRg+XGUT S Z*_LF@4R"+_/d34t CjJWr,<՟Ǜ|[#?~w2Dg  :{ycXxO>?adi|ߝ񃵜ɧƱS,XVr&Ǡ{rPp9IeLA7м1^{yxz5dnhqT=NH sBD_G|\g bƥͣ*Sc4s߰RǗUro Cvq&qTQI,aiPGh`dcx\2)_6+%^!bPETYYE E Ԅ`^dN=>#"ɨQSPё<j@j SLTʄp:%;,ZlgrX̚zą u:)AY9 s+tLNo@+;u+Q A\@ I EɡƐʥK'y:ٵo'Αo~J'\f,|(&Qѳi~z C~7~Jr?O<__֞/s'"~+? WO>MCe=9j^@ur>}IW |*IedƼe+;ɟyl9+++s]9^vxtP?_<߽W߷Fq:sCl3/ XXe} z9a Ϲu3O՝"N`<:bewz26:ȉCpgљ uCR bB"5?oxC0=rz Jv D r*L"ER(\V)HՠZ0)[ F*G Kv fCdPTGSZؑбWbg9eԟِ`%)9}"8<1Ha 1hAĔzi gKӠ  aOnz̶-R8(R,g@pb $1^8es'8?X8Wj{_K/s657ȏ}I6ϐOV'oܮ @8qO}So/ .Ik_S|#[<^g?7VZn1cp,&h,U9[!vJК0=lpEcT/7>ӆC41MGw)ZZn=V^dq۪ݗggtwwݛgv迬?Ngg|套^8?s?SF|#}arws|w0yҗ84dËlrnD6B6uЪx{sk !*EjsgvFo +p9*uTz©6\ eKx!J EúW/y΀2qD@iH>| n m̂P \ H%D{)[`6G5B\1uԵNpuk -K ˠ+\mMm]BPSO)} sƞa`AV)c ]&1C'S଱<@L$ܳqfXOs +7 fq>t\᪥GnF!UU:Ues9 FGDL2cN 2AGjĔb!RPBfJ26u99f|: 5d^SSt &DXgrz^P5*U߷Ǝw:G]uz>/|>絹pBk!^/ ow跢^uٌ.S]N<\Y$-RJ@ŀRGjlɔЛzS7}z8N.cEL,DpߢaZ / 5]k' BB4mc -rxo8 򁐏Jz&VQ3a1WZ6Cl5HGXSJyf&g8RLbs-7 6`QfkB7uMT1h kX`Rm5{yac$(ШQD@MmB3\4-~dhXz[5cv_)R4D**7@1IJG}:tTi?p¶X1SNQ]|Aŋ9VX 2jzgRSڟ dUXrcez9h!Ő22%LWg + yOd Iik dz4>X/mrltǖk).vk8#_DOeCVX}uyÿw}+ۺ oA])87xdrϓ7Yٔʔ3wvp+&~o=ԃkي  20ȶ\ hC9\"< rLxN01`b« &D㲋Q*e9|iS9CUPTUvd; ;;7Дk%S(g딒uHe~GWN)E籇A%)=;4#.7 $*HWfݖA J̒d4uBlcL3`'-*<0"3017E^8~~~d>SCorgcw*Y^ӛgX[?uߢ]iq_r]\ Lפg-CSw$ߓIbLRUL->kEArTAW*BcONؚ'<2?,{  H:YA}TF| %fK1젲vA8E-Z)=H72S/dy>C &(1'fXP@vG Z=r *)җEwDaGKpr@RAWzy0(^0=Xr| ~aщi黁26Blh1kl1x('\埜:C' _y=){-k_x-6@uqq_v$NP6MlfU7jl=2rey::qa:͛02Q̶Bš_,U^E6A%o 1M L: L4JD{{6cB** Ld dgVRhiѺE*  AQSrB O8(1}&tlcn5@pԑպΡ\FΜLYQ`eIVMnЯ"R/XԂ\5WrخE@8'{qBK`ð{ >p@kHrsCS&ʪ |AW- l8tBs j <˞Uva#Ŧ{hw#G-JGI1GwPelCc'it7Mop )_޹̕mQ-/<7AZg &аm#ҹsty+sp>3Oq%!Gb>N0&.TCMd}fQCa`ҕ&ⷚK!V)LH5|܌Q"m=K@ˇ5UV 4̸윙utѹrsE90!5Rn6;((JRLN%I]|G>i-Z.ėAA.38NQpe)ѾY[ LdtV)5="X [Xt779HV%LIi0 Mq8SܡA1Z(~^%yi!Uȃ9<b2g<<'_{B<*cԹ]{>s[9bx=1MmP.]yG}Ts$$%^:8w=?X-:OOb\yM˽My 0 惄V \6V E-JA,|7_U*RMM!Ue%V6o4]NkđķLae,k^|HS ę`,$g {Js}ȯ!ysTd3N1EXuBet]a]aCa@v=UKp^yʎ}q^Xo.{D(,25Bd%fCa*پG+ RyrGubH}*Z蔑[pQVx̏x[o.iO;#_묣ܮn:wOo_pv'z]tfQ.l/?Cӯqro3{} tC8w߽^.ۣl΄,;}AwDV*ԃ d| 1Y=Q{5jx [zB!BTZAESa.ySIf ) ,0pI-gy싥>I)HiEP] Uұ2ݛO7ȲM|!%:fzs!pNsa*R+Cvt!yuU-j*xAz{e  7-L7 q:.;a&e4é#a4 N}Ķ 7d´28^!!'إ4/|n1>_6Z <~ ?}0Gy{/l#_z->56@R }{~ƕO-q_{ ~|G) FO~^aF#EX` i.pgA'Cא Jxi339[&ҠZi K,Y%>*"¼#m=9;jU>aP]E-N Zǔw6kt j1[0y ^e991zp:泜{,}m56`*` 7=P!Y?k 8F36%n1.3#4C<M &}~N3, 68sit´HRxM<0[Ƞ1Et1 lr9j,COs&LoO/]VEZ^5R9ؿ_e? χ<='֨%b@,sN}ay3k#0. M8UU$YOhj@_S20%@bPxyD A^$.[s# t`liΦzlbcK!#*LHQ͑"S4f.WV^yic1>|A[GZW8;m6 5Qf#.0z CWfV(}W9?64'$G YgJzc\+7☊abeHq1Cb7;h=č -1a}^AP) &dGq!~dnݎeƏ6~%x wGXq\Lw?䷇?ŏ\(E>䁷Hm6@Vw{?>}.O{2|}}ثre-&F-?M 9rWDv0]Lؖ}sQ2*I/~P/M< l@>LnPQuYedžl @ VD*X`r?˘zi 8ꎜBT|Df|ZG(SoB3rjId)EDhU i `A}7( erX!A/a!*Z/n(3M5zJeUiyߍ)=1uʳX$A.hIv {~3] Ϳ>'zG͝k@]w=O~s~/{O0tQ|~|;kZVcb k WY56,I.V!DՁ)&ESe@K|a(a`)!b*tYQ@DMܰ"̪9!DBW&bC:zN2t\R%yw Io8A=L~m#&K v,6մ`yto_@ZY((*2*E|lK"dLb,ЄK:ZNG9#{ HA5@AjdQ 5?-^k r8 {#hHGQ Pyt@-#F('N_G&WM\9 9g悜}XOwS'9FZ}^4B!w~2t0tg99%f,3z^ GNǨ|nN_(W39 U#aPT \ D+Uՠ>)ү/}Xz0THj@*'HseAK+ETK-4DsɃ^\TI )f(C+zG~ā'!fSb]̠ydF_B*S (,,8@)) #(cHJh05hPСV*1m95PPZ[,E* UMB5ǮL!Q&ך[*1X^ BV@F|.9›I~?xgH^ * 6afT^wӷKRm!Я &a K u u Ʊy|m|xnw7GluV4+fR/K pMFkh$()(( R&Ʀew;K) (*$Д^5g@[R mAa! HU=(k |$a IHS0Frk#)е28Qbυz!b"тE 1 FB:z*_IV@c.^T 9Ho>c#{ׇ`|1OVQ5RF'EU0Wk-Csj!5YAD!sL4/HֽMIUhltW[1iVEESsT& C-atlYqACEUvc.m&u8~!شuom))* ` P^ Rq5%*BXH'1 sv'π'XკQ'd ^&/;KsBBiҌsEd@K7|ž7!$4j~@U-`lQ J<Qo,wuHxB+ VeY8B˵ JQB *(f壄5VFYt1&Pbiajx킠UN@T&Zb!| 1i1y`&0X$zB΀xY.HxKzX:5Li1MAЂ*aVGKބ6 ڂ@.)lS_3r*3Y9t:Cw|:$ ~`L 2`ZBк=.A0sNcdT>ɻU\vs{;6㽹]_ZU(4$nHTR!ZW! #N,,y!CBDA8rkJHGm@BFh *6P:1Oq%VURIWͲ1:a-*/mBK=w SjjGl 9rx"0EP;L K@hs'b?C?*kfrT>WxlhGv;%V\[pygC_EVq7+9c q%!Я`6kWur!coWO0pK'voaU~cM1 Խ6(qBh LH_ 9Hte*.br9Py1QC!PJקU.BUaѢ*"ꁇ$#Т4ѷc@يe @ =z@veV"y<&I<6ɪm֠2l|(a@`S[U0*(wpK{P uri63 [FX!4Y@X#:He7LmH)Δw>0- yGי|ᕔJD\$ac9d #WS= r߬y MC_<8yt|j6]m33Tt}yqnID21. P2q}sl0$=X;d5 wZވrۈ;Ko&|Kmy BC_(4|`9m|. !*~םZ׎֮aD.?Qk>JWH<$ҨQQҨ(4o)0̰O'bf=ĬP.*ƫ0]%<|SD r=5+12it#BPD)Q&?:P])N(*Cǐ! fu# |7V.ɣ,Xoe!Z !*,q>Z U\> *1`פgbp%}ּA_,?e[cl'%_cYW)xNjZ+¨QQJS%\Ǣ֔jl N8S%JNum.fR ]"E^- \DTC$,-EF5V Ak< ss x6WL4ve8\(˴!4&G@10N4KANՋԏCl*Gu*Ko%ةf2R's\n\LiO+'X%hbeFYnpWb뤿wXsJy[­4>ʢW_b[@ )4v]5C޷9r񥴞vT7Xxs#..c):$ՑYIPHPPji&g7E1-PQY UhfЍ+H"Kb*+DM{aUENQDF"+`*+풋U`VIPx⨇"T\$G#K }LJ&|h/Zgx3%Cպ i}eV]E5.,Vy q\wL2s1jSyR]b++a{;.g{9"$nIR>VLx0|(/ ~3|øgZyQKk 3oԗ8}4E EDLHitUC*MD6IAS I3)$ Ts;,WzF* b#i " o13mB6.('@kyFqSʜ Pt 62++B߂v,a&J(ď||= bgʼnvkgF'" 29'/Iu!BOb"QW F%y5^k,^j~'@w"<(X}Dg,Mwk껃ˁ59t*/# ~S^\pIfʀǽ]/~H<+d)5ߪ78V[@BcUH1Ex!8H?961- i8awEZF [*+KG$b%jo5ep4D  QXP.6 2}6ڮ[ltkG@i\ DO:WRst1Ϩxa?R`00+Q}"Ez:γs7 C*+{"0҉ܳ`/ɍ 9j,$XES!ҼYc̠\Knd%: ==T!ίT`೗ydwaYlRN_xBKnOZQxe5uN -HR1JșWĈ%^пaut,t̋6A"A i!jN" EfTH*hM6N\`*UDQ)%RF'! "2#!o?BB0EmF483JxFK3#jk%zK~ jp _ia=\IE->i{PY_LW3/7R bm ADe}Ca$0=@y}PE28Q@FX / ݌TIx = t}Ut +Z4,N2I,=VyijbpaJIVZ(JK8pX_ٶϜ̓u2f0R ,A-3æP=! 4a.qE-&c`*QNp.ycDhcᓊD!`WcFWhT #ұIg eeNn%a?hF$<6ؒoz=-UHvJн"ɺDNƖRe*mxd6=4/ 2=C">A[}HFX˝R ZQ3O= Z4BJSNC_LN,ƻ'YUgWJh h 8M2x ?>ͦ070NCX2!53v#).zsp5ydCӇݺPgbi"\ c=Xa7 fiki Љ3&,=K-R5h9S{*XB7!OE+\ Xt aQL<YM 5E\ZDiN.QJH&V1n4@B8t5+S/etN3}.* A 6̐Iz~mœD)=cwQ1;e! ccj<39Й|s4Y, dX9BrswhG6zWpY8Φs{v ip:m&NeHV<#gMhJ m=؝ZWmqE_ ! !J vQCgQkfka,RȔhu/' p'Vf%G^k.Qλ6u+ϸ>Hm $Nu4xhtT+)jD,qNI*Go&߶s|A!2=J mM$Ӓ: r:.(`5&_h]|O!@ dz(G٣'9ggӘ9s==Z]ාpIFN); N- n315; y&isy>69@>>Y7a u˸"7,3IKbV5^2C9GXPz oIDAT@\- `ᾰs h9g9"f)ز [ #^ղ5R7@NVd76 93wܣO{.?Nmew ^h3m3w R9@j/dݿ乒C{;u|A?c2~Kr4υb" %t~=88Kpe=wiXM8OKXݿѴs&Uvbj։0%L2Nu} o`_ kl.S绉gW ̨D şDף5S"’- ՘Arm'hh;ch<8,*{u+s~ ؘ_!S*շK͖G{c֪$'h,d4x@7i(B/ Cwоֵ Q x[o?Ըr.bqYK LiZ 8}JDn : ڛ}X5 \.;M8rOv) O)TS>'rfx OLW< nQ*MC JdǎLminʾ[oi@X5Y'v\6=i;غe=]s-ec}V;/IT*()r$OE]\wR(enxogg~n<6%OAMk6C.={m ;/yC&z,aMvnkdL=coėIxO}M`L\qaC74"z7qjtzd3ɥabUhjW^7tG>֬YO>vձk/+/}l>KѭRuMBX÷4PO._sJw1咈8<{ϲC`_wi/=ΑŃ9*!8zȏ@J]M[?ggCK\E9ѷg>^񰳒v?M"E0\J%GѮEZjTᗆ n}{O<^Tعs'w}7O<;v hiiy9r.My>dZ#-pSwǹo!^K>fy\4xtly_ru 2C=ʚkQ(ʕ%&7}2?n ?ʥTN̾}~$J({|xgP!(PsXMnr~zOIRﲏ1]annx nv9~wwy' 7ѣGI|saޠA״@<|#`Ν?!7x#$wwQ\d2@,#HO~ Ї>7|G^W]u^x!֭)9pO? ׋kᦛnsǟx뭷};vbfٱcW_}5wy:<_v򖷰c4ccuS;w288?yٹs)O{]B8BWRkAR_8mC!   leHSc DF 97 RC - W1p8ӹy\y~7|Ub#@񽾼^zgg'oOOOX^^?Sof rfq8>:GTvJ(ˌb竚?恢W:~wR<>>5[NL&C__L!w:R)K^e~XjjjRT 竚@1xxx Hpss>cXr$ k]?LMMaٰZtwwt:ezzLX=J}Y,vwwy~~Z!|p8!>ކjR@ ED J-"bP h['''x^BfG M-ud21>>N<p~~N(baa58@{(KKKtttP(coo]T@3677ikkjr}}MT˅n'---L&k݆HE-ud2D"A4`=rycc0r?^ȯ ZB,b077"pFP₭-nooFEI7LŸtZZ2ɿ q5L紂644yw+д1(ED J-"bP hR@ZDĠ""1(A)ED 3,ੌIENDB`mpmath-1.1.0/doc/source/plots/kleinj.py000066400000000000000000000002001340375245600200340ustar00rootroot00000000000000# Klein J-function as function of the number-theoretic nome fp.cplot(lambda q: fp.kleinj(qbar=q), [-1,1], [-1,1], points=50000) mpmath-1.1.0/doc/source/plots/kleinj2.png000066400000000000000000001704331340375245600202720ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxM,[v[;"?Ϲg KHݖ'b% jĄ!r [ʞx`O`a -d*zs#>b֎Rܟ%dܽ*m^֟|'½)oږ'2pXX7^Ps\NI:I%vi@xzkw}/O~ߒ5OZC|= Jϓ?9hg_{ iڀ7?v)?}8c4)K.aE/}<Z#{1_\N1_zjtuգ^ _?S| z,,>B?^M-}Sԫyz]g**^nSYDR#5C즚Mg}S%˛!M ~α΋\8 S&x?ǫ}qEa>ݭW~J!6dPq?jQooâljڽ8d?o6F:#o>Z^{z/`x 3}A ۶K stq@y,qXozӯC70#9:$sb1I 7770WpubD޸@gdq<_i0⽄0'Œ@1 IWY`^e?}|Uu3R|i,c>)Rs17#Ͻ95#< w?x }ޗ$|x٠%Ǘțnz5gj"?ejq.:G]urG$\>>|Io.kJFmR% ?|?s^0'E EZ"AXa~Cf@:*2ECma:ׁ&̧hMcp* 7*%&L^fm_V|*K,yE@fQ2$yh9>/jӒ@"m;I1M_vrMT%@W6usIj+]kBb^[¼nc`;y>h*)lṠθL.1?m+7=תmZ5 ܪ8@ؓo7$@ _}N5~`ET^[(5urR~WJL7!W1OTY*l׍c>7IUVN |gHCH #UALYnmP&bIщgC[J|4 HL"=_VoIC~j_'Ej,57xnz$d_N|o>{ǿ7fϱl_ 䭣tHVF=]nMX"3@Y TJik׊4@_z1BBDu:!8InM\NeWXs V Q(?|FHkXg[kwr٤[+V- [t*9~__տ:{~+տZ~rΎش;.!pKE5;l/tJytaf1]nmo2U\ !{| ]tDԃT_V_/7kԇ^Pi2@1F$%֋|74褕HIOg6'b~5ygq-w/ )?vǿXASTa֙D77i7nbLdOEЃ)FZ:rQGպ7K&ö]uOg7 ԃUfs)cy,-Ƃ~R:3}dRpI-5 ۨ#5tu*_qw{C")}|欿%=ѺEuy=rGuNH(05,{T'eB}K^K8<&8qJj/p+O4ISk4󥯝sz-ĘJd:Ɯꙩ`Wpc{Ųa&Ff.l*ޜm712ǻڇbA~1WgH UBIBw?~.h=ŗ*ЧӉ|[ ~G~w?G?G8mggYSv-Q9ӀB@TKrdaՃN9b? D=@87sQ[7_5PdnQ~}ț{XKЩ8C-Y2AG s/IqB9^H~3~]Nu_z,1m/%bq/?lxSϗg=ӷG>#)T>/GOqgV/Go8:5zVn -Ţ"2Vג`\m:jdzLL^OJ3"7yI+Tݬ8b+[zsbEys雴F׬H_yRNXJ3XfLWN0lo K֩JNEBIYW"m+-'Ky: nZ y#8u"@s'ԞiY8*L5YJp mjjZ)^(eM*c%vMZESW0E[n i4?0+0zP<`ivR⹧Hx2sf))k+ctY{߇PO^#pǽC |K,ixvu.n9-?igA&:`gVŵ$M^sHMHCyc]Tbm15 ~H/:$ZSe̗݄vqZ"_e(#Zii;bI+5g㸅BN(^5\yx-bZ13Yl8J}e@t |i .;-&iA,a&%zWjs%2izq+ , JG .vyxۣwQiaHbͺjq^{QSUKˎ$E5DBLբ7p^ X:ye%?iJgZL1#fMqo%E5gSÒŦjs$tyR\D0WmV+5 9Ц:&Ȫlhz[{ߟ('eYTnnΪҘ9gՠYI,fv-}€I"sG=uwK6" ȒKbv3&.+(Iz-:KN]qҕfU aI #:a>hdᵂ1KW3x{vk)㈣)˄U+ĦJ+ۯ|5!N퀬MCqdD*N3%)yL*dgPZSbDz(XhBA)Evё[X䝔~ezĹ'7ҒԦ9Ar/5? 4V,DdΐF'1_wpu aK #6aPdqw-`LDz:+̒IB/[v:urB%1b()-B;%je< ׷y~ e9 f\ls`]\MTʔ_Wo9銸 ,WrA,:Fh$Tb1jpo H1M< Sh#5ӄ(gH,P<҇r%ÌTskf?ti\ ]U+q-`l-r]C7q5V%2Eyt4i;m/9ϵ|ɐ.b x(O;<-PXx-%w ҁaYw ;ibW9O3e_6*r[āBp+QCҁ Ԧm!n>]LaăkQ(sDG: σ#uԈXCR/`|//)P.l(>Hٙ7DcYF,-FqS5$n&mux6G,#Y4$wZ S G4Q8k0]H!f!!63. + 7#ynXT~gAG^6GfV7JB1c_#8>; % 6&VJb!? 5]]/ coLǬx:k+}1cvs zLi L[IM|$AVhz+xPiv5nx>Mw@ :ƤuqШ /l^n}d20;( :9M'W&B*QvXH(b!aۣ{N G.Fb`z SJ,Ȃ>Z NNjS9a.6)oWW/V8$ESb%[n.σ63bק8'3b^dDZ-b]j1-q 'Ķ7zs:D}W*T6ZqxmII`=5*vMK[wU?9~~ Țά$ F]qh{C(f`b%JmNSHHMh bbºj~Q/F+X5zhi@$hDFc))&=!i1`q;%c{#hy.%.`{}J Ub}=XO0c:9FP>Kӊfh5U*J?-U2|'ے;%I-}^x=yC[іV$ƈM-&9̗HJ91OUR HX)DO*MKg oo_( ` o:&n_3䰉.zkzpb1' Zq KئFV bk DnDpc" ۋY4 (DPv|C˙lb;4읎l|86I~Hb.r䘄pZI"-!oy+:-Iˆuw_N"a:U1R <_u0ӻ -SB =džV[6M&b~R24O+D|%&pe#ߑە@W)ǹ7}o ~~o|Ǒ3ۏtnmZz^8M(muBZ`CbK,*2&艗g:8愕J &VWdQ0*QM*l9,+KmCW}~u猭m6wP*lF=tVQC0@ttsb6JmhzE{AzWD78F(2T.Zr/4 czjݫ}t9ت&dOyJvbbaPN!S&=$i ̇ cWgA[)tuWG?<C>#:O?v>H$m)BѰ,AaP7lt \:!o#3bJ>h8p4瞆1tSr|! ʝ%,8j`%ira(ejA/9 [y;eM%I Ӿ FŲ8Ir̘GHxO1k Ɗ%$C2i:ޥr)g8q3qT"\F[62-Ҡ1]$9)Zn'|ň nϹ޸RJEé@Nw+_m[¿}K^Oړ[N{s!q[[Ta.8lH@@ԉXdƸi[s1)d,+H i\P,ifݚƃM%`4n#mֈEbkUœp`ŢW:`Kr$&^ 55~lLMt_sGHdx^9w%}yFZZIe1fbAqOn{9LR rc2t?\Pm<0Nٽ uխB!8:ߙrk8ƞ\"ʁY0LIE$tq}(cUEG/17ZWp@^$SG=uSKna QSLoPXG}mFGf}n/m&bH`TS-s;uϛ$ľ$d\I#;nůђSbxf[2!J-ք+jx IDATv%an&fcé1]z/m+o60\Y2EܾWTB߸0PgBRs7B'Aq,Ίw@3&8Xd&>:|DZ_ky~Һ*$7Ko(3 `8Pd̃!D &:捓H "Sj:eVv[8 b.%SbY4\,p0eKE7l`V&&Mxܧb1X4"}F`"ԛ7ŃS"%9%xozK q)1*>Fg"N|oƱx0At;[).%aqWzd[ƖpsB-WQg$Ua>ZO| &,# A$$76$Q} +i]-gvt V2Xhdd+u[,:lUc pQ|"p} L֬/ iDac0yx.fQ$Q>p^C,!j%aErB+@z(XWQKr1`.݅yJ8Qr¦NS]%ńmq:1 %c8x3Sc19O&$bOJ1.Nm5 uF f>u⹜AsH8.s0NX2xY|G A( *HxB^$pFwlmE q iN:;rdjni$p2ƒ/D1VFqHD޸Ф3hiI%wt4%xo:΍κc:-pۅϠ<"mѱy+ m렻(  9fd1b!(q^%$ p1wW IJCQȳ|b{I3ӄpwuay&=By9IoP1`Sܓ ғN*F#iHJvh9Z_% Fkk]'b1ü˂!ұq`8J&EE?)B?489袳XKA>Ri%qV x+Zn6loU`-[Y)Iا7xT-Fkg08R߹NHVv&D@l`O%hfҤA'r.h&Y@"Ƶ%jsӺ́:#QtJ:\*qvnB,]t;/QCrC" E&5<.6Z )>HL4mۗ,5iHXoǵ=;]$nr;Kd\\]*{s{#֍FvgSimp0@h›hvѹXT}Q 8f7 'xˢ%( w|UGw(,sQRR @|yR"b|;yטĨ9ZJsX񦼨1!&lv5^x1[ݳñNz2%٤DmyvJF|=R 4V+Dk*z/Qa?xu"ҩ'8[J))ѕR"R7ЉQ+q&zpqVZ<9XoM t1:=^:K)qc8sV+<F٫oϥ4`F8O\%ccO*.c|ڨEJ,>\\zrL$3FQaYȞ65s n"q {kw\q6Q]pm{@ 8 4>"\2K'{HU-7 ^lFcy.FxM:8b:v3XxFȅ+BE^]4, P>|2E\eM_<԰؄8;p8`;Vg`L=A=>'ȍzW_b;kMIX!& ĞϛsU\5p\$8=sV^jt۸ MTB!s Nc3eIly2!n*+HĽa(';a܌J" N%'AtT^q5Mc8@(TXo2q70 0q.%>e{= Kspis'=[ T8(PAs>+9ͩ"]EcBĮN0f Wb^󼈳R !QTJk½촉gCzWE#ulggyʾ 1ழ]pDSuY2T*F=Th  t\x•SSR 0QbIDt\98^R hĹSvQ$)8G:84A#ppB;J$٩|U$DVsd,yDEZ'n.vg9UQ!aNfEǘb[hcF>Dx=u!1v7'иJGF9hv$0ut[aNtVȷM"1H(,[q9l5Hœ6&>'.f{3ϯE]Lmϫ!)ԄFngCc6=BL9G,x.11H& X jZcu/&n.9Ju$\Hq \oc^- AnsOwl3r⢯=k!uvA,BAG`)z v)t?(n &+Ilu6=\tеPA((M7^mG=]i:O+pEt湶BɷLՉM1I58htE~ks 8991]oOvl8r )걻hL wJR\a|Zpl|YIr1sJRM|rB$'QNޡ{/Yo{[mǑ__^߉b9VU)C$qO^rI)QA "=g˞:x:psb{Ng\rkjsl*θŽ\#ʦ"1~<+ GY{ĸ6+Y4Z7aސ}0$azrrϕ+^ìmLэcrLqq bslotᄃM&` 񤌩b.N "K](ʩ_ZF%!VPOR6x3S+Cм/V&crcMl\a؀!< #GM4&ƈs<{v{s2dƀyJWg9Ӻk1Awy|8gIC|Cc@$'Èr}8q#?#?_qW7-~HGBu,eJuj93ras G.!>tț0 9ľ9Q(ZQeq"q|UDGZy:5z} ,V7F[)Yfr]bwJs>dOQG]GS\4 ĊED2^xT8<"Xē}4)405`~a(Tk9ss`Dy;FMip'x"}ԑsI[`>FkgPCxCϿz@y~_@ߺOO^9~ϕ H Dcn)PN>ગЗVg\t&>i)PTAyQF^tv=zK ș}ypI<<K)}8rsn}cөz5]UKRD1?1y#'F#s9 hNn'\sfVc+sܟ3%4bZGsu< o_m_m7wG k_sisqNJJDŽ-EJ{T!GtѡCGMO]_ 1KjwۮƱ YrpS 0O (3rtq/Dn 줵dFF= O*/^{+h/A}i 8RqK ;[GH@8E̍jIhO#Uvl8FiOX )m0߻[x@_$gA^/{Jp0r3'`u"߈dqZTu20^xs h2t1'᠏Q呀󈾌F_%`> o<zgy fo.74m6: %̗~,D mkɈsk C&`ۊfxQs6n[ >`&V.F}" < L{^#\ Nۄyax* 1n[TBdE`^I5E8Kxć)P\%o>q? hv}Q#}g!N#W4 o`|<0>pa̶x(o<;F(UFw({Tv&tcSluq]@ g$P8KmZnN`t4pN3MR#Cۚ_=JgbR|g7<#=#vlAOJ>{ q< YLpI И 071f8xA )#$h;x.SCRmR* ٌ@apU/_u> &'w]y' F9j KƆ.㮲}qddp'1 E<^p? 4"IKpz.x*4[t*Gޠ}yv';oތ ҿyܳ<ص4(Nxo4_ E-;K!6X$($9cptt;9\q[ce1|20Q? oy=q4I=qlG޶8 {{'{p<+e瀗I;T7 E3l089]#}>bnlv[ MyE30N2.%D~a1cFF=2_*W+eEz 6o`$3~4K `?'^s7ϡ_N/'A{cS>{m.xtazQA, ^/G#=蜷I Ig_.m@dm\jbғPom(I42%bzKGjgN8]c|>1Ό{}O{F7tvl܅ǭfCC,ݖQJh JB"~Q%!9 *&qւe&oHZDb*<6 UkP|2#W"M<pGc7:s}aO(QNh΁**r2퐒 S#%D')&~}7h |$+pWdHƟ IDAT|M%H<}SD\˱Mf:uV,|y1>'Sٵ0sLhe(oa/GLt՗Sd+@vVO2rÔYpWSpY0݉A>{ 1| o呖GqrD#xGDac(Zi"J _D9/sq&6V VrsAJҤe  SPb191j8!. K [_cexR>vƝlH?fH#88Gìl"޵PEBqJa:l ( s cB9d61f}ic3}\{ x~=) g>VJgq{MB3 #FF74k̿eOǜxˁ#{ٙek 6`Dڴd KٖM'e*o5T{E*en񆖁AQI Wps.]]4,.^ځ=-swt 0x3ر0}aOA[="I8:$q63bć)m{"y>w~'6PxWN}^;K Yx\8;5ϡ ca6/lg?j峮[8!z1?6h8Hˑ=.I%7K!mgGD8hNl `Q0bۂ4A.pӐ0N%<^" )x Cam77.~G54j,{7Q\ĺȆ8$NK ESB \3ғJ.̠,[`9xtG3b0wM(#>Z|]o{#Zb~aD$q*(֜, IW|-S491ѣGp "O`({t(//"rE4"prKvG<ޙ?{33T>f87gv. 1Sx0y=v-4<Т8ID6uI((B@oHה-F,btpqtpw  U/1q/ߗ(' a9;ap{|7{|s@zl]x?лO" KļwJ#>u ?bqQ4cj2)!:ab,!FN3gJ<~;4|>D3r9;C7 2_+/RpNؾĄW?onowOGe?OSKwvh1<7 ;b_8V%9aN<'?ooۿ 'Hl4 ʦx GBb<:xCYtMpkǘ5`Y"q?IXuAGts.4Ÿq?Wj"x:96 0a\$%<[CO[رB\δ(p)!i̝ +I1M{ |t1oø(SRFHuL9G1#64\H✙x^LQ<}k/o}[|g~gɟwӉ۷|'|兿7&_W?Cor<jBb?Tco@}yq Sޏ%ɅOP?g2>7-csHT#>@9#|G+ 3 g?d9 Ĺɤ}> ݉%p}iepgb 颃v?繸Zf } P1/__}۷dYbOs:U sU'Ty\)< CLHa 4Akd&_Q{HG;y<^kLij!ll"l6.8{}T$=U1F\\ȃ00 q;Č:5 X2wgpUcnϾ@6C!ѹ(gH a_>"_:uy Q`^C7SfWHmm96rm`D{|;\0ǼˍZl 8 (oS02,@@<7q~V..\&îb k it h6ȗȗ٦DPB ՞MedRN qFaٵYd|ȉY @vsIH,{<y):~> {O/K_]7|7|c[[;~'~ӟ b|,J6' 3Eznp ]yĹcpi+xj'2; 9| )+93^6 nu䴍.GX8~93FXΎ 1G:Mߏ&???y/G?E;/~5W'S?S|sϭsy\16|ny@\Lй> +0 و <)<N ؅6N!_AAҕ4wOW@Փp>"{9ƚl8ՙw uc^E:+Hvk˪ȑgN"vTlFiB6^:#Hm-bTz!&`a*\й !uyT x>V9E ypFr@|^iI#Ԩ 4!5pǔy~c^Mffa]Dc~iyyA08oZ:!ב@YZ̵;E]@ycwac kyǀ>,|D"wb¤ S@ ue<x^-͐8qXyH&ν@ŹFv|.c:#kƯou?C?|哟$????/~~nup ,<~lb&+,s6]<a'Kt梡WanA=ûBxOw$-W@ԏ b1ґUuUmխM4XGd$EudNh#1H :iCc$MZ$hz^Q_BM)Eǘ\8TbcRxǠ1'5yo/Lg㻿{f{@ C]#hth ƹ" x3#ʣ£ MtzkT].Ay v=WD^InjuzGh"X8_P1 󣙑qX}8|b8nqL~l}'5^r?)D817Q[{rp".Ї3nBA ;mTרXGapS‰+6=i28"f,$"+BHYDll'M Soqs#1CeA=D!pa~ cw:zcc]ЭGav%r{i#1aK(,Ml!t`ƂSj`Zt*\\ŕW~xM= BjbCKI^SE}&Hi@'V sب <׎gLTHu#r5s(, trfd=B6v Ј$usa.S7#K i"T ӓ|,EPki:$z8綺04oo} HJ{.m_n17wN';;ߡ_HوpAnk|nmjAQoP7[N;:4p'%G5vWL!Cc%8%K{Țaj#6y7)*!V @&?O TNAhdb;d A{A"!mN3;2;:R2Qs+Lr:&Bqw b{)Ώ BaNȍڠJ-mTOCui˱zc>i`ژ+NIHeJp|يwLXXSL@;P.[b֌:?s =fd[=׎ A\; c"Bxf'ܨ֎,(X/b.0?-`plFbLj"DIP;a* 듋q,oy0L% /ɘgg)ęT5:p s GKf-g† IDATK"bW0΄bGB!H-HuG˝nHo~OopLp)tiE[95ój\0/HHBJb?Mk0bO 9~ZY:4")Q[qF7RNb"\TغHo6*$JK-&97#[np';-3ZOs?5\n:#:RZ=40$!MBjsrR5`~z*3Y ,;fZ.pqEq1M9vnFz̽0!5p--wC1#ҜV² %zQxA^^m#BuZqTҚTUP lqA,݄w% l__\.-_K85. ,v٪H$1+{hŽU( .sgAZLΉKaps! `=FN95Hv;Ճ`L'&s%( tX [unb LC4- :.}q(X).*.,\i(a.b߁jݧ+=Z|'J/ηt4zOGpNgGBiL&./1lZQ:c,Dh -=^gg|๛QAJw2`N|e"o >vxw$,N½wu,Ld:]˨S_P "}JB:|ɹ]" MgqqoC"zQo{=>0kh}h$` YW%י š:d4 ‚B.z".cF);Y9wjB:S6n+Zz'NKv\qԓ LU_Na5 }A҅9M+I7tHVrs2{q} B`A[:E-޶\?t0V|qGa~,c (/0/v' <(Rjys.=iXse`"7Ua^"JN!PKmKM"⨼kM3Q6¸t߾+:y3YՎ %4|]xs=F ~O̡cF?OKK#֋VZZbvgPYE}6 ;B`ww"NDPm{g8 h1=9`m#i1V.SE|:a\)@A#&/wQ}X:&l.sǽ`́ʔč9g1{\uC[rOŹ``O8X2Q0φ*Ԏy,Qi!>0 FlH&& a89ἁ)@Dټsg> A{ut䈻 j  kDHH[ZӅdX<eL83 ??A|i{I@o$-V՟9q`B!X{Iڈ۾N=igᦅWwjaFfQ9qun -gߦA(UHw1:!VXCC{ۢT&s I'~Xyk82Z po=qF/r7osF I99W^#mn^0pq67S-\ߊx~[[sv0?RBD\(4K$v^ u 2R:cj䤽ssי6 !sԲ(nVΚ\^ w!)o' s#p {KAT#*';qQ>!|2Gkx{.<'ZǜTiHR!0KUYOp9\GK㓟$! _+E+#s'ɜ@DEz%czzˆyymD|&C|zC-^JK͙g2gTZvOo8bDV'o!'!ǎUz@cE "J""~zI^C뢇@N݋K],qǢUH8*'8 wҾ!0("dJ{7s"Уn{Q8':]}!GK'VE("Ww#u=c`\*$T#Ӏy&mԞg7 '07"8#I<-3q-#%5kd\}J0[x^|0YA,x]:JOX]`/8OTj[qf vb&ThC蠿;K uuK!jni[ TEmUZ[8/G7HG̎ Z+Zw͕" i;+`wh#~ԉ<eu8nB.mΈ.9p]@&TS{vgW /IxɎLjNlRE<}+''!<H,"y2Srj )XyunXvz\DRnH#/0y6NQ8XtݛIUoB~1T+]Bx#tB89k< %TīDʵ۾E]<6!> EC ?$`knʼnlڅ:#n &IĹ9 IyE,w*\ $d=Tҡt0ʠQ:4wrяe'fnA!TFB H3 2q֤ 2vFڠR[q,NΟwoq9hn:ӊrNjTrC]B{<G\0F?) Ny嘗N(tjv̹||p8 5cAh NyaL/W~W10x},,8#$ޜZHV3F'> w wWٶVظ0#wGד$U'vggW-kȩQHehUפ.Y;i'oΝ h} e}q(gcq$T\3_۹~ (ۤIoyhnj.b+- :%G|i)w)Y\{G9qɻQAtN"^83` 89rƉ%.EhU" йP 7HD6a~ޫcd&> 7AK/0W/1zcbxөfJǍ;g9#̓$9qyhW7.YAta.Ezx.7/kוW__O|Kq.Z>*%'K(57\htKd[!g)}YNlSN+!{g1 g7Nx4IbgKD$[HEIT9vD^_Mo[kpv)У : t_Ө(j#gH,[/z uUȳ œ^0f'd,dp$hCEVpD br̟#ьTě%4<{4JF;f'f.Ht@)׎u/ԢȮ1')rJu߆yxYx- 򷰈C\݈R#9l c.Vk"ruHctqUM\.]$u. nzgF$ǝ{]y|糟,__]gЗ΢rv@EHFN(K9N q~VY`Mecr]SDvdݚ@j7Q~q;BvPυ؈_oA*5j+9Ltjo5zBl# |*qn3PCQtsTZ(mzDA}8< 7zJl @/'$X~Pls:5PMw4EV&,~c8ORXx. ܡ7"N~*va2!:œEJ=wv$ϓ+9\裦Q8NtOt|M{]y};y||sϧ,=me[Hr*(͝Zrj < ӣ 6vJ zѸ*mȲc9:3Uھ(Xa-:" hD"҉z\jUMlPV-"B"݉ egʋi;LǾa^#" 5h'& UF؂Z"~%Ԍ;99X}y{!Ή1_q,4Y"}`Bgcwmiĺ/P.fm:?.%e42|8? " ^`X J#{ -M2yye8FwB@MviyĹ q̏"kQiiCx6CZ1/⿾{`>*W*u~ OOOoşM_0w)qu(tDe 9 &.8A*qouPQ 3!o :jʫ&8b' H#vbLBv bM.Εx- gd'o%'qӓ8-oM(..]';7ؙᔯWj'{2v.,! F ++Z{ $Ej7nEѝоTP |wr0FC_$B#Ij$ 9r^ Ǝ:j\]gxr66>agshܧg%Jt, 2,{"]oiuk-Ō\:y7U }a,Cw,@mo!r=}aHb"N}n3Y󂹍%@hϾc,"T|O|t ˟P]y}`HU۸.284e,霰,] Y!nrTIʱ\r&7W!QEG'$>%G$NjPssU9`ھ 0h"]ܜo0Ċ#YVıpg.l:L=[Cb<+}s< Oԑi5["K bX5JEV \'/+Cq\ؠ#M̻=8J&.НrI1ڢD™*R5:M FF$ṿc~;;޹t.Bq/#Eo`,W'] !Zcܸ8a<}]x%>;C>Q98/c~Q0yJԓw+H))"mX LH[wζ9$=֭&TŦ W򈣟p7׷|d B!rE8Tlr;%\B;]fXDb j9C"Уr' v:k6i~#/#$Ѥ"&ğ(SG!.f3\E'PItt.70hs. g\pl裥,݊* WP\Wk1ߠ1 OgǕ0skpσPFy=X;ֵ ρhf}El m$XtLfAǕ+V6Js(JZ8/=݊9f] [آs 2/i1GF928邷a4`; 椓uL@ožٳ ̿q~E,T=q.pjz0qfm\9gzV1l >#.K58"zB 4AKdOw? :R-u/FlIl\0\8&5&l!%+94sR Մ""WvJغ0ob#Ծ k`9 S=13g[,HXa5[S9{A^{/x!t,ΉIIDSۺ@ILdpYf$pL"'g-a.1eQTf1" yJ]/n> *l>9 1)ԧgՃt\:s}e*m>7ׁ4Hj{źy [ȝM*?Nt-_8އWN\rNNMzq^tk"[$_8#-,sѽ X(2ºX6L+QG' :r-;ۊ@aN{S@s9%sdLLcq<#-R1#2#ʌ&YE<s~YjpIDu'&Tj]KAU3T7ל ?!qeм6[6jeѳ8fr/Z IDAT] X%H:Gfy6 u/fgb⢺tѭú`nף'8$ęLLbb&/a ltX…yܵ@ f33ĕn!o=ot"g =旜S"WH=hO^:VNd\&YMf4dϵu\Ho{G!Dvh۠0-\ [<<vXq0#7ב&&DvlỈ#3W7s_D9Iv'eo.o!Qɜs vBةa-3Q<3ZRfzv'4?8w.>n#adGSIHh0WW U c õ;PFߏ1 ';j7D]Ŭ=AvD|baJ@JaGf$:5mKr~<c:rTN\f:HkW\gy~ C=lKx^"GcnM$yEq$yy'i1C6%k; ߏWqoa899Sw \: 'n{ȏ! l$$m !gDA.:rJj &mQ~G"s8iOsbqH**5}2Iv$43(^|]q"at-$&]eN`Nsq{+ bR3=XȀP gp+T7Ĺi-ЮߙI7\ᬨc.#(}Q }Bo 4zaL\$*´+#{;|F{lfHsC߂EuKqPn苡N:՜1kaz?,x_ee{,G4H.zeٚ0C~%u\xNasy@DobH}vq똻H쉲X/͈ B F5mJ%s2m0,IڅvT}4&w־2ŁcBpȠ*[ŜȶUZEv mE 7 ]bv[&F5YN=aRBk[@[Q}QT2sA {%ZRB?¸ S1@vH,?絺!q?b"{zXOI4=c_)՞%;aKg1SUT7[rcO@L؋A|  W%b*$$l\X;8рxq#-~ʿtmrWdN^{ܛ8[X8 gС$r D":!ntNZH; h~0q ဦF,~ȐM3FZ` PDgΐ<0meUmZSNz6nBrɉH+o#')a6\@Q 3jXEmz9YgdS xn%t"y,YM 4|ĖV5xaW͉N@gS{̋vy![V[5/1HzCG=1LY.rhGB1c>3eF8E^]NG_&ejLɌve?ܧ^\xT8dtuqΖ\h:;TNrS<#4#/uu}C>IQ8%NOr0 W 栣Š)ʌՄc ŵ0`)ڻ'+ #ȯAatB*JL(bʙ^aUΊVؔC^r1A+ V|v$h 3lZD ,:4Hjā(GB9. nn#hоkH4ns̢Ӊu+3=YDf|Q3Z`H(ˡEV>JE/Y"v -=RDZuzM,,/#,s 1<˔l0aZ&saj-|T[3ϐ 4*E`bFl pT0?FFTdDO9h\Ḟy@ (;"A(δ̽Hi|xW<J i<:L+i Dzt<9ybϑfU4C9qOB HoM8P!6ǐ='1h1_>|B1^Evb_eBa>/'y<?_F?gLq+0#'5ujq >%8.w8! LM@uTX\*" PAB)1䘘o`ɇXR(eY~=2, ^q"+D Y2s~T!utҡtA'%]mc4hy|`H>.v-Qx0z@"yw{EG/Ev7t<1v %S ~)Zy;;TUşٟ=. Wmd&!;C:f8(9p1{ppadI@&$Xq~ͶuL>ˤ Rie{Ɍ!)"/M~   OqMaf.zeh +rP(yLB! bFRߕ%Y듀ZC_<J2FG#ĄN+huKIT2!>zaqqc*=Zx.cLsy=q) m1[W6TC2c k[퇢`&O<Zvs [$8ϑz ՊqD % ӡa LZO$?'Ͽ@Woo77DUqAz= JM6'~v^\1ĸ(KDiĦ&l`\jd5ڊBF=L3qfaacKP6ں{ w!MZqyT"EF3A;[4n!]4 %0 +T#ѯJd+= ЪF&9Q4c{-1`.^iC$Qfi( K7:WTii7`LҊ557a0wC!s9N1cHyŋUCLn1c"D*&*L"lv/ XmUDkvy`/7+^11/D^ 4Dl +7*X 􌄰oP]@vipg$bTZUYh]3K!M<<7-<ڭŻL0m4!yŽCP B-#~VS of\d$D?b~-S2 mQmd7P8Y+~p}~ 1H._B!ԃ F"dFhYF& KS66Z`ubs#ׅP9Q1El2:E DLsM"q}q5d<5*4Ff"DO ɷ4$’sJWhc"cFBYc,݀Gl@600K.ʓF+SVŢE>yCfFfҙF0?scv۬)WRs<ڕκbS s23!ƨ.!j i*@P1;.E0*=#3B n*#J&joELA֘(lX0V)+)`)V03G7!xޔ SԜAnbkN5y2pH -`.уc([0(HOԞ%|<4h}~UY+oo|.KX_{MBsV+Ąi9L|o XBBmH!3yJ+S,pDY&{/q-q3ٸ137 RS"hS $;mS8e e~6 9ЊyS!l 7`kdӹo؝HFPIhmH.Ds! xM{,LGr3 5>m-gs$O]XkpMsq^l hjF3b2'n͌MHRc|AfCq8::oluK@1z0#dBkyLWVK\)KUQ02!QYd0n6H0Lv@+*H#8ρMrt )B!E =0̘ u{#`j[dT=b16߯"䓻`Dj#:* Pu70,VypED2)~o"0LMbfT0剱85r( Kp_:yVI`V_ ?_,¡QC 8 sd ]kCHs1'#2 К̶9_Ŵ+ ~_JNBNPc^076G#Ѧά4qia(VpgGbFEfF(7{wk8(" 9'@<&sM0ka[uA8*G!pfbC>>qV10&}4E+bQaV" L ({)y̅.$pnʹ*1b޳扐{̯94II+sȹ4|(-$RCYt L6V*²` º`~#PS) k1f$T {.[-@YO0XV'pgfda/s]|IŊ xsP0?xx6f0Lm1壑<&4WXPBsә|Zx>r}GaTÔyEZ7Ȱ-c ȴ Z7*d_Kdlq[l}u0@-"urqFc) ˜|i5+*,^QؒmM;gmOǜy_\nn0^Yy Y31pG2)ȉ2g7f,pǮ) q:V9Il5R}(DBB!UR W;U`^cD4+[$B-ƶrdc[e\Zډąլbe 6x}DSvkrڞ0<I7p]k0l I }+>( <ad-A.M~ &B+ B.a$hr:P$*ҋb:"P,{i:'\4Z* "$yY3bn [Wl(F105ӘW +:M19z~A[|<^&A$#7VZ|sHXK\ɔHJ(_{&\τHKhOhYp]Ѯ}pj1;xnweͻJz%+r/_ȧ0  fI[Ð`=N%HQHB,BF R&1.!5A^4ZnrU>7b^KFZ"Pk5B"&l$Z0z.RE:%v99=?~y1 ۵q:ۋEe{'%ߎҢ;Pnм3rKf8A85#i GuuPt  SZ6xDg#Q*K~^6Q[H֟c:W|n+6LsQڨt|Kcx~bd1L`yr)]ּ <+Vˉe-缀8'ls%8J˂y+'FG/65sWX1MRVTh/zWo?IsHa ˦1?^9zHt?%`oUk^ۙ|QcvժX6R6FcO7XŒ*atU#:W48qqpBwC# uX|db ̸$si4t6G@Q7 ff̶d[9Cl ОY; Լ˚Gx|*~BHnM>6l>LFb IDATKj"ͺr _;R׶ X,b$ON-AM=x؈.w€c>RXT9Sc5ecoǺm\]k\r0| >#?YW[,*[][xpv@Xo4J"1X:Ͻ7ݼr}/\b6! AkԵbt< ~AZ{'T]A$-$dF0ȁ3? W*͈t,9`u̥ABLT|]sq7ɽc^ *N ނJq==/b9qK{BeHy@` l:NRѡ"JXaie=Komȸ$Hl`:(ola)]}ϯ6 cs/Fƾ!qiBRіT eP<Ü0s`M5޷tM k*-4 1/cm;h% QBn !PD "ʰ2d@d\Zy E c!aA!`՗0a) ii!&KUïeJ{XJHNPx`E$a.P,8'EC1[Ɗ`*rsUf$ J1*W"1 1|@g[C0Th0ײFSJɎ-~0n{V̐s< Ԃ1V\E}#<49=}ǯ'WcGOfsb;bPS0'a6CsC}dNq,TE}o.SelB[rB X h)Ƅ 59U.`!\u *_wG^y܏*ymI;CS1xHXeL{ߴ>lמ wZ, HHV&-HMm 4L2-N1eΔ 楝|)NjNC^w )Y#ec$Kv aY Vi<Сd&TT=4`׎yP07Ȉ{H*G>ZulއǯD3½Z$%!fH@'44Lg)s&,)挛CXqNsntH7t s0hx>e+ @T|$aVl"y^%ĥc e<@mY{`1`]*ycnxѯ?{ ;d([[s@IAEOʫaAżɄ0T.`sBpH|WxU)7_<1/ -(U!1vV 2ʩV@ aai _F6 ְZ \.aC2r$Dx}xνO٭Ɔ6%09d΂ >t`kG&2e ҡlQ= 43OaH^W|ꣶY\,1͡%1T2Z,/̧-!Wmʨ|fj%LW7ư~vX`9b} Mg X DR'`ۧ4:R.Uc&sej529`΂ef"L$ 撈DZۊ[HC*ed.vRŃ-T 1ρ= HmHWsZ"Ek5/׭RlL&*~Do4q x[ ф)5|2As/mfxlZzN&h*ex0Z<G_R>h F JZRS|:wkLMKԂ"'],\˘x#=!@Cd“cܴ5G_eu3#s30v9S֤+p⽶2)k$)yp% t<wyhّw@qS! BZ~lNkjl#Y9n踨cMt9)7!I͊2?~̓; [&";KD*צ5"S滰`X.Ӂƶ3B=%T52(yLv l󡎹^8x^\4uZ0ݚc <0Y7էʿ_S4昧g57%M`qkO̍)tz/nc$=p^JB%"X<C9B-1KUʣݟ6^K{PLb:M^a/LF(9k hҰP:4 )"ŝ`XYF̆K|RhW7\mo0W[^ZW8do-dg6. S&gBT) \ex(S+I#ȴ%lhhɣJSӬuLs|Z,F;T(;YVl M%RbEcLR$ V[`$2[.W.g4˷׬w䣁[pcN>9Y.xt2̈[# 'zK8F}+e]sn᳘fH Nv2b.`A{\ZrڂyknhE^Sv9r d6vF>f)rV}8{kM׼L5|gq:̜.;<4bL~a(sRHsݪ@.9D"K A k$ A2P ~ ձ푽`(-V)?(pXfGViA6l2-b=b 5òsrMkf"ٔLf`ˆgx@% .>o>ĿXNwjf{eg9DE }F{KєQ"ҀL:d)bF{/& =';:q?]"3F(-ţx4t%tɷ̶K6Zp׶0){p&ӳe#Y|ʻ$ 1p~RioW9ذns2!3qτ]az a6#!ɱQ1/VdT&7 C&)v6v(W TElon(K.x [L6dq/_㹚*\35xˆ|.>Oũwwk<<_=;f  s߅)Ă^ǼHwר+F\Iqg0\DY_\zGZT50WeÊf-蚬+l1v K bctdC9P{/^"~Iz=N**6gb҈ x iW=L1`f dLa& FFu(`kG.? hl\5 ̉bbEZBlU0%KR n<'»7VmgH zg?8)ɷ1.ӂ2d m @ Wb92⊨p(qjjé1sFwc;;v sߔ@NBa-ZHkLWX\;k VXJŘ_a1-&"gT</-cYb n?bc -1.!݅;mk~Mh~v O^>#ی`@@`qoblba>t/O@F){-M0+^{P~=/PģI+<ͬv6%|3xan M%ȅ\?X#t_3ݗ8'<j&sѼU@s${fO q^x~nA:;1O'-ռp![R[E':jٖO 练> \nTwL&Og|y/dܣ8Oj0:\>|卾#B\_-xoZ@8: ,zl XK;@'W!tO=b'~B'͒YL [M 61"UpO}R$ uPe9y옗Q+ױ~Y$??k|[~QgۈmjeZK,0TQGe`C˒5W̹fЙ7-踽hyurc4-X]=ƌ̔8;[Y87<c8:A@d„j;—CMn*[XUEUGܯ#'2Nؘng;mQXP,EFw!JTtvTCW\ق+j6&֒8E+MK-kvT07d&ą D[Gpt JY)=FD1_Ax WYy\q=qx$9^*K̳Lk9qw̅d1'e:Kl9\:M#sB:^ܴ>hi&-b]t1 qcA˯ؔ󜹯Զ 3r1=BW@鯲 _Yujq{1cav18v3L!EKkF5Ds|.7_%w?H₿wwk1IFۉ34l!)2wY3.K鬣avKo-[{!Mf:#CP@8`UYCuVbt-naM 3=uK+F}ґ&N7xFzO6c?ݍs{̽4bny92Xs.s{uW7|Kf-ɀ=nQ"n*J\ m>S^ ɷV|c*# W>ɓ\ Xq2h#)i / ] v;3[}USx~&qOz{ΫW6|kVxè|^xYDܠň)kcC#v_`rAct _3(Zx>-~}|IL?%kZ4;ϙ?bsfyE7 &C$P}Ӟ,.Awv/[5wako6c2lO&l^ '\Oș'3MeJܳCn0b| *w|}׽G{Zlyol#`6KlhH!ߐi$t%@BHRRBH #`f ۀmY%Kgs68~AǗ޺}_Y@pMy߲3_Oi+@ X)T0p2ThL3ejE +vgwQ1m1o "<2E ( "69"@e“DLbPbg-X&LO0 LWK2&zMPŔ8u:_Ƚda.@T-}-:5wa6HWdIzEbS/x"A.fiA<^A|0jj3D}FџB`edLW_ JN, r8ⅷ{%b( D 31M \ W,r, 0kq"sdB߼M.mQ>2'kCa!g~steO$1 %ɬtZÜran =F|MadfaS|w憅pfDp18D 4Z<0֊JQ@zҩ1> :B:9W$8rޔ%U"+7"a E"*b:+W|'zb5qBe*,뎱\iH#dՅ5t,c2n5L1zHy?{\NN2=Ч!iilCSheo'NQ<+ز~<@ىc0SE,Sæ1*F((V ssz^f Mu E#B7CÇ X?X᝙g֠f()yxM]XTS5;sa!(#xʇJ X*¼6"ʩ3[*qYDQHGB]%"FT ZUD;0@yo =ȸ *),4]zSALJKxa,jᯏ-#*%  $cIR{߁[k.廳1b"(c@ݙ$ay4UIX]ȹ2 GZ6N%5 3'}:qrrGw%W?w7+89LY\U0PhJA&&r$"A32`N>ƻObQEm9ʇL.mu||;:d'v;ı* wj)#ԋ1c^|E(Viשygj.Ch|AdxH8  M`B&G9Z_B_(과m" Q6x?~u\HٌL l,G\ӲS&[D+Zp95=J@u %q-s(DA&:ޑjb g*hbEfJbvi2oA-wE `h / %^ dz޽5|CI$-7 MG6GePc%{:+_&#g!9U:K-:;o# x&;DJ&G21" %F}LAPi7uxFsha^&˒}ʵHLC=t"mm'Ȋ -c ! ;OPL ᝮ.djG)[0gjbG+hsVJje[G@tum Ck^M^AhOޒ)dF'u(]qe'I AI) Ir>&XdZxt&JbHD_} О,lPq(9@;&1>&=0 qxesA|g޵m d!D)c$cH/ Nm=¦1:\? "L`X=͍@ CxS8]KyN>f(9?Xwu8$ˍЌ)a89 W0pz.t,HΌ0/KDG0˛ ^*"."&Ş> -RdLU_]3ײ[MB2h)ʤc03xekO4`evVQИqqNPv #Rԟ؍jAf"x$qc)ga$S xuW\` H!N5VD,HS"jHh)?TSg޾UЧV~@GFij]ذlGg+3zCG}|R^5H~ً _ \wRia)"!)u,aN #E|[60;CgCC 5B ܊%a(r7qFi865R!e8#m1";L*`,QLА 8k:}G7o犡kJVK3FEN1*"'BJızX#K.GmB‡jd)`}iL݁&NAuAʒY@/zܚNr6vOLk,Lx@5YbQG܌:M;~c~+ez`+S /d:G8D=Ж%`` F"tq1ZwUqߖ‹b!qōz(ȳ\[\LtjXָ i$ɧs>mK,* PuRM504SHVAR$Oe6NPyēOCPQ~=aV7mC |Q|Wq /?)fgɽ(3ޱFF-ju:(KxTx 3c(XIv46&ev=_2[)PݤScLPS#-1) #]Z򲰒gnovpхZ9,$ED =%K sM*+L 0^E>%/AM,M5H "Kܿ+S=a_;6fjEB*!MТg9#_J@3Ϙ|s͉c9+ |S}Oy!O3-0s b^"3nO9e|I"pQS#.mC~kx^V?Hv 'p,dL4ȩ ʩ1ߙiar̚9^Rș{}$cmtX 8YI R}_'r) qhDq*K4g枕 f#pu?ў#UQ"n` f.OfGg?Z2+Iy".BJ!߃zfU!_n) &?K xv/fzl0o7k$v}ijft A{K~릅n%)cf'02#>ފNcƉ5{ +ZE2i1?ZPj"1bZG0"yv7{e#baA!ҩN%R"a` bqʳY@+:ο1_(9ɵO1r~pe{)xt8IBrJu Mp=bm5u%Dqduh;5xvn{p?}*;^FQ.O!WC~+,HDFscܕMM!5m*O;ë.NkK#{#~e4-KlDY)V?GXZ{p qaD #r dӃrzo t?:P,ԓ[)rGu^#hfOγ:.c<_ I~-E4\L]YQ~ Bq+.$F6? jn~.RT@ H&5='ҟf Ļ vr~7?{I7G-%\[D4TۣJ^lvi_7u{+6,pL[/1u5,,.$- y҆ m-v`5ȥޯ t \!EP~5Df2qF0`iIDATgy,8A蹇Xy!3G zV\XB0%/ΔI2uTq]^Bŋa\0 .zi8> gG?AG.b$Ɨi"JYq#l:/L};w/uVLofǎ<#\yg}OSnZt<d gJ+OPKS\g֍,i0蜾PYXM[@8剑BtHiT6Px$jS2UWg+IPGF^b7r%d:vHS05MgRL~3lXdo(#RݔլGȂ I;,ҭ{)jPyY5K7*2+C %摺Z8ƽ}5ʸYdVȢu@B2󧟿1]234'2 ?)鼛/i.Ʃ,|멿aFN ,@"0؇~kpo*@r#)$NnXg>zX8 '%,2p6xQיcEI8_iمlr]̎ #sk/5)6.eIVJ"}5  WVݤp}CGҢ!&-YnѤq3ôd(Ee;+2߲XXQs/U߲39ؾ,Zq?2ښj u UE1=CϠ.kDD$ez%[.u_~a|/NRxx}>v>'H>Q7o#S,j D3 +q.YCRETAbD180{_*nakԄI;t>ϕngpFlc[NuTf(]# (sgn=2[Αst˫ロ)z{{سg ,{ٳC-lCYr?-|3Y@톥:Kmx&W/t ~{% "#/ec-w?DIFv5l_%> JVLwg)ɯo20_Ὃ##YY~%Cײl6gG'#_c2@O}Ҋs߿ Q}}1M[W0v;+,a;y~`HQ0QvŇUB@ -ee` . :z2$O^ȷ 4|z1z݆uMNݰI~/üYr+;T\W r"H'!oD_l/O+3XL6<!`EX28y)hŔzi-KG}ՏL'_+X!k e/o~͛7~zoi&6lދ(xw}ɇ>3WSS7 =yM]@e22%5EdL҈lZRݑ)^7kY=Qri$AyUN6K.# :SCELBO'Tb:) Aϼkii$DC@t+$$!`Sd'2ʙ/rd.Y&[O#(CYr r2x+"a`Z:bV%Ibu!915 US[ q[gh S7S9,$j8R DsCȠ)f #`zRG%r(4D|{S[\BT4LnVDD m%PU 3c"l.5q aZ  +ɡ^T g0g9(1 Yv!e+qs=Z~1-+ 'sdA4DD.Ys,,AJdM7ti(YQ0DYԼɐSɊgI8dID{ϰsNCaaY?---p]wQPPpFib?-l2֮]$Iypyd?? 45MO}SȲas[/M6Q__g?s<ҳկ~G/P\O?/~ t]^ϛ-wy'ׯiCnVs0 w}7W\qt]'v.x 'SRRrGL8>Cjs[l?s=ܙϵϹ'OӟYG>73VYYI__߻37fc߰aTUU3ϜݻO?͖-[ޝ~6o ^ϊ <#:u~+o5J^z%LK.as<|[9_j~=pUWV9ر-_'hazzz΄fc>[X,> j짉'˝Ϝ5}rͿiY_Zϛ{з~;?Yn_,xo||;ߡ)߹G}}K_"333~:;;y>n7xzNz>?}n^ àƹ"Lr뭷O}v-[v^>k~["IMMMsM@l6kΛ6;m6mvzذar _=Dw~o)Lf%W]uwq8p[n/~_5wqǙ+_ Iii)T.6[v޲,7|g޽yD"<Ǐ'JEEpol6O~N'\pv:߆:hK /qM7M7tg46l۶ A<mwWжo?yn6nVTÇsws 򕯐dhkkc{mAv0絯~tMTVVl}m{Oۺu+oW\amNm6mm6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mf(;m6mnZIENDB`mpmath-1.1.0/doc/source/plots/kleinj2.py000066400000000000000000000001741340375245600201300ustar00rootroot00000000000000# Klein J-function as function of the half-period ratio fp.cplot(lambda t: fp.kleinj(tau=t), [-1,2], [0,1.5], points=50000) mpmath-1.1.0/doc/source/plots/laguerre.png000066400000000000000000000456211340375245600205420ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwxeMOHOnH X `@PDDE"5K$#&H230|jժAՖz>>>P* "!33@jj*ܘݖOOOQǶ'ODX{_$$Ox(c}v3htxc8;hZԬYSPʄINMM:^r!mww]IOx;g]|;Ti޼!P[XnaׅgZdH6Rg_.;wv>}>9 tpc,i4Njv 4AEB>}C#Fr)jnAEBʴi-R4 %BJ3AEBʴ-:11JtbCJ '"!HY_E$`yTZbaׅf;;٠yB.UmPiOQǵ)N6hl#e}i "vsM0Qqr'4OEBegae=ΒGI)w+l AEB ' h0z!@T!܉t1L\$d){^ۥKXza)c;Dh4QOo\$d){VF=#{;Q7䎅gQl#e}j[z~)>>1xN6hl#e}203t&,Xk &Tr'4EB냈?B]`>H%wA\$d)r vFĞ=R3ߜ)tH"ܱblujH6RWQ7`VE*ca 4\$d)T$f%bXaUp8G ct1L\$dV],XpxA ce 4AEB5p=<=Xub4hH6RԷ\O fc7;V \$%R)ĔEFbfLX*-i&ɬy. )ؠ+hl#%}7g}MC)#& Z.pK8V[7{C4hH6Rwu|}kX`}PZHF[yHA߽{`ii C& Z.k1rH moQ߽ȸ"Xח$Ԯ]*Jp*Il#}!CpMU-Ln3dU1 0jrmXw& ?=XUw֔Z`]K- نe}5wBG:G9^Ų6}`]lf@. {iЫ^/,km"!۰C/puBxaV XZ 0jrmXԗѻoydQ!޽{P*L 0jrmX 5 e}G/4hH6nl@*s+ܗ5m²hLo\$d=V?F >bR,i3V 5hH6#"{,s"tV A\$dV-:{#k],@cXf,,듯̈́\$dK8GZemAXf ,+6hy#;mǦMJEB4 >K/^}ص vG?6hR ''' 577[l]c@DDDXmW)bm͛7M,nrl X1pv6#X V}>o963 BP 6aUkF8G.-9솿]ElڸU},.5hH6bwL=4V*+l ֎&'&m|>V ZS!I6bїPW_zf՚aQ_BB 5藡H(eĠX1x`u&;? X{ʳ0iЬL1V 1"_/e솽=gc oXbb4hH6B;sO N/N|lrPX1d`4X{%^}sȹl#l6al󱼜GΝs^zGb8L\$dsӑvxXu!os'.4 ޽ OOO 0irm̭vF섿?  %3{rETT ѠAC1 & Z.9mێgU=o{%N\DDD`& Z.]yx =~N9w"<<lfE.9Oz 0;Gzx?' Nl_ASfD. ucW"~s-N6Lɹ+8X-\$d?5?_v80U N]WV_l>.|a_Ox#|ݞ˸\򚥧%;?fPZeϝRDݺuh4hH6eiH'ҡ֖z]a}{@B6BU64֍Q\XW\A?H' ׳K^W)UW}{7m][(-~wE mioC}<6GYgFYs {Saa'On#oyc(lϣV£^=*i..Ƚ\xbԸR]yO*\$7yy>V=._(n6z<߻&5 F m2x9Ճ"Dy*W]ϧ>5 Zz*}-+藡H"9ws16GD(,mڢMJ#w OYtFT*/ǥq"C1X͝1W_1i/C%Է /GP97mc{,I_}k{ރJ–[0 >/B@vk rq5}"xrg(,苉AAAB)H(e#fN R*Zgln OQcR X8ѪLazx*,:`+5iam{#ic"'F"(d]B5/ʃ 20z- %A>"FGRKH+VլmcK XF|;49P(5 6M-$oKƕvWϝO*B+h*CZ>,-Q뚨66ח/ CiCUV\o4Mb Ct\nuM4Sɉ5w\>s,L^AEBB:£upyĄĀ4>hs j|X s(:}w{}{N\%o |IFHMa?kX')&_"?\jGJJ rss <:y)yp3j6&-e >F KCM=~sNغp-d /%Efϛh1\ʝv"v}D0WpLI#GԩS CXXbbb; O^{5t:t@˖-aiiY E-aMauհ6\ >}nѶFp4*B㑙VZ1gaҠ_"!s}D;wq P(Pvm4lz׭w*V:+8;=?d$&&=x7oāp=ڷoAaȐ!ppp(W1f F05Ǭx5P(oᶆT;Nc7o6m*p$AE!">}7o?\]]ѽ{wt*^yX qY"bf@A߯|ww8~8?'OСC8t>S >AAA(9i@S ƼR[0x5CiDD`‡5yqnܸ@: "F1l0CZmxbjР(kѢ͜9Ξ=KdNGɻ\sP URĄo 4rH.9Vh͚5K:!8ߑoV(BJ`Ȑ!BCC:>00xLEAD*wX8a;Q3ObCHJ@ժN~};46ѶX4j^/gʽ[>ȫⴄ1itiΞ]ʺCjEm*N%(D.uo#((7c ;,?._x `<o#@4|G 7H8cB*V*F(.fk@IAZ_mڎE+@*feۻ\? G~_[k7`mm_q|-B _)5nc2bp+ME]a8umA j &_09';;,X@^^^%s]xtZ=\8CcV{TQkG/Bɲ&ADE˗/'@δe^c1yyti E(̍:u:ucmI6lhOh mN=BQdQǎD6A<_̤y摻; BAׯW:VtbQtk-ʉ(PHh)g+ !q,֗I|IɗM`` =yFVS,:aBJRS\$mܸ1d怾}Rll,9Wq&޽zB@oI`"_ߧFL4iBDDF!!!BHTەs7n{Ę/D2.=DM7%쾱ֿObAtDVVO: hR4aET@JJ # =z4EFFVzlAZ.gѦGx9 Zr7NOIIw}JRY$bl"nA: QժU‚BAGGGӪUhɒ%tq.,^z|@:6lo/ LUOu QJ ђ%DM<5jkkC!jyW_RRR/$[[[@Dѕ-ROt$"N8y1E?%̫B/.'r9dt:Z ݛ զйE, `TQ^&))P&MLG=yd:u*ڵ8@/QFѭ[8E}5 8P-U-څ]O/ďr΍V^^Yd:х DAADOͺV-9sy2RRR諯"@VVVP\\\4:zg7Bf^&M;BGq\+j֬=xe^Ȥcq:ra@Ç7iItyS jJAAA4}R=|޽; i:_ Ej]{x[GOZ$уhv"~&Kjj*S*UJ?wVzPG64ر# ooov̋PW/6O֌EEEգΤq$iDD?-O&f͚WAAA߾}__V믿^t[{+It3|EsBH5[EhY"#M#zjD~JCQ$55f̘Qʘ? BPG?,PUJ?y/[wR_\5k=~l8) IDAT00۷ϘJYt]pBJ>'@T!"{Gh~ZH֠,YB&MѣGaxs̡ӧOѼyԩS%&fddP͋Hץ @P/8߱dtV,J} v&z"Ȩg&:~hJ"̙3KVVV4i$2 upC:WctҏoDD/[k*1k:NGs-YŲ|rqtҹ>zPZK@ƑA_~uFz<ڵkK+֭[͛iΝ}v"*fWՔJڵ#dgmG!v!PZ[}-s:,fXB@K~AO 9Dqqt7 %QDOKJԱm &\1[XXOG-/˗/Saf!y*Z+Zkt~JŶa4"c5mt:|.X,-- }5u[Eڒ&:PPҨ5ِmkK7o%]or ܹ,XPs!̠(''=<<諯t*CG:\;NG:Le~J!!$Rh:xM2m1t8:FHq*BE-[裏LKD֭;wP\\>|LRic1gHdd$uС,WoNKEnܢPVрhW&ܼI'Dnn .ّUɹڶmK6lrh)PE~I.@Cco9x zN{{B7FdNEI222:uݻ&'I67#Fƍ9/>>nBll,E;HOHe%T*XkQ~3U nJT8Z݃r@_`XcG(-D>GÈ� )Sņ 0j(888ɓPkn і /@WC`W/Ν=z;wyfA3Zx>>>)5r"s}%׳IӠ0HIIAVzt22n (\wSoPݶ+WVQW0f {7 ..Wܷ}9r$bbb0k,{in fm 55 w? :wrb/gWWbӑ8pg\9%j:DM皨~lnEFXkn6}ޅuǷAHMGz^:sӑVyHx0DGAGRQ*hU:ε:w;Zھ "7WFӦMqI8::V~ tp 99hW#x 0p@l߾ǎCLOL0j EF^'لt11Ɉ)5P!禭 =G#4hXj1W={ÇѥK۷"іonFhy%*^EHX\ D*ULOlS7'6VVj{F^FYdQ#kG~a⢐,5pqKVpmz۸ 룊H!%oߎ7xĉrJNͥ ^wBL<UU!2n9'''#66 4Ĝh(mX9QQ۾h:2(0xpQa^Kg C۶mzjԮ],ѦP(Pkn-\x 1_c1 /]hժ8?uPlS@``эW4j,X<~,tF>>>طo0c lݺ=ڜ;8å r"i]Qq߹3bj`ԠWJ ڵÇ@@x8@Ew*0uV( 3἟0M[1Sr#  Zd \rō ͛'NNΝ@^@͚@T52@=0{ljhslwܑ+?@̕;}t,,,Lq0 b/=yyD[uFP<[D7hZѣ9Q, U骧IS$!!P@@[fH/999hm /~~@h(0bP:zqRƍ-[`ҥTmM9Ixs"~J1L䋄b|}.8xhGNlТЬ/@z: Mؾ};gٳ m5gׄB@wqdbD,E—aA4EBcP*.]͛D`iS5jՀÁG0(! M-[ҥKh0p@ 9B+VZjXf va|=PR<KϦlЌ  > q-[ 2K20a<0l:y\.q0O\)4#EBFH]v4;֠;]6U`WuGx=P͌ ܸq$!`Ҡ"!\rE> 2|4h(sP(Pm|5zyKu 0jrmJ3s}իP(0e$&7`UQJ%6%AmbP͗qz`Ԡ"!۔ }@ m۶2e 2331qD:̑;KKx 6[[^#gS6hlS>ʜ9s={`͕oU_yB|6pEAf?0irm qCêU'Owr#!Be圀0 .: /$L\$dq:tI&!55'Op_sba滊Y<믛BäAEB1Y }@o/n̙݊;Q^PX)1lw |YF Z. b,UT)i?i$9sgf >"yyeϦVř3g`gg' `Ҡ"!O> 8z> ]vŘ1c)Ssgb]~YYYh۶]L\$dU&Yp!UחDpsΩl'PN85hH6fWFI}@믿Y9ΝB@ ]EXhn}t٬ L\$dAǏO>6l0uR j`U(,HZ]m\ͩ///ǎ#ڶmk & Z.8dxxx~Ñ#GJ nݠ u?.ͩɓoR?\$d3;~㑝]tPڪ x[ͩtlL\$dQ3ȀJ @8mn=ݠrT!uo*44>٠5hH6g@V_~...Xt)N:%6=!eg o1x~39ň >R"!0O> ^?% ";Vf>I8,sݻ|bE\TZvH6LꫠȈ?GO77DFF"x4Bt +/+IG#~f<ĠѣGR6m͛7vZ9s+_. ÊT8qR\0> P)9Ё>ȝFC`cc:~>1# U_o%WZJYYYزe vU刈oy2V?sM ~Ťmһ7+Mf Cv@~h9fCb7rSdž -Z<$իصk.\GCDHј1ch„ 4yRK˗WOQ {z!&6"=G%u͑3gZhz@"Dk!7QFh'JE7l 8YתE4gQ|<1DS(B)zv4o֭[}-6oEB>OOO|j(X> z0z=G]JJ .^VeAEB8L8;vč70|N]=;TiY9wr}aÇЭ[VeAwկ_J+WΝ7n<݁> ךhsWe_^W -I6RW̓FѣQXXXzG`@<ncݰ ?4hNBgM<\~Rլ8aRCɓ'ٳ'TyXIl#e}jS*Xz5lll0{lܾ} = xX'w7𙻭[9XIl#e}kW̙3F =`ƌ喃{_w(T NlOoؠW^E4hH6RW)SM6p-Zd?Щi[0KK8wtFB<9XI+w=z7Il#e}eiSTXf 1k,DDD7x}@#Fի|P{?w@d|N(& Z.A A~~>ƌVkډ|}.8x<-Z5~3VȝL\$d)H-[ٳ駟9R tl\4d д)pᇰn*n5VF90irm"mXf ,--\.'}Td/'HH50wnѺk##w۶m 4YIl#e}ikܸ1fΜ\;:  eK`rC[4m> \Nި& Z.m'l2~ݴao5 wlp鍞={ӱ- Ffii5kӧOGtt4qH;ڤ> \xzC^Q6L\$d)W[@@Kj7Sb;SLe233cAEB>C͘17ѣGoPeX{[#t& w6۸q#rrr0|pyz4hH6Rg6+++Y* 9bbbxKP;@@)eW2˗/ qiܾ}ZB-G0irmm!!!hӦ Ξ=pz .H?=\> 믿&Nh & Z.'S 4ǏǣG].]]U"T JZ5`pQ?-:dzC.V- FL?aÆ8p.\QTOQ٩,-2(rt ԩ̝#7x7ѨQ#H& Z.[l +?ȞCs}@n@t40s&~>0ys0irm m7Ə?FC"33Ȟ֣B! gg?DF^Pvp?e+6 IDATIl#e}\i0a hL0[a9wrm8խj5>9FyaҠ"!HYW ~wa֭Xj'i?lQ}@^F4hH6Rǥ6gggPT裏pmvn ,AEB>>)Jlܸ͚5Chh(&MIѰx:uSz*/ԨQ&L0> ,AEB>FjհrJ,^1)Spp0lll :ML\$d)S7o?Ǟ={Lv <1DDZgbرƆY-I6RǷ-[b " :ׯ_7i c 0irmO(m* k׮ȑ#v!44T(K_\\AVcڵa Bv-BGL\$d)RJš5k"99]t -\߻ z 1112d L\$d)ZJҥKn:XZZ/UIMg(i7gǣSN Aa(LZhaݔ$d)QFٳUmۆ͛c߾}^M+mp| e;nyw7‚-/3L\$d)\t {ƽ{ЫW/e~>9s&w|?aiiɋ& Z.M+vލuŁФIL4 .]*uEq4q4 ֬YFaܹppp֭[tRٜyIl#e}bԦP(лwoܺu ,=/_VZӧODž @*2OfBEvv6>)Snݺ3f ѫW/\|Z!ܨPzѣGDDViСDӧO/oǎll߾]xEXcZp!mۖsp x 4|畾} B)Ds?}%Un݊}_Ezzzfk"*JxEXO?gϞEll,.\ݻaÆ HA l-lѠA;Xbq!QBLe^vƤIJm9r$ Vj[BB:uC||<|}}:C~~!~)>S@,\l~]ctZr_>>>E }RRRJIrsҙG#e}K%WΏ?8(WdΜ9شiڵk> k*Uo:D"և7pqqS9͛7C3f:$Nh4ݻ7:viӦ jժa֬YB)OPzudeeaժUBd2 5knݺ . ,, f͂-zA "[**JΝ;ǚ5kp1 B ;vݻwR"t8sEt ?# DWL3ooo^ `ٲeذaV^-ptE0e p(E֬Y>}?~[С;wТE ϸy&S:v숍7"00D$<|ij)..xp(-Z|GB)۷?c޽+fusssCFƋwڵkW_aݺuƍ7sCۻc(H4Bzl*e:`j!)MK>Qb~ s~'xG ^/|{3/6(n=׫nVQF5 Pz>:GU۶JT}t:)ccPY\.Z,Z.nJDY9{ 4|:OB( 5Mz' \y~[F&-'_hx)_}־}{mĉ35 8y[oQ@z:i@|5k Ņ .dԉGAA@a!0|8=j;G֭22/W_j[F॥@B}..IJ^w 4j FϽ l ̘AmO<4lHCaCIi֬MKڦNK<$%Qx%8E..\<qQ%=IB-noMӮa4~I p-ԖGd K/Q㫯lNq)@\TA4={5<</\H׈Ozo.Ug\I`nz%ܜ-R.ڈ4 [;Ǵi֠5uyz5.κQSp-R.N.]{qXݺ}Ҫj۶ RKxޚp@\UP2@cGJHL֥#F^K Amv'/(,/ǎUKyx J躰0,&P-Z<S֭@p0pMmKII - 3pE ЎLG&8̣MM,գ5Km6\w|uwJKyx Jhw*7j><&* ߟ_t=s&zf lB;'?\\x JhIBWF׻Sˆ xxJ8%~pE Ъ% A.fpbPq:. @\Tuƒ%K%%I#]K-M2/ .:@W$ q˂ iz;Ku*(;+V &&W$&&Zn#+ڶmfuDD$b߾\KuRSS q->>111={6233 it5ZD\L:ׯǰaG~7n-[f@~@GY+[X}}},X IŠpwZ 5`[ԕ.Ņ .z]ʹ+O;Fi);+(՛[\`\b >l q~mR:tಏ0 d涓B{\F?IsFŅg'@QQӸ1Xڴ^?D-; 1孷F$ -#tbץ~X^WﱟJvܒ\ҨMzҤ8/=\JK {!;;NRS :wڶҹ!!U+:볮dppi;fFF¡_>\JJ(޲_tU6G͚]GWX}5jm(%I ش)QQgOpjRRBDףG)W6T>l}J+JhI%8\~ 38.EӀ dxX4DՁ84T71OpC-IB}soi xVA89ΰ#0&WDQ2@KP.sRbh`(81Chف{pLw:3 P}pd$hGpD-IB}̛Gv#.F lA`~ WpwxxШk6m %$ vc8ңrev5>>@:k)sg_KҸ(%Igbcwu}/5HO/,_ ijK ]ߗK\@s-99޽tvђ/]9b#hIÃ}0s&ybW{[،Щm ҅>xpC-IB}_|).ҦMw]k ƻwS˲n m97 ˅JhI%$#UF T~_( z7h]"JhIꣂ֭T˅}on  7XIXܒ\P%?xQ`]KNa⋴9(xA:ads~eq 7d T… ڵ5ƍEx!Chܲqc[8x5-oBȠv2*.;w۶H:=&NTo'Mp@ޤlXP-MI`+9#ZIL4ј ])Kv6{PZ g_Ko`wwWɅl8|%eJzf'a iTw X<s~ǎà _8;ڍ;WC )\R,_N{6lHEP+ ܺ9ҵPN.`CBBHIIAHH幬,X111Xz5 11W 紪e4z/Y1l[<۠ea[|2/d"?]o i8ZԤ !.و>X֡5+;GCЯ뗎;v?ĥx`̤Ol4mƐmȑڤI_~湻 +Mx^z0P4Mۻw{5&h1grm޽.=JM[Hía`MۼYJK M;v 6MVL$ߌ_v?i7r~`y~ohvR4xb'# ڶK0y2oO ~p-lh@h~{^+P0avNc,ϟwE9.ɖJ]JJǁS)SU1ի.. .v2 eql¿l /|mq^8~|)[tNt+ԥY3`Xt*KNiK?*]\@\TAb?c@3Z6GOW#.\~yb)vp+ebhIE58tvNBTʷ]s..|:CzC%<0G|:c+H*uyI/H_oJoп?}Aq..I42=ߺӦ-sl>;}_~&?px]A.4mGbॗQ;tj]\ @\TA-I,}-8:ܥh.MnŽ ˜R]*tuJ>Ф 3zcp.Z$1 [Z?]oc .mC8'Po %7({ҟ?}ۗسC]\ @\TAbѴɟYiZ ab.PZN3A.9HO_VSФUw OZԯ$*(% 삺%ss Z5{J K1=(%1Ӱ+ܐ[uii]aϼ:tIL D*(9IB{_ۺOy0A %%q_hQN1i1@\TA-IB}q1yiTw ;Ay'v2f v5=Rǹ lcpcbH#.ZTųͱ^ z7:#zL k%6&_}U7.p,0~<5u@\TA-IB}j ?"ج(\P3__`8ϟ9DGӷ9vҡpG\<qQ%4$!RϷ}f~ϱy.M}Hn?}Ki)уix{Y|IgrG\<qQ%$ qK=_ke ,7}ĠcWRR^M7tn;|)%_|ѡ]UP2@KPg4Gy8(*FO?=kЬǸqT"YpG\<qQ%$ q7FgRk-/ƶo̞SV?u'N 6gqELB \}G#oqcs/r@*G4 |[AKP\Ƕ>pv]hڴڠBSwqE В$(&M1P8"B~]Ν+?Э#.ؠi\[ В$0˗_xn ەx]z\],YQwoʗ0C-IB} ss*I6d\B^ō_=G#hWh..GƍLL3^^SO&JhI]֮D /xؽ{w5F-Hh ]/G^@D֩p#.@wIOfiOm/sҩmڔΘ= y1u^ -Mq.{P%#Fȋ۶_L#PTvL +aQ4iMۘ1c0rHa$ qcЛM+34&Lm9%"֩`q\RT]ʹh>cL su%$nt:e6o!A^\ѣ=qq\<'oՊV^ll}.$#ܹ9iG вP ];֯M_}EmSд'pmw1qrμ`"66]; SpC-ILVTht)Ø5BC-뢇 4{pvӦQR9#w}7M\:ZEE@n.0ʡ7:t LJmeF0Ns s>riv.\O*psǎj}ϏVؑ\/P2@K G|=G.4ף}sT/:Ѵ޽N%9Kf&mwA,>HK\F85@8qK,ܹsu$af&cxmq#޼}slpj23)bˀtu4~1#9#"K2 Sttt44h֭[c{' Ҭu)̇=j\rڬ=sgImN׈;q^5!vd2p ]j0q4mo>5\ 8-@O8_~%qIl۶ SNŞ={j咄%%K_)^HiiTw^=h8;VT4nLmIm=zG@I7sJp(b2Yw_oqGRm(x]km_'/n8-@oݺ~e{4u6ǎ//`-sf) ϷnM\a Q8%8u1hsRH'tg$￧7`K5 itu geea1b-AG>bbSWҽpNpjƔ)4<ٚfܸqXl5jS",,(ˀgN e]||[os>('PBT2im/Xep'/nj; .N/ع MMB;Rk\ %4띄yiu/?ʥ_o:Z*48ɅJhwSCi֭i zr.Na3f/XXɅJ:_n(i.R#'ieR%~~L'p 73gĉc̱ʍrAy'h.R-R`0prݪU+,]h֬ʜ IB}wE ajGv6ˣʆrF8N.pZpqLjѣ1j(ˈ<'IB}wdҥ?]F8jySq.OO:H'Ʌ,FX~רQuV,ZWHHH+Wm$&&Z>*h[z!κuම/+ c]ꗘ܎]]©_\̞=ഝѣݻ7|A/vGp YY0 '1(BtN~mz Snpsܒ\S.QMN/9ʘ68 SEI3nǥ_t=6IT"ks1N.`;Q>&1ԉJmѴZiآZvSg\?{XGF* \ %$ԧθL?d r m~%ڌb >xpC-Iȅ:b?h}D׻7ar ˅JhIS\n MfH:N޲hX&}rᆒZvS\|}i :sf >xpC-IB}꜋9 S$+su8N.P2@KP:b^]mH9C6zbG(%IOsڷFT鴓dxTZI(z]Q#u.˩\q .jd$>ue A:̩:TE~c(%IOtiЀD_Luڥ_?:@v:HML9huea4rZC!\d$>uޥڡ.M<bG-5Su8{hْ%&"'qI%GВ$ԧλhA%HuAppr~'NĨQPPP`$ q 4ǯe:jnqj'n >>>OM"%%yI.ҵеv|8z/pr:t7|b̘18|0ڷoo3$-\#_~qG""j2nqj'vhOc̬YѦmȐ!˵5kh}ihi{VZmDӼ{{r4[ۻn>6ik֬>m'X8v>c"==G&M,Ϗ=_Vrss[m\FزjE;e#<#8]v1o<|76$aEK5k_".j2@W$ qjnX/\<qQ%$ qhڡ9.tP@ЁNB\@-Fq//kW +ˮI5r +j @'!.jdK+y?tgbp"JhIV._O}@Aгu\!gN r.Z TɁTN.Pr-IB}&#xxPv nu'n(%I[Re'tc]섋 .d$>nbbZ.#GӧWA{qc'\d$>nb<.ǎo||j)W  .jd$>nbJ]̛RFvi)nw섓 7 В$\ArQj)VK .j]Up8%1X.QQkg8|b#hIv.&*>D63II; %$ qK^8}řN.P2@KPt:2?'L5Nz ظ~epc\d$>nI#G_qÆQ廊'`bW?vɅJhI[(@?0[4jTk3]oͱnW8pC-IB}%(hؐ>0};U-prᆒZD,kRεc蝈[; %$ q[ʦ9L&t\]TT{}7?UɅJhI.UC~qY 8pCɂ$m]ݻw>II@|<#4-z5%[vޟ* %GВ$m]Ӻ ;Msޟ* %$ q[*XQ{.tS\:@;:thvI.Z GRXtDɂxqF7BAG_UΥ~}xYsg~sޟ* 1tPׯ#<3$ǭ]uFtG]̡Q8E?Ʌp_/_Ɣ)S[q+V &&W$&&Z Ȯh7UmWr'Vϥ~}j{a$ w`Fjۺ s5~Km񈉉ٳ VhOcСC˵ >}V.њhڌoi˚VXi?Lmqq\kE?eرF+`*~rm$ǭ]ڶɓ<Ц m.K>TX)/?mB 0Nmj+([ߟJ ZI.P+3*s4g>w =Gz@Ӧm@&6ap6؁[ߟJ %$ qkNӧv9}o*oN Vuu)kGcb4z஻tΦ`Xw6nl]8q"]7nvwFn 8pC-IB}ޥKz:k^ԅb:e1`=wڮp84SVS 8A!,f\ -7 В$]*X mb.I" HAysG(oEm3gҴLQr47ysaM=K R֐{xЖ{t֑K/Q>}Kj;j'N@-IB}ú;vBknyjpivj;u'it5Z:7˖-3ZCH^4J2Oy9Fe]^n8tΟΞŸ>`[AKPq<ż΀6 pK\; XTk<Z @^r]͛<\}8pC-IB}֑ѥK]BBhN.P2@KPqē.{7@LOEprᆒZv#. \ .d$>ͥ_x JhI#.НLHۗ S\d$>%&{{ &"8pC-IB}' KJh3B˖ֺ.F>\d$>k.3ѱcG Υw?prx\d )r Xz 92#իW9'X/N.}e@e //-Zi7UOOO, ,MҗAчh?I&ٴ=sԫW~C!33|et,&O7"66xnЧOxzzbN+ҥKg} XsEb„ G&MޕcJKKO %%%XhS~=.'Nap7SNxꑖ7|Į],FIE.ؼy3/_bDDD``LVtRDGGYfHJJ$bF-["ˁgUr >GKYBBB~!%%-$$;w7VD*r1၀9ݥ"?WIUO̙ooo)nѣGѻwo<_|999XjfΜ9s )) 7o^XGooA߾}1m4hUVǴil,^7ň~y嗑L,^Gqi'DƍѰaCDDD $$wqz)esz.~~~QRRpܧ3=N 6`С֭}>3f-OOOtŰ~ % ;DP- BdӦMx7q <Õ&t+:93f|' l H,NB@@!(hNh"˖-ԩSY&"A"#hAHA`hAHA`hAHA`hAHA`hAHA`hAHA` k~݉aHIENDB`mpmath-1.1.0/doc/source/plots/lambertw.py000066400000000000000000000001661340375245600204100ustar00rootroot00000000000000# Branches 0 and -1 of the Lambert W function plot([lambertw, lambda x: lambertw(x,-1)], [-2,2], [-5,2], points=2000) mpmath-1.1.0/doc/source/plots/lambertw_c.png000066400000000000000000000700131340375245600210440ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATx{oUϻ^ћ['UT\iAA%AQT#! ҉H hMwaр B#kRu/QL%9u{Zs1cާT9^s>ǜk^nݺuvW&8Hnݺu6֭[nu@w֭]jݺuvZtnݺݥݭ[nwu@w֭]jݺuvZtnݺݥݭ[nwu@w֭]jݺuvZtnݺݥݭ[nwu@w֭]jݺuvZtnݺݥݭ[nwu@w֭]jݺuvZtnݺݥݭ[nwu@w֭]j/v^L{g[[׾N8}{O~EenΪi"^:|#<Eanβi@{3??voիW񶷽 }{qEܾ}[?^"~m&h-,{` T[xDv:?7Sa-Ka/] NA Aj-#_ыPV8s%Too~},*xyփʫY_F3/_{ԧ>E-^ 5ud #2*) uA{Zk@[y2 LJT-`:`uq@o1G6_G.d- 0/C%?ڍu@}1i;!'ێzc)(k"K(t*)P1O{YYw[}OFK*l@lY>Yl="f]?^ڦ-l^=yq ޶@ EeT~>w!ZJceN;cUVmmox<zR8/^7uei9e(m 0u=P|Ӡft^ΰu@o8[_?/=&|A'4UPonWCh'SMWT7 @j#LR/Yr7SE{TXCx|:M]﯆e.;*yKkPokv˪tv}|t=}>ckR"QX0`oӀ"_Sr0{Ūsu:W\%;kqgPW0'N떭z?O}a*׫ݔN>uAd S3G?iSx ƞ:]6-nd|{6P/=b?|N{ݲu@xy;RLK@o>؎V6yږ`6[,yq굏[woG]9h)ctyXe%`[q'TA9M ;/OYI/y{M[G7} xe\EPE9 (_Z׭zmaȉvjYڵyun3K݄~XTRi V?W`}}e @&{AtP! m݂sQހ}"-)0ѿO,bA;n+K+nkajVskN/\fv2T0M (m4C3oM@^S!K/ޫ,?kR(ɶg6d=ZvM NKzHW]Z[g>ݗ9U9ځo܎NT2iDY`^9\  AJ{ *(~io?WsMv^{W 2:xyqϽ>:pli=Z;$0%(7(urN KE #?&`V906T[%^iy-itQf#,z`aN7Ѥ*gxLW邻 1- t<8~t׭:'s@wC1)gmks|:mdd\I֏4vk&HTYؚ㥚& j_Ң_zᡁ=2j,hx}֜I@,<2:iryT@8s#^G:WZE(%ϮPTa^TSA,{qG7wq)y^w4X!\;0pM 0:𭖁ӎJ/ kg ӾwH'`޽y eL9LrnXAT1YҊ5`XSK6I*ʘ?jO)6bH3ha20@i z7 v@okTyBb55]Ŵ<ڀrC$Uiͱ +l Rq9ޮƦc!i)f6a:WZZwk}Z*ogMxb%NsDb^R.5H>'oO[ fݟk֦-2 @➂`aV<fd`zRE[`,zPUm&lUfYրkoj׷ iZ*tKkhO5prih, vb[bèױ186֝:Wp [f -9y7W|p5L1g2$A| o& l:bjrkX~/:^50mQ f>ΛY( ^&P+ upJځt}쬼Zn8oܸwݸWO>$~~ oy[׿*mi@\[ڬ|@9W,"\*g惂 pV=f+@\kzUAgo*N>Yy^5sƭEdw=o ׯ_ǫ^}?ƴ|iA36eq e?/SU $ ^#>R/*tb '\]f;V=RT5 8`m{>jc-ۙV< ַz!ך3!c* xiYÞ#;I{J.;+"T̩Tˏ-ϫ&vKv}U?Rڭkӛ~s .*l:lŽ4ϴ#AZAP>drm$rq~oZ j$TeEs74KRYntmfXeWEYӛgo:׏ĵcNhgz׻W_qU\rg?xR|. q=@Oi[µ4Sj=Cl9;WbguH??S &vuzR 7iBy+x G_mtLg?k-o15+r Ext>c\ U.OWko@])l[`&gzɇ+VW Vkoy0qQށrvai.TY]i^w k n4Ob><-pg uB2 ~j/%d-JZE3'̄s7yV̓LX8X۾^bk_6+UwQH ;T8r萮YJ5Q[o)$ cA9zf7kaX~2!zFG[z,-z,aũ-PFfՅ&6S:?cm p͞pT:l[:P Pj ™u"&>PNR}i[EJbyUۖ*R܋R8Q~CZjMX[Ұ)h\/yq+ͺad&Lgjv3ANvԔQ,d9a?hX*X5ѽkWVN\Y@g~l"θu@zU׮_ޚp-mʠؔ0˽זz*4e!w*MM c}6dX 1ݭ7h%]F= ([Y^Wѥu@o6gp4^j!x9bf nPi9OXHD,,e5Z18_+RV(Fi?w ҈G.ks'ּt@6OY.g-!^F{6SÿtzmS<ז:wDs(&ku|g;/Ä04ªy ]\-Fyl790C/(4/:`wI5!b𤩍]D8.b#ş1_c8J=k'VӕUH;'bT(4\T̔W!O&zepN@׶T˕W0Z39F9_KJn3U g2:"c_DcmLQ$g V|d04ޙ؁tj Ўe՚֭z a(:puTs_dx}BCK͇9B31+3 Os];S@29(q 1OV`JXrs LM^\WW.V U0a[4{&ȴ 5ݮV>t=(]Zd s`ƴاJAƁ?O[7 sӃw Ϡ7\/M(ދ( |V?P-[eCZ?k+fF(Qy5X[`x{ 1-B34$dp&LkmY#|)ۮ,@S|ъ9U+h=Phh\i.r +y| GL뚠f^m%/z~XJ\!k6Hvt3J": _q|hઘù-SV$˙.lj|x|$ԨN**sp赦!*nTͮ⫸:euZMbaS !]ɵ*sjsø;+T5; VY, 7ua4`9:u@o0ڟ'kR5hTp ̭~܊V *Lqn-:Ir[4)ϕt P4i)Z89\|dVGNEVϸu@o|M;|aWѣ[f{0NYPcPmr00(Å4ٵGr5_A"{65Wqp6'zP$J^Nq>/Ȗ9݄(L{ ߴ`+z8KVB4CYwK{%2\M5[VS9%LAz&F^x%մ iƎ?άuja *}S\klː+j+fC=GH{`XcmBLn=SX[{==nq\*g7XiVSQ;`.NΕVTʺ p^n:7є&됶ѣ*C[J:7AG Ho uo (N`l}B9XyB[蕖oF i50W# 4=:DUܹӔ8L%>TȀsl+™9_9#;C똖ֆSj%E1;SȁvL(7;lkθu@o4^kcJ9t,0KE0S&Si2DмG3m#̍=0  U)IP#8$kD˅uPpvŬM vz6%>Le,gn4h9Zk `07]&ZKJ Zbzf6@'ك0 TE_F1@!&p&k2RžiА&ֳCruD}oF;eS%E},pt^kAtweZ!]݅2Vd>"=+VJBzn4_&L=iR{dWnrttsYMҏ-zFzNsz֠j:A!iםXEn\@յVn:O4aՓe\셑<VTȳM qaӬ % c%"W 2?\rµ 8НYrgX X\u]ZX[ ex7a̻o(HJ{?dyE8 %"܉ :̆jWD!3ɈOc k`QN4䭠{ ̾e>Tsz6RVMW51퀹١g@yX2+tQ[*uK-Hÿ1AK+#Ke4=?Heڞ1 FB\ pyܫ 1>t 8pHi6.A:t}׌ϋ=@ǔqT^#6! +P( b HcTY3j'2{i BwwhH2_QQ'90Yh ŲDžsBEGG0:0`c1FŌ @K/5Rss0o289-qdxitRД@,UOQC[xu%̈́Vqчq^iӨ+ˁC BLIG< )c:9v!=wjG9#L81Q7[_4?t`utoMXr[nKے~lm!T63H{~z{ѭIwFYEg.Y(l HOjvh(9E\As7Էh?:BzG1"x9aA<8w5gKR#?Ù sm@P]$%5x:Ճ 79\qW9MfSS4 $.aȕt|O01Cr}D-^6G)>h>%z$qp#)͟>Ego!@G@8 cCx۰ܡh( GMW֮k%o-kuΘu@o-l5urІtri@aN#?%A܅.67:i[:\ ΔF ҳ×0I㉠4dP4!03v# ̇fstmpù Щ[r\q0OPah^pm<K+Ȱ7ú_VK&^i1EeS>of|z$|ܯr``jϘ!D$AtX ҄- <?0-äٳA989Z]gaA]  eY -`0O>O$>ŋw~VK !a]}e`X=KOMD'jTP&pŻˀ.fHZ0Gs?tđjjIH#v#HH#);tqHx {JOBQKKqc8_?-)cͪu{{y&.]x_}Cw|5{jZqt< $q0IĄs^ܤf vqꙿR9y&aRqvwh8qs#p& 07t  ߜpοMm/ÔXjUVW}BɆ'G}_җۿo}ͪٺWyNA8:Ռa#Î-"Cp.E \B..piZF[2[8+l}hn7 G&xzݤIYߚ&6@y0GsC,=$z)CSLW,ٸT[U_]oY`A7%/~< ]K3/]`etV9}؉2 5}f%=CzfЋrDw8'U4:?nc8~7s88Cra|n#^Rޔ 7WMh# ^|G]n/yxgGG/6kjYCK,T!LsQ=O`J58WЁ[訤% YAϪ9\Ap+H*//TL5.]ѕA~`8~GWp6-xn%? M 5#h$&&I9o$ZsgczX*ʙw2Pп?_Uƍxߍx+0#'u_`)T2ͩ)n^R&y@: Y~sȸ{E9n4⤤ y9>: qxk7^[!a<Ӡ s| 4{V /l(3UuKn/k{I+}CxS|7Tsw÷m|1=q<__6gַC駟ƫ_j<3x?0~\e_cej3y%rI:9ma)L7ͩ=xyŽ-5p6DL) +9⫠ˡ$9r gӝKOn?'7ZǐU܈)K~.̼qaM;pn;?#k6Bn˗QT{fmқ}xp:"[ox;>яLd'\ƍx{ރxs^իxކx"n߾-|ЯďIl'2OJ_F@#kY|R#~b" }3iL/bt#pnkwS:DcJ@ z?>ރI9AG1p{u<=![Az-q÷pq>qp=va20y !*Ϋ!pKpQf^DU啭նZ羃 #KZA׾5| _Tg?k}S5."U.73o+Pv`z(&1"GLox ` V4}b'9>AI1%=7> ҍ{}s8A70[p# lGB1h˝k )_7EMMnK^~_/}KBxg`MF%Tb2X5[̿[2&2c^saG:[37kwl2sk: pc=? \ہ .a&@pnb-"8-RQ@ZR.Žwaʜ[}K_W… P "A)P*T"CEChu۳jx48+#&qE5ZEf[pw5Bpi f`y€v8s!SIMYM"m5aT*lw铕j$0SX?ͻq{u{~w~ٸZ M$c'FfT<+F8G4MB'pG:`; _񬚏g(G@-nq0b7Γ  n#ܤCtwgG9΢a!2]TSŕzkL2Wlrqߦ'{s,/)hHްqLN1T+0sBz{#"9p!͡Ll d|fsn- C.a z|˜!vC%WGRˣ2.bkk=m8e?8EmZˍn/i@#OO5?lua=Qkgay6g\4ME[ qWpoj9 e) p{dr i&aTT^p\xҥÞC _[jo=۲?[r/yw]H' GW/f<ۙF49@8|{NpWpLEf戃f}@p͏!LSǷ)%Bz >C"fPgx``uzܓV+3R~Ph)d]AG{IGG_.LF%%.oO9,ah0s[ l ;7ÿEs∐>5Ǹaw`kw ْs8|z80y4\48x@\Aӷ4t53WY-[;b K.iʽdC\JZ+g/xL[Yx7P1Yy,Mgo4xp&Ս:$o褜[# IFZ-[ i3!)@az B> d?q9΅iąsZBYHt[0P Cq>3 };I80}<;8`7F8 sa3q탖oUvOS ipac81ϙΊ"/;o'"S`kM%z:ObεHo8 HQJh[\ _cNf5Ca^pNs ~~/8ʳK 3wuH=~Qr7Dg0.3;7<"#ZgO92`q8e`=`RqK#w\Zg83IE+礎fw8Rrf3s  4 ls|kazp~p~KCzR0&Ftk̠%wp(z:EzΏaP^Q96l8iaw׃:Zs/c6#Ncss;|pGU.#(Ij,NO(߭7Rf<c@\ Lg09{#1]v9L߾YVkw'8v$˴#RγT3Wyk각\Sָ)Kcu@ED4rS>)U@ jZ9Goss<9IES^5oAwAu dP4t()8(H_슾gް}мCz;prI^DzzJ\>sX+vpnaԷTi[)OϳCf+/|pVugat`7j P kyJrpLBAZ짱V0NIFltwpa׸ }ԧ㱊 h+t1C`ѮO=kKE_NQ&[WgQi`Z٫ϡ.9nqb*:&T8w7~@Bw 8(KK*tN4\RжvA~k#]3 8OPY a]B=]VmnU6C%,gβu@oO*pNuU_^&z$zʌkJ:n>BY #7=USzBlHBɵ}ғ#!m9crOղ =ǣrLU*Sɽ _[ں[:WZv丰8:ɶ3) kP A+gRa3%EN*Z#m ulGvꃞZm:jz"@zu,r_egw3`^\S̞"@m|]宠u@o0=(j'iz\-ljqR.u 1Qutgvη]iPaT4΁Cڐ7PYz/\AO`qJy;ZAPJ96Y~ұGt=KhBoDZok J:%1Tz˪)p쪀TZoqZJ *g8gdӬ`+hQON^,Uo>9xCZ? q@yZ>se6I[_UMwiZ3$V* $k$ѵAep7 vc%JO*Z;Y? :!M K pwOk3@$/,}UuҺ|:Wu#Zb1*Gf&@=W(ӤnG9n E! Co~ 0+IIˁCkJ\?hi=%HM;hQ]VYSI9g4KEgkxi 2r.ڰgG@t~v(Q[%ew6qoԆz)e j4{WY9sG@Tq`0e0׷'E|C2CCRTvQȷ8r+ } ` [[i{swuI^iw)lkCfYNDj^e͘y0רK_4'??߀`]><89#05 ;cMe˰s[3%XC$_™m5]=-e gnx "T,}6p%+߾Zakb[#CЀ-?zgk蟵dmPVk`9ӔҤb.:Sξqv2ۈۮ1J,nCYX 3ɥ ̺NYحdCX[[_@K'PϮڈְޱ쬜C \'&@>b Ƚ(Y+s-DA nc6˿45uj+_FiaΛ(ԨK[ipmjU*g/<$2wypjA.\gϽaTVȳMہ9?Rk?>󡭰5_Y[O܎k:7gqSnˆn9'VdalL,iw݇JFLpSޤ9W;K !`ŒP,kyfBV'ss/pUm /ju7F`">*[АM_ 6>CʶV9؂r,mPiY- ZK5 qi_"FĠ^݀x7 %94ߌ/]2'nhM9x[8-QztP:kV6չ͑ \Esw.MrrwxԲ5R8XVVSs39 #^{sF]ްu-ܲj*[c}DS| R'\zq@8¨\I%{fK+Tku~]˼rˣ+imʐT2T͵R2~iq58xVC.}CB 5WK=r9̊r?RI8w2jsLSyi+,zij j6K(B j8q+-JM,gnYV5WGRJ|;$-_-lu])yl1v/:oKAxN4K.V+ù x!-R%Iס,]O2 -Y5Y Ԡ|FGtmAC(00,V|憥#{S=h(,g@qu4;Ϗ;~lsmA4~vTG`k.j/SI e g+l[#by_ rf p.w{m^R%$ZUCbSGB3sz鏞r[mR6z[mMro+7 zKjM1hŗzXZ0n3%sWd}HB:7)JZ#<䣧 (_G+ean;uJKomn Z^B 32B6h# #EB_NJA:[_/35476vh CV6tc~PeZMVoN܎L7~7|׮]ç?i\t)oďȏ`xJOIԵ \uaUAm~ 7ϋx+_YuoKݲƪy99OXτ(,ױ_˖-/cv39`0~g<B,?tLe@{miBW,u& OH{ߌW~a|_ M_~~,, )tf,OK_[-, oͬVNߪŷ0 Csw:(ZȈn% m߳> mbJa>`uCddz*i6,Va[Y/_^iKiml:L蜾nSJ!3HA@bj=Ph][< 2T\VVxSK@^h =pz'Eu[\F2,!>e/Y>\vT_z]g~e~֬z{Fm8^s'=(gtkgrhwTkQMY=ج?|m͡/Y $r.kE=wmEUlFEMH3To(<0)A`NV {j,y_Beg&H׎E[^Mu{yhlӿY޲[ 8le=K3sp#}CUA]SJS6_jY)P^Pѐe5-^i:I@y25oVX+d[~i )gwH`S[ض*fkh.y==5 |KsE߬ۖWm`?NZ-Z{Q!:k>sÃKem;J1kY7\sX_>箚=`'j4<J\f9-ʰQ͑kZ@.y_1pj  ZRguX*`zY76V7tO- 'vuhpմ mG= K/ ˩zZլߓdrҖ\Ow :9P#Y ܪyRBrǂ.\r ]&g7jZ>8>7z\o+h{NUY+/S}?t]9xY9c);.VRBM5[iֺJ~e; yqGwyY5b1]ǃezs]_YsU<`q -f ,U͍[ mR4[{+rq^ }0:bV->&>.74*5`ucK-X+XB-riPO] `+ ,hta4H IDAT?.X[2nFiY+hm4/ ^J0-ʙ}s ;_.!Eӱj\VZNիR-r{6Ah+M?1>ߊ}+, 2Rɺ?sre2^Ttq"Xmؓ>g /Zې}_z݉K5]P.U=ChlkiF v ]XwizF%.sKYV2f6wz.jwr[6%pʳmlAZ) sjyki =| ڵ6}hr_[mʺ m=DZO@?S n5V۪-p-gvԀƨ:c#+Sd@Zn%iˏljkՇR,O1ϵ1lObu8{ W9ְfhhw_?`nwP\ej~:i4ѐ:yQ 2~!,Z{/!yGW2liHk;<ռȃ CRvVmlSP",Sr{z.յ.mHt8<;]PhjZ ZB5S2TׯσW*cԎJn ɽ)뢶[$\x _MnV]SѷÇs-h{i1>f \]Go3?|L?>~%X$^k)yۦ!ls4 /eUۖZ^ oS)υt-77V?ti|9^ Z^۵6dJaqbDY[J7>V5f? fb%hy9[=k{V5ޮaMy56*qX2f. 19VzaoJߦm{@j{ s-^?W۔m=!]jKs˫̹l]YKL[F;e])Z޶bZTsr{i6@W^^˱H/{[sTLױVI۷8lu+y~t:7Zt\!H6 rr!=rր?# =1֦Y)qY[h?R~{jr8Tr=|AY? uiZ $~oOAekW<:z%=lDt y\3mbXʛA55_ /=-g{V?2kQ9]ɵ`Qpz1xy[J`m/j5%e} yZ c3A\QӺR5_~ W֒JeA\:+h:7؝B 1՚p5(ka, ׳+/WѨ|6J}'V>QUyv]MjJwK ̾zoT KIWЭ}ʶT_S-hη V^ܨ^ rm:@:TKyb%KM<ޖFt}J`so_9="\ڒ羐yV;ZOyH+>V)2nŝ0Im|,V~_9!sڻ˿|,hYP\oa#`={**חuUt 򙯿ֺ55qgtKj9.\k5NiaRͦviS}rk{jg@ Y9SE^i|El̀WS;{pm]N۶s pMBbK)PI[=ױ,'Wrumz{yن"/__|?G?wx׻ޅy^h\ZeB󶖗BnoZ=4#2Vi j׏/o>z1pev 3r9xٳ3 xӛTߺu ?8>O{1_qmu+/dLӜrk׮ebbgQ~1o/gxi'c,\[la0==P*'A/bPlooǶm,ˢo8ummmx^lۦ+V8?%I=磴7ٻw/ǎT*Upgz 033Cuu5/^t:jN$ܻwF~ ZDĥtI("R*hRAKz!@:7ߓH$盛IĽTR< PSSӧOiii̙3\t H$BSS?~ϳ~zطoovx TR2 wޥzzzXjyi^|Iee%a>͛7)))aǎ :=HVzZ ! N(4MBМח/_f˖-ٳblEJOв(a^/OٳٳgDQFGG J+jkރEmppso:;; BTUU9L ZݻwSSS3Z0T9 ZDĥ-"R*hRA ZDĥT"".q)KED\J-"RU-IENDB`mpmath-1.1.0/doc/source/plots/lambertw_c.py000066400000000000000000000001401340375245600207020ustar00rootroot00000000000000# Principal branch of the Lambert W function W(z) cplot(lambertw, [-1,1], [-1,1], points=50000) mpmath-1.1.0/doc/source/plots/legendre.png000066400000000000000000000666021340375245600205230ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwxTևߙ@Pj(" HQQ"(WA) FErDE+ P@B iRI̬cBIddfsg{e͙5{ou"3 %8boC44444Eoo44444F 5444-@khhh8(ZpPhZCCCAh E 5444-@khhh8(ZpPhZCCCAh E 5444-@khhh8(ZpPᠸs$^u"##ٷo_ṳIpuud2l2;Za:nҤ _~%ջzxx8[fɒ%n' 5444C8hҤ ͛7'11ihhh󡽭p(L&MpH4C[7ذڶEs0'uנ-6*t:\v3]F_~ SBAE=B⟏i/W_vؘIIa`3X{=Mrqh~) 듽{֭б#8#Gy9q\\_]VShwww@ { 6DT}$( h~) XX/'&¸qg)-*%6DĎ,Zi+)tÆ 8}4n.nQv>ߋʕ/Y{z%u5bnUpm4e 0Djf呕4r ?DKin@^z50e teޞ7G݇'=僗9vfЪu<0D L,޿ٍZ/!|~=tǏ+KzBS!Ow{1R$ӟՕM֐h4ҲeKx"|N|c-7c%_J>1`(|^6m xb\t.ڞٍNQ /qZ?C…pMF7J~}kRRy4kJL?h???Zl (Ba13{+KWn(GE4)}]^An&QY}f!f!kWCItjjj4@>i҇(~^ٍFQ/q*(3x)ع-◘_8vA5+Q3\j| ԫWd}uJ6/'qC?6@Ki'YY0zsvsSʅ.[Ux#۬>ܑ @_2hU1%:p4Ӝ-gp,=̳N-/q DFBj-`nx*w7i/;v]H;dJиqc<<x;YY8Sh~)Oc!?χTVlTb}zjN(8[@~\>zΝ?Gqssb:55LÇg{=ld5np*RIb" ~ 0g>!f134<]uqz#Itze-+ٞR˭#s^8Sh~)dVe޽л+pLKcyr\cJ(o PϻSzLTPF);4y.]RaaФ]#rrx{_eX>LU ' 999.+fVYxxdRsSk>{RIz:{/xy)儭!3?|ލTrxHl܉OS)m2~~a8nĮ)᣽՘}a;4vɡCJa m[طƌQ/<~W ]{N:"aΠ^"zW> YY5e]pHR/O/Сjgfh"\t.k^+No% ";M6%))2mה:=FF~ _AKi⓼<8&LP*-Zk*KIKћeݖ׼V,ww'))f͚8e. JY˷^gE98bFq04}r ˗C@ 0cFK^Qz:^5 d¥ /' "!\ɥEGG{zm~4))|!8 _JS>ٰA7:*KP_D|ArN2;&<1ljS'h׮MP "!\qpE(6ϮPh*qv45 ΅!#fV;7jd %^jL7 -@ۀb,Нv޶#+mjİR$% y`Ԓ|MRVN ;z= h[R,|=fc%w;V6_JcSݫ4nBG#Gnuų;clV6_JOrrg^VZ LfwgpUyMQPP@HH:WSEBZc` KTJ?& M +/Q'11Jի!(v)ST_BWà״_矝I ' Wp'NN+EpYM +/Q'Cp8~gOu>y1H,jh[sHUA.4Yu&XQ9'p(|^6m۪O'~xq淕yOFxN+iF\-BM +/'+.TN:ٰ|\\3Dsyuh3h[sHЬY3<==8e@hߎ 5&T'JaV8 tz.{`wlyg]AEDa! ׋...mۖt.^hQzdwo\&T'"ʌy`pz v;UzZʝ=^,$h^-lIrr2mGioa\/Bc:;zfj M +/O`h%榔 ] <=mg`%ןI nfDޗyz].=H~W~ae4$2zPVkhwOָJ  Pv u凱ׁkEB^n$q~<* M +/'k(cb`evζ76n&<>vx݃[3HA׋`YѲt3XY10⎌&TBֱc!?χTVlyOE;zg;_9OީٺUY:w/ 2+k+qu ,Ξ=K˖-𰭱*,z7]LIO{^//EcpT&yNQTO7\(8@vй@w ʨ8wK,VDFKi3uSjm 16L_LRV#ۍG_naS Udڵ,]NϏlK+K$4[^gddU{ae4!vA>_JC{U&YY>NϼA,jIѩnjD\͚5#11ڵ>Ԍ,joc#5/|X~&旫˃0AHh],ܽԼTqկ< ̤oMǥ ~Lm9@_QTt<;~G֯_(>}BN8Qk+Zr퍁oaZ085/_;~#brp⫯ȝ4 t:ǰk),ڽdWBZ6#,8<ywAAAO& __k:t C!"Nȣ>*SN_|Q>3ٸqSO=%O>ۥڍ;> "DFFZe SP-/ZOMco/""uꈀko,ߞB6=gqSϝ9Źkǎ@ZaWT`3-ۛիWڀmWHJ~? **V^+| v_5EBBS|)~1 4='i# ,޿ZnJ*OZB%Z%ע?.+O$[8rUc0tyNS*뗔6L >>J )|-BS!3̤A=K8 N :]VbeeeYݟZ PVD~b>'r|2G)J+r}U)ݫ,ۺ:vT Y$:%|M]3viwϵيAg(T.$Сz^]ϻmof؛o}ڊ<rS\>pC٘eޫ^Π:tAוI(KCQKBZ>kY̹u~bԍ7{ÇbU8e.o'!!!!DEEBkF|VY }^CyF."V\ koRDݵ+!޸rA_K B3I$G^Li)3. ᘆ?菋W͞/gKrss''&MիPF GY>y33e+|K_xsѡCR"aL8~growd}cxyY.tP;.:+~q9DBFX+3TZmﱿ&UE85n>@dtn:&egzɝ_I1 jU闈K-|{Ŧtԉ~费 i)Ĺ%8 o;Ln[ZE5нo]BWApɟ3[i]5Ot-ū7}m T 5LE"!+}f#5I|?rgqB[|_~~lPnz^߶!dep!wȊ8*.UQ9'p(|^6mJ:Obf=m\6+-@pe)Z`x m1'kR_ywٱM4֘^{4+Z~dzzD K@α\+7/A*uh>*?w~Xex8qV/N+ A9c28~jf4%imL싱D1HЋAbUw[{ilzM󷚣83 "ȉvGnn.Ge|Ze˖/}vǫPDp< UJ>duG&>muǏd29eztGe"!(zӦM9rnݺ6[ŚckX1SOVU0嘈?q%<~\j|nsn ko$x^0Mf4F9).^?O?ÇIJJM֭޽;={dȑ4mڴ,,xIE?'&]#i|ݼyo{Un_VDLܩݹ59@N+ A}ya >>RV-cU޽{ 6}k6e׃P䓽T"i0ȡAxXV .(aab >.-%\777y駫~ZsɓEiҤYF/HHK "m# IDAT[> ȭ_ZmR:>}ZӧiZ,uɓ~&vpDoJjnrd̘ؑk}@7\w_ŋe̘1%1cHBB֖ɓ'eԨQ%c?C5زE һHbb͌[ä祋х'fz0%gK~zdʔ)h)Y"b:5ĮIK㭰Ӥw{o:`u"GVSmFAu>˨R ڵoqϬYjTUiӆua0hڴ)k׮SNlݺZ[ w.~VR%_t *+1 )S@^!ܸ"Ȟ={{f$g'|q}US,٘I0Ȏ;$s6Th*ls&g\lN@&O,5`mdddc=V25k*IKe-f;1b-7=|dPR*#F {OGA;eD$Q^/M6= v,B{VcRŠ76mS[~No/rssKR޲~zlP/k׮-Y=2bV2 Vs۶"Vi)|VF!"nת~N==iR^ߪhT$i۶6!KZo~ӹ. raUp,ҶIx-o}9 $ݻw@6m*H3gΔ37_\d&zl4&ܔcj#D-pJ{ zbVx۷=zpnV߯zQ̮]߿?O>DGGW<8&LP*-ZkׂomUJxOϿ2IGGם}a1N- t![!3 RX{Qϋ'ko>=}hVsmS~}[r`o8p ϟg„ 4h`UAMԭ[͛7#G߾} 3g_?X`3<ĖYY{Q)Q j>BS?HşwgNϐ-[ ? hq]yə3׼#C z S7(h)919.YB{ j~L&y饗wwwr*R8P+^mw9rªfn,O*{C=$lr-š={سg -Raέs31uԒӳYFEZ} VSdYx&kA^\ֳ1yM_z=K,GyM9mdsapȀٳӶ5R.KgEDa*y<^.o__<NoٳNGJNqt2@[Rn___:t@||<ϟU /2mӿ.j"?._P:Z ɲضm<R}n;)d1mɓ'STTȑ#K;RR`07||jt }䳲Z~6/[_qzaΝ#!!;[y}[*"!@޽ؽ{-̹OWO޳~{$Gc|Ʀ3EG {!//Ӈ̝DYr/&L?$??Çw^兽{[7eܱ#8ԳQ" .g)ex-EDHYh.[9ӧUc9N"•7&-FH~e,ܹロ\,XYpJ:Qڤ1k/=#;;aÆqWHLq`hvXJM=+ /0 duه+޾x s^<1sj ED[o62yd1`;jl\GɓrM7 ^ do^1`ёb.r.,/Ϛ%9*x j+aBuR$%'E>cĊ$_~]~ PޚHU ڶmK:u8p6Zj'fth \ x7j$pG 1b Kqo-[o')R81D:i5)NbMLRurj| %'E"&: AxT,{y]aa!N:q_,)tUDBP^zo +W;3}wʹ|h1M$,**bԨQp}{g؃tƣ+95T*k_ݻ⣡CyIxx@>`x2s4y)#GPPP@޽2]SU J&M\=yGpӻJ\FMu$PD:u*Ν;j*\\*ܓ[d3˙Ϩm^xF˗˾}o>~iվl–>ˈ#t[(nz7_0^2{U7@N*Bͭ09iZ}؊M/[3ՑD>/F/Pvme-u%Dߌy2D9i`xMpqÃ~&M7߰pBPMlᙍϐgcN9E f!yU2PA!Bg"yvoUĿ/ rdؑqyEy%g;Φ;?t:}UYX_P~<&Ҩ+kW3gʼ%z^6nTJGfmZ!iqk!]OiJiсe-y]V U"!@:uh׮6 {;V*iɒ{gϴ 9r1c "\=zTn>t 3/Wm~Qf̃Å Ss'y{׮]Ybf1cpIl[<+<۳,ԪbHS7z^.\ ..W+ 8eHXбc1 wk^b(:|yfme-^p#Füy=zUuDS'IۜV~TKV/a28=üdffrQfl-Buk2} .],?0 4@WіVfsqp٫ʼ;?a,? 1T"d&11q+o;Q8qgWU =z(5Z]',n[oqØ1c0l~V~9 +QF|x+R֦`3St}\j/4o4@WG$ o+bVӗR۟/L$5zGyS$\`t҅?\-7"`L&}-[/k@^#F([tRzo:o&QY{~y /F|A=z 7[sDBDxyyIaajdhE's?ӓB(кT߿_\]]f'uf9 1`Jaz_Lz;LVuy钣lu|Mb6eQB(2 s2G dO=-,,///&@uDBa%//cǎfOg/5df~X{|-jvC$aرF.\h4N6Խ.ѹDoyqj%1 O?wxrC˖-YjYnֳm|=βUѣѫWbJ1NTW$9Q9\\{<`Q__Vܷr9UlLJ}̙0|p&Olӱt::|>dg=>ڢ-U֭еRwo8tե뮻9s&7kPY9ug6>W=$$L4|nD4@[8?k.Ul'f]치Axs3牎c ~'-[F X|MKRۅ`OR֦p3/f3q\ӧCX4ibեyw֭۷og޼y_>+"_&*D{?moSǰHߚNnrM+^)Sy9ÇWmFFHF>f)DQ+=_Ona,;*[DM5_ٰaC[LQo0H⇉k_DG7{{Y#k^/aa5[g Hȧ![h#܎?|\  g6aÆ"Vh9h :O>HddUDzޤԞ_9d;SygfG  X""DܶEUXrҤItRk iRZKN(L+00 cNœcǎ }z\G N6g7|-[GnL.kqwg?lӿ0K הH駟Ӯ];Șe׏vk=6̝eЬ/_~ }_)lan'fRKF],iM⋸fls>?ṉ=Q:闼<8&LP*-Zkׂΰ[x1Z⧟~bɒ%52fu|tiԅUWBYD{s}C!GAAԪUKjժUйse6^weYeK1ǒx\>&??_:u$,X\٧ŀAv7- *96VK% ^3FVM<<<ȑ#6L"#mq]%8 [NTY]*{nG\\_~%1*|eTNuwɩֶ43WuNgؠ#ozS|cՋz'+ѣG4hf٦Hui^ <Ҁ|s+ikarC0p DD(gڙݻRPP#N ੀJWٳmVg}%KP^=BBB`?~\-ʤ^=뷒V7a2r =N ڎg5#Gxܾk׮s5[neѢEԩS6:B :dGdP"%ߵkW0`\>22`les$3f;$::矯_<I> 惘gKE$Km&`]#''J˺o̘12i$yKL&8qLJm-{Ut }MP"~o{d6%'.NdP%#~, .HÆ kl<+Bi(/M""qĉL~VdsC8oJO>)n k׮gҥnݚ%K\*ubHСC5j޽{ʲpӳ>치<:iN\:aq[["O?͹s?~<=ckW:m{;痟'~NzVf;*FҰaCV\ IHJJ8>+'.`ү|4m_BA镯d߾}о}{eO3<ÓO>NMJJ߻5kFbbb͛7/^Ÿu:Cd2m6dA\|jcp`Bo %(F[dY>; WX?@pp0Ϧtp3.&s{|w0c ?~41{Sߓȋ[6΢ׯWՖӧ;w.6{UBS0LGe%iPcgӡCOfΜ'p<8}=|mFGGszrg=]f ۷ʖC?pB23msQ+M4Irssٳ2jԨ*ɑG}TN*/|gqF12qD6mZ9hDIIIHv*7<1 N1XWrR%!W52f1ҫW/_ѱI|sPS $'\.loıcC$""F^qh. d#C d_}` @TrЪ6^:!Ӯ];$1z/ŊyfcŅMxt"믿.KYms^AERRDD$UeKA5G}T2Pck"q5F%ڵyQV-VZ:kmFQrNQp2:lڤq lDBu cF͗.ӧOgذaDGG3{l-Y.f7x~x~|>)?Vߍc*.+ZLq{X[l+˖-c}:qqq<_?߾]AREDDw~]{jwM!NXa"kiԨ˗+O>Irr}|&7Df$SG箳hd͸2p@gĊtVV,\PJW';PݙxqⅭؙS\r=dO@.}i6o~)QɮkP[#"%$$H:u-[XkyA%0{z|eMKvdlۮK}liӦתI\z4O!hG֚i1Bn[ $+"vSL@>sm wEҨQkV^*mdjb fLutZI<=Qd2ɠA3ge;&Ҧ[P [@Y~I76mb/k:8 )QQQ'YYr⛅PdkW/Ήfy>XrzJ߫tD *` '"""e6Nm ?Rs:/|u|SߞP5jLs,DARELIƍd2I1`=],ө޿ g>rX ,^Y rfYNN=mHᥚEZC||N?_*"]ONc7ɮ E:`yd2I``zpd6Vk$, 2`Ξ=޽{I^̞k谅XZmލ_~ٜ8qaÆ1m4YYMnU {+浢:޽ȋ#HLy[:M6eҥ?8iiizf+Sލ{hY --/SX@{c{ܹs 0 -8eVs'l Ў̀f|Ęc,.Oa/^?+Vp/!YIcq\ӧCX]H:TR碣CLN QHHH '?&ML8 !//Gy|z-uf_cϜ~s@ 0c@NԧՇ09v1r"m̩WVZ޽a3Y~h9>l}|+>JzWVęg0irS<<6<<8[tq .6mZ|&'/,9/ԩS /"u(3Ehk8i1` vHNt:`yחPxn6& .1T{G/-b-6v=|p[0O>&q: G #ԯ_ߦ x"f=[Nk/U,;wJ\-S,#G@+ϕI)2˾$WRRR]j$-h)S /|sO4e„ {g䕾; ; (U2#*jVuiVhuێKk~ڪ?Num]"(.hE!!B[!yz>ŻyhD||Sra]w>:)k+z=cXWWcNqtΜ^s4VڂH,B"|BsTWܠs*w&|1s|.C~~ujb z3Wob("2L.z< 0 W H6m`ԨQ(**Ž;xo_tZ/oMOOsUb4iܸqbbbHq<%s'ۃ]ߟ醛yZ/vmR@A9sl~޼y&MKb26=x穫M"q5^kyŋD\pnۖ(wqui͂ H!RB;uk;̆_4:ǂjee%ݛИ1ch VTQtTzJS3ѫ={v{!b2 Ϗ8`XIX=_{ ]Fz͟?~?@"h#S^vEj{viBt mWִF :ynpYFYQ$ā6tU՚=zH"Ў;lWәhn@L2V:a|r@}q.F,@"VO]F~~~e|c>ٲe bJs'`5 %'SJ`ݟ~-(P?3I$VxHWD"@N9:yd*?\mZd2ѭooQ d>|V[2CU~ XLb6l`@/r+'>kwjʨ}VXгhp$,YL (( Gȋn k׮%TJ"</fXI ȑ\ߟhfWvSo7 MKv=6Jtqs̭zf38PpR*klٲ$ D"JHHqNw_pY{tҕ8V d2ф v{jyQ/sۂgK÷yb;0 4sL@R֯_vY.8GFYI+Gy7To.O;|-V=Dc%b4J4c"pB2T]N'ڞsT:7| $Wۨ yШ3ұct(/;;r]Nx}T*ӟDQFP(!3lZ".8-FDoEAM ܅;M8w9~J (@T麴Q]۷ F{r8d9s&z8=T&ӧ~X9 TJ(..kԥK@:tkoP' _fh2 i膡8tK*a%$RL2JJ ((odи ԮI;@ќvLa\G1Ll2@tqz,@#&OsW[J2{GZ}K^KKKi$̰aT*mfoEEq94(a2hПjm Z< &d dIB(xq0}w;d2J LhsC*iX&*JNK ؽDR ґ#GSa1 Ow;m_;wk׎vehh4OM65W[jPSAf؞=D\p0_pSy< ^ız&_$t:*RCT˱ct;vƵk(66D"PZ`[D(Jڼy3EGGׯb <`IxgWu+Cۊ#9?49b1uԉO#G={R@@|u0OKKzͰ{ LF}mՅdM6Qeq >(4)ՇM+W轝tj)XOٙ2u2e˦;{,gӕPo2׆HAoe׹3̥K5jD4x`1bEDD8߭[7JLLtuiZDD⥮w|_(N*Fhx#;zGΝ;k.8/ЩS'5 &L@֭יS1cKnH@`iR,N] ^HbvөmL,:.mM̘oo>(P}ˍ\!!?'9d=eʥu>GwWBå(=\ m{V-޶._;wHMMNq]vի&OAA$]Y2@"11A4& JA'qRjieeeP*P*hܸ1ZlWXnI?@l,f [qVƪU6} g6FȹFXՅ'oǢ㋰~@g& F+-`'EO+HCK! B%"tE:+˵Тyls຃{]t: L&s䥺 yW_Ŏ;t*UhR#t;I=s/W\AL6m+S7f4z 6߀e'Z5@&1<a0k (M6!b"r'}?߅=Y5jA}Z m!R@O!.> O lSr\p5PNk@v6$%{s1TL1{r۴oe?ot~w|-dmwWp~yKIHThLn:&$^U@ #x` F*{û7ľ54C3 Ih#=zpj`P`fI{.XW:W:3w`Klފcحcpz?;̺4pE$LơpMz@ې]#ss" {5aO?Jjk׮ïQQQD"ʕ+k׸qm|ܯG׮fĵ+z’Kpi|37!U bZƠOx @@۰5Ldf f o&PjnȯunӪ`/k, RfHJJom>/a0jq`hP[rT7HTuRX͘1OKBB#+\nÖD loGfQ&v_ݍWwּ"G"L܏%00r5||`47q6yUr?ܿyVj?aX4LqbjohQ_j6QZ LkoYmluu.0M Gжʣ\ 6zzsd$pM`Om0],aAh[LB /snз/~tl0d$$"n-oxhSY L e֭aq0:LK&@9L땨]Y/AoF˙@h(ޮG1:LK&@#Lǧ7͙ܿvg %La ]Ih?h (s#h`Əu.0MN]&auY$!柋dށ<0],aA2 +s*+!g r9u[xХ W舧 06.0M t]&G柉իrAWIn30:LK&@.:1 T**U; @c%La ]IhYޯasBNWy& <8v 'UcƏu.0M tm&:Ȣeܜ޾ p&c%La ]Ig=[|Vs8;fXb Dx4ۨ$tB`8.lc%La 5М SR)tǎq= 06.0M 5PsY}dJ\"`R` +x DDÌ0],aA8n)/ZVL@|<`Əu.0M GLBܶ- 06.0M &!~?{ ϛ6qSrrQ%QQoc%La IrHӹZ-]܌ ?aX4 Џʔj6Zi`\@92:LK&sKx$,K+;CԹS!ic%La IJS1@r2Ъ3~ti" 9Q \-:@)-ko3~ti" 9~$,;7xoWi3~jb D2@?j|-^ ;l'Ì0],aAGMBste%L{$`-nPWFc%La ]m&Ϫ ~@~94P(3VXY0:LK&@$TgA:"{޽\93眙(@c%La ]m:6bGJ%Z0:LK&@$;\\ | q,uh?aX4HAAA "A$AKfͧNq3 .]κfXb Drhs!0*жID\~+xtf0q ?WTSpeB@=ufi3~ti"  ׀l <HJj9?h40d¶@^\p:[g?ti" r_,O|ZX^gsfZMۿÌ0],aA7ZFυN!!B wv0d:PJ9%7(* oDD?aX4Akj<2&F̃qy$ 5 [VLK&@ b?1cr9g//QBnfXb D2o⫗_ҵm˥4=0],aO?{Ź˗cҤI;v,ݻW]܅<(29Tgؾ}0],aXGR 5pk^r%kq\"%%k׮̙3f͚E!hu.nS)bLK&Gnn.MV؄ [oE-iӦ֭[#??y#7 0d{.,b D$@GDD`'7mEEE7o"<}`֬Y "$%%aXl^R|wh޼;`0ní!L>DJJE^|9Rj*4kMt=~)J%j5֮] ?{3FEE!&&+Wtc/]FI EL&LT шx7uԦI^^FcǎSRPP/YYY8}W3^CI&//* k֬QT\.`0tn݊W^yk֬AiiyoJJ ڷo߈@JJ{:jD$!(( ss/]OV׼i5^y|O tׯ9?ߦM9rdypa <5u4hgyhժN'=b4iݺ5`2K/aĈpsoݏW<.@m(>)X%//W^{hh(jnqM7o4#-- S~MR&ՈbA׻Wfu̙rT*$$$HJJG}Yf! HHHT4 &O`]vUUUn+4 @bb"F#"""矻.E`̙8pF(|&@3 ӆ`LBx``0<O$_|<7\f0 Ќ'!C@"`„ XjLCxb}6! 4$>>111X~=fΜ .1 Mc0  Ca`0< Ca`0< Ca`0< Ca`0< Ca`0< Ca`0<db[IENDB`mpmath-1.1.0/doc/source/plots/legendre.py000066400000000000000000000003471340375245600203610ustar00rootroot00000000000000# Legendre polynomials P_n(x) on [-1,1] for n=0,1,2,3,4 f0 = lambda x: legendre(0,x) f1 = lambda x: legendre(1,x) f2 = lambda x: legendre(2,x) f3 = lambda x: legendre(3,x) f4 = lambda x: legendre(4,x) plot([f0,f1,f2,f3,f4],[-1,1]) mpmath-1.1.0/doc/source/plots/lommels1.png000066400000000000000000000640361340375245600204660ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw|S?I:IB)P6_A_Ad*T*,TdBڲW)Ph]4i{~<$$m3nƅ~xEoxrzs9<" DDDDD\ 701EDDD\A(qQD-"""⢈ZDDDE":hEt"""".EDDD\A(qQD-"""⢈ZDDDE":hEt"""".EDDD\A(qQD-"""⢈ZDDDEqsۇ-[@"** aĈ0`ڷoYf9s""""Nzѵ6,~y/*TBr$EA&@~ - o ?0ǎ{7! bƈ6tHhIxN }9{9- bƈ6t ZIq IU(;YVc1?rxB2Tݬx! bƈ6tv ׯ^4~P9Po SG"b fha Hm79 `@`(6K`P1і7녟]- bƈ6tv 9 !P(]cbێTVP <#<~ Zqo:hQ3F0HfR)kп{@׮@|<_w>m~x^l y;9Pg:+# bƈ6tмDL | w__`6Xp1܁>’`8,:ޛE1M 4",ѢpajDG|c Pr2Z E fhat'w5cǎxװlٲ*TY׮|Ii{5iS &LRpBf~xM(#D8A7m?ӕH$@yy9k"«Hm <40xp{yUϞqܦhi0"x4OGT^:ފC1MtmDFFz "ʕu 0; pЏXm~t;Q3F0pYG*" ư [nEll,bbbY>V͛#GڢC,fW^ayֲM[c AQn4C9\mvkemOFll,,Y'T ׅtqJ%fϞݻwc֭"""ネ7BӡE7o'x:X8pк5ˑ|ͨmpW!΍8/6D,>>11Ѧآ@C }bx~ PZČm" y ׭cf95c7nkp4'ë[z[u>n7NDA&@J´4 ) hĉuzNwΞ~{k-V#DA\Is'{}I3z4ܺeilGu{;|BBJ Usƈ6t6^G}0K/UUVhz~_(GJy91cDA:hD¢"֑.4S*u6WgQyrxyX= ex91cDA:hD¿fO<d woqc/ڊalCxOzP7fТ fha HmHgxCT>eᶔw _w+o<DČm" 頭 xQ~3!"+ս0/G"85s_A]Čm" 頭 ′2r^DŽGaJhq˕PPïm+S}ġEA&@j?+ =^^a@E[LHçs/šEA&@jP`C7;"̡8ضޙA1M U"a~> DE ez P(C~ȧfPm}W17 fha HmH^u,5zrDWP ۞Ƿ T9u4 fha HmH_Ğo]﮶v{%(AL[EL':gqsMLUEBa HmHw?X2W| ϽAh)Nv9o^ETݷ26I\nGQ$t?QQ CIB d>2| ?~=gJ iPTi*>'{yogCR$MDU~]a H( - #h8xʎAWCH=3-|euךZ=1e%΍<Nš-a[[ BPgR HGv%"0X$tTY쵎0_7>]vBa{ bDK.A[EĜ4{$I}R-|:h_>LX,E "zyQRwc^lg/A,oSçZ|ܢdr:t_OQy@ E"#zrX&:)[|vY{?zPqh{ESWmVԽj%pjfv"0H$:4y4~12O y2OCFκd H( - e}g0QGࡼN!HݥmWvH@lg--:B I$JWQ$t޽3;hB![^A(ho@@;pvX߮}6UU^,A "N<ڀooAMx8fj*paXSel 6޼^^!}Lqh>) \|dhLa/ǫ܃QTk.ÍPYMl:WkAxU K8дiS@͑Y}EB}W/>g>}XFot'~K`Q:ePP#xd0ml[ǧR%JJx%"0pIt@ZZ"_NII֭[@jjg^Izfj?{mkHݳ׊DzD:"xnLL>[Fqyqs1_i%/+Z8A%11ѥFvibɒ%()qò.$D3.T*1{l޽ÇGnaÆaʔ)Zƚ5kj7alذՀ屙3xρUpo4RƦ |Z8ڬlXIBq^n?:Xpu88mҋ@H*u⌐ YSЕ o5boq Rj#rV2ڵkk=,Yְwo9g šg 7mjLJ]6iț+h\#n|MhyKj輫3RS!J%aH 2_:e9zJq[G=ei9nvB^)w}Qn@c!Lm]J@F@x69؂g'Cv B$)u<2Zk^m׵_̯2[G^UϷQ@ !n_G8{ ?AjKЖG(.y[L( ?1a!_dBF!y"<yѸF6ϳ'Oj ]Y_g0Bbs :&N )z Ϝa.&2=6)(G(OPh]*+?d[A(qU0,&3@OCwA.A7Y 'A8W^E~~> ǘNY8d,u-ѢH)çš*Cl.a׎E}1qhW 5ρT.Ep aAW3, lv}v؁իWc̙|^j ʀׁ-M# D*a!ۍ쁣С  ,Zj력R4\%=ÕDB v@&Az:UڀCa !w}ݮ'69[⥗^»kLDlNx/yf'ٳLG ?V8s>{<bb=`<,B2oBng8a^.w%@144$09 BfϞH?G`R$nb%vҳCL} H$lqG)u$Πwuk`6//_@֭X .%K@B@y$zq%P}6ג#@ ,WFL.$)\v#A^uUyfw&0>3o40|а!n3x4{_9.Ɔ ?*ecg=^ͽP?^*"!@" dc O=^bsVbR$ǟ]@ 5硇+_O?(/(Qv Ν f]XwG&MoOƦWzaS&$%zH}bT> PIuXn\[{o+y=%KP[vZnB(-@U^K.IЅfе z:w||'񄣅CoV9zX͂, y԰^21o*ܷ[7^hǬLc! 36ꁈ WGIG%Tkׂ1fWdIl8kNŚ5X3r l V=(8/'p` $HG+ b DƓ#,E[.6SgJcƌi0w\4t-[ftH.0{Naǂ!hǷ/ Aֈ|嗭NyU9^f힅r5WN2<--e%%@UKJ{Q+|:/)JTR՞8A=z4VZ"p!Hr7M1 /]bMv:wfYNZϗL.OGoQkB($-bp!Cb!Wo]Eu}6lSNb2y,t:ϑ6mK`S!1RS p@uJ%x10p ШAr\޸:yr}spBӦ>22oH>|?#V^m䐍DB oA"? C$g?MC $&=z>j\ك^k{\9 :idž74|9蛛olNStDDgG*" M~)))غu+bcc;T6mT rvCʭBaBTW}?R[23e,111 d H~ m/H$]cөMx|(^=58JXǏmnaӀM{/d <jt(;VȑĬ,goP))H$nRoNt}oBFvlx{:^^3Xd JJJRQ9 3f M>̙CW]vQ||{&˞-!tvٚo$$֮Ng9w_M I-~{u~g?PmѠ5֐ ߙoyMR@Ay߹h f6m{gaGF]˘ʜ+2tj#,R@A^DD&|qcТʜ3$ N"Trļ~y~EE/RKqnqt(P7qH?@{AkOu4e \I}>>*h wS.)ɩuXTTlv%y]kD!3׬ի<4ёGHUWZSS,6R@x8}_Z㭺RXm@%Ǐ|")7 3v"d2ߵ[oiWX?L"]#@D~heC,5+"Hm Mڤ?o]>gELsg&n9bsY-$Rt&O/{2l=FImh L+kU]^&ug6oc;O~L1L;7sq88 NO='"JZq 6'oF5޾\*JADB?UN!`W0&$4g48h7q&<+_=DXlq;ʿkRCp to)#݇E|6R#b`zaBz̺W4``!*zfD]9y3|ðrJ΍:i Ea1] O'>=):hJADBpzEs6Fw6%̞tӇExxLfX=:OvHH[Ŝ={bN9(*Ǥ?&9=ԔwkMy ms怔J|zSz"nB^YiwΞF"7MiMû jv?AA?=CBج $?lַl窇?$ f $Zؼcss%AADBE6>ȏ < jЀ͍(;." ) :~Jv`MNLjFc#N^WQN3^'D?D?$)suO ѠWլ93h(,,._fNҤ_[EB|e/k ?^m ~جwH=5ckc2>K0FXի, -laӻ{CWTU_AYUmFX,A.&Nd? ֮5ibcu=vv6[m.\݃IpKv_Z#c 5-["}:-ܪ}avamg9o٫Xӧ? o7oM|t{A:芊 ee(;Y>kY@0%9Ľ<ϚH?/ޛ/BRT8yΆ۟O1%NXfu%mliܼ *ͲjXm!!@P{tW3ϰs0̞{w7ʓʡ1-և9"aFI^yqXt  ӔV=2T(=V (oth}#b!K,$Tys"n\z ϫASƌt'O2 젥TLe *,$"4G/QMѠ'W|a3jsp9gVV*8|pE,矉:vIԹ3d xyU* nF 5]q;"Tj*ך^h]3kyp ,*U*Pw_৤ 'rIKq5Pzaիh8M|(+nFq1TJԤUԩS>v( };O6!4DŽhC_Np_ŋ@4kaSʄKHŘ UJj-!:j9mV;܎f&ڽ%h.^#k4@nΗG)璭 w+s!o]?Rk;=)!dIQzu:3gm#S?x0㏳3>hLhN"Nt|0^SO97 t l ݻfp혅"MI-i0+MI~kC^qtaRH6=`e"I0 С1DoΜ!Hڄ?2K;-wxO[{j-!ee2C?smذ_,)#Gl~HsGw'DzIUO6#:rRWx=mD> cZ}/ǟeQʾJ%YvI 0g ]% fbmbbQ^9mnoyׁ/!4ʧJK͛Qy,5zyoD_ 1i5:sٟPWyO`>OgRe8 X6x}pasدtz|creoԅD"'`@>wl(d`Zd"_99ֳf˖fRRXW|e͖ TA]ʎ㩃ݺQַY6DTTUPeѠg6Qrru?O? 6KmԈHY]E>w j7myy4 ZvԌ+WX1P@Af(1se3ȯȧoѠ9{ޣbxl_?u>ɘ RMb 7jr#ެ*?Ϸ:>{vuizf;v'HB4hs[Hn%""ۛp1%A񤀂 ;kHHK I,n@_!OO9 Juرd_|aj UxMA#?>Bkd46wީY&DA&NdB^ jCt@ -v0d.:hdna,]f]8{֣jos7((MlJj*_۶DG8 zq# /Ͼl8d^28k<8uʕAB<88Vw59"G_|íyCBLqiyPP6{7196np?sѠ.+ʍ]czc%j.r[͛>wQ`^zݐs6D=z8zѩO٤[ٴɬfh>;)ћ{$D:Lr*5SvbH6lp8老J]HgQZT*ǖf$Dmω_yxѢ:w:K;E %ڼKm? \HW x6MIH0ɋI.պ5;fA> |xD&8zZ%8?Le yNwL.ݨtD͚ ѦѠς-yi9JM#{; [J$,][k?5)ay9oa!bhP!tm'vAzcUz]$dj,`)mr!.%Iu-(`w77+WH8Yj|KYqSGoAV"NVgKsD}K/ԩSw5lt4i$6mM<ђ%JG' ts_\A;5:++ M6DFF"33h{ $#:1gc Ƽ/DtH=h}[HlkO=pۋ[퀇$T*mې $_-] k,3z`~_<GTt@zz)߹=-- 5sWƻE8}]4 icIn&_؎vfM+55Ր_׶ )HN͡lRmf˶F"oΝ{B.WbN 3+;;qBUq2ǺQpEc ej=/ BQ駁oMr9wZaC KfxD<,RϔX 8s~CZSO!"`٘z5#>kP̡c$~bb% E_ҧ2FH@"Xt %VtIĉ@׮8zTW_N|i'<<0{lڽxo__$^h755OFll,,Y{lrr z̘14}t3g^vEѤIhƌ&cЃZw? &?4|aNwkE#귮1>6L'nSTH6Nt=A*{V|BNּyJsJ[CY*F 00*58JKxyI^kޗo>TKPUk=caѠ(¼J+o]a-17/xe5)K7.VGINN3m[Cټ !'z]ʕ1y:-eWl8yh ` 9? 4iR{>bϡgN{:w7hoѠ>@b`u :h9r) [Ui~rK(8짭>>'G_o4ێ&^}q O'^6s(_'CXm-k!i Jza hP3u> *bIJź;&9;gɘh5Q/ŕzYkB4j1/͜S Z󈫵;C]ޖ+_O53Tęag{BcYsd$ѿ~;QiTo]?B4Nwf#:hψ'Kg h룔Y:)(թuTu8F ((;rΥ2uH?@K/11c _;yM7|E_VN(PۙPYHopΗhm]rᦇ-͇/n` Q"ُw:N (2페y-n:fL=|yC!H.g(Qt;"g6*/T&VjW0#|YYl \l(9;% N)iH{Kz4W"wm->$-ᰛ,iBľBm6; P7Gгnсu˧Hx5CCaύd`ñ68Z bE72<^]df!3gK[_Ji@ ID,ܨ}]d~ͺ]yX1ӨHpk`Æ>m.fGL7?Z`B{>Tr5ƌaדo4߹,myFm[EAzujecB4#_{q-g?oYw8}w߼I/ie=!Cc֬Z?ˁD O2ȃ];MHt<` b.SFqKyNSb(3[俿&o5g@n.t)Ҳ2Ҩ}4N=o죏ZuN}c׿]p\u}+k3IL(%lL"V%("ŠUO@c??fX˰RSIt  BgΜ_5kRX[L~;U% %F%Hcq E>/6-dո?H r[F+4f o[4[qt"}szGkhwqQ ("@Hxmn.EJMˆv-]&?6RH-wӴ 2]W5(VE+2r. s9_/^ٜ9<{|;5PlE$>][/H^hT$Pr.ޔ5s`QsiT0;:L+|L]kIVԚTW_D*P5zTQa͢\YNC60_%eRb-粈eK^Fi@q[J]2OFu+QR3;L/b9K -r~8E_}Df{vrYbxh 9XHT\QJJwjU5|fm0CGoѴbi5T(+h/ 'w>IyylcU3{{pfjf-:Ҫ + }n2g.YqݨY\v:Cn/biMOm-[";sOG_G^| MB3TW~UNb21˝):c0HAŊ5׹ vׯg{0>ȜbNKgR|r< 2v0}> ed5q-qkw,t]JyMwoncv蛛msi4C1le"ܥdkYX´c\B7!C8U[ۙX[]nCYb~]&5l_JH`-]3f0ϙcQYRiyn4"qmb!'NnԍY_2d&)S(ҐQ%nc(}}s@s5j:v?<>b…ϛU݄1!$[SB̷Ɉy٨:<{(y0+ 9X'Y&cfN7`DcPgw {Sf87*(1=\W,|faeb9y)+3>>٨Umy7Bh~!;G4k1|ɉy33;~~֠Oph&k)X}u+:]x GVCUJ/bdVVbOZ8+ 13v)¡B .xU,W_Ν;-ڧغ?ٴi@|<~rww "/Ԡ*W:p&W˯jU* ѨkDZ``x +Ax:iuwkRuu@~.[Ǚ~. QA!`^.CC>Sn.0x0;׮^ZC؇'6aq: ? OРm@mC-2K3q80~3jjݩ;Cxq3geȚ܇>,q4='[۩ɠؼx 'RW H|CY[: LB!JV9_?zT벧l޸`sw78ԅ%uuuiê,b;3g6]̺gE ]Nzdݻk59EO:lg\7jiŽ9wY>-Ѫtҋɠz5봡R{03J-5uvr"GA ]DO?m]һp$B׳FE=y8#7س_? |pz^Tfʍ~'%EHSn)&~͒Tj^g\*+,nb6n c[CQt/蕃){ЂkI~|_MD5aRڽʾ~tq H`Q!1X_"?VQQDP X%͢ej5]-b}Nݧ0J^}ߜqZE?q ~( =])*^{ 0{1߂A\\3mx~͢$Ld=0w. S̖]\%-X./DFWW>y@$BBj(4od˵Rr ~nf4Zcb .ysFjׁge  b};xy82t[RLAA &YdAM_,;jJZ:֍dm|DžШKՆZ6R]c'ٶ>\gϲ7α[x};?T_a. ze*>[VВTж8 E&ڲX]g{jW!7?͍=C3Ⱦ l^mV5ORǒkQ\oZ-]T)+3Mh뵔FNɤ5ڭIZ^6O`u֬a^ɓ7 E@ 'լddV;Y[l,k`At`֛M ҁ!-W^aKZw?ŪU6E_tgPN@(kA^B%#rhV&YϳꀅS}J%ن .*6YRB{XhYkQTiEq(Z #jݨnzȧ"V$J`qqܼiT26uWeWFq2SDֱѣ1ELŽBfII}uqq'UӗۼaZQR: KCv?AZ*Z_dR$!kzϔ:uo5a;,.TcLt: R+hp4!څ_eJ` ۟\)Ys$q1u ׌eLaO۷Y$3!6RkϯԞ#9u)7ɅhEavS?O99,.R|X{':MPvL1U*Tk+so*GV+`wo67}::4 8~ ; pŀS됳0uuufKZBB &n%u$-4[XXh@Fc"NuL eߗtfĽ}w~3 km\Zׁ۷1r7ōo\E!w󁞨H@Wfa>jcz_ΐӒn8TUUٳa[XXFggglܸ~=UdxࡇӧciwϔɦMTўJBjx>n|g8 yfpTv0N=0h dV/7w6)?\pvwFPc :?? 7oĉEf4 |*I(i7@ƩSct?@ǪP=ޏ6.Jeg|}q"2̈́usa}^=̺ 6d rSt^^Əo >ضmpf1|ϳv> Jj\qkr4V64Vb@yWxÆ iFWS8j s\&4զJZUB֤,h*5z'D.1NQ!!!HJJj7sL`in?jjj}VPP&mpWLg22<=q~:(SR_|ywGfN&O̷z 8{{:#0&Hȉ1{[[o&~dv1L$4$YرđǺUh r}U佟8 ̩c5e" $y&0RTpAXFhm~(4\mRKGe" $P);L>Q}SpU뫻+ F=<ج,DHRAs'0Rw |z:`eJ)5^s_<n^)˥#2TI(?{dN2\u7޻ hlDb\xZ ?z,ut\&@ ; i89"w|N">`ј]A.be" ZnZPg' V@qJR5)ؒ"12TI(LFFF-_e$24qp'0.i I͝pǏ0\.pHI*h$;~r1DHRAs'0# )\&@ ; ape" $P.i I͝pǏ0\.pHI*h$;~r1DHRAs'0# )\&@ ; a\L2TI( wb 4NBaG.SL$4w ?pe" $P.i`W`<(-5mon:̝;ѐͶt%Ł=.a *7"""sJ'N 11ؼys2()=.aMAwJ<[>5k^z% ܀PTTlNJZm)8$\.pHNQ!!!HJJju;5___ܾ}3g5^VV~Gs4CP){.SL( ʹ9ȈG+V={0rH,^DcXv-^Jlذ}9nUA[RܹsoooZSrRRR05 /d7,미|2ѳgOL4 ӧOBK$$$ 33}Ŝ9sn)v:Ǐ޽{h0p@L6I5ݷoLӧ7Daa!~{O899tJ`` v؁֬YM6ƍs P__;>3cƌDFF"77I)bY< =z4F Jc"55SrJJJG.͒%K׮]Ò%K_yFcΝ4i9p׊U 1B{WWW89Iv8())hZ;3s׮]:8"ttt4^{5ˋ8p=:̜9ӱ+J|2z-,Z111pssٳ==˕+W0o<刋ݻ_"22 ,p׊s/߇9A p9]cǎ!>>1cI*#tI"##Yf/8+hN͛C8+hNd֭1bv܉X&#Ix8(|p8 Wpp8 Wpp8 Wpp8 Wpp8 Wpp8 W?ɖbIENDB`mpmath-1.1.0/doc/source/plots/lommels1.py000066400000000000000000000003451340375245600203230ustar00rootroot00000000000000# Lommel function s_(u,v)(x) on the real line for a few different u,v f1 = lambda x: lommels1(-1,2.5,x) f2 = lambda x: lommels1(0,0.5,x) f3 = lambda x: lommels1(0,6,x) f4 = lambda x: lommels1(0.5,3,x) plot([f1,f2,f3,f4], [0,20]) mpmath-1.1.0/doc/source/plots/lommels2.png000066400000000000000000000423711340375245600204650ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxyxUvOwNBv (EEqD!2#38:uhD%((d K$!dO,QvHH'N/u|Zq?*^eF7ʩQE hov=z@ǎu+?o Rإh 55N@DO>GRP^xzN]DP. e@{$BI?'Mi"-]*6kv3xd#Sވ0NTeE hov0a{xʖ. }3lg $0E#,H( #hhի D*[8EA8o"Rpz{=w|~;O^3w]v1Q<@ȂqvnsOLM 8yHeśS5MoepG']D/xr)[%a׮sd"A`28yHeKjj*;[+ "G|יq:;߲͝J"(Y2U@Np0Fg_0!RْMJZK"Lis~+&<(w-GL\D@P. l@k3< ҏۛ^B%--ks7NϹEn(\dA؀`߾}8a7Uր<hlZ^rt .z{=]." (Y6Å^ȴiؾ};hx[%!>ÇX;RD%??;>Pr>J5_3v(\dA؀NNN&$qqq6VQQ $##Ď1-WCn:^{A2ubB e{v_ؾcLh&*~IMM5\Z^e233y7)++C(4M۪ jƌ=C<#Fxs>T@Ӟx}o޼Y eg{ͭ.5#K"KyN׭.2F~:R{"~CӔKKЄO"50Ν5o1NVi(8ƌ͛a\ȵEzsgƝ;˒.Q`ҢQ<@ȂC͒1膂;lO?5I"-?ŸsQMxpɃ,ڳs;D/xr)ڛ%a.=* kQ_\ F4ߏ)DĀ{y˼]:Gtۻ%ߔD/xr)[3 A?91i߁oYPcyG9uED\Aŵ[glֳDG%t5Q(\dAʀLBIIz8vMfA h(3֖D]ҥr{ 4/ ѻcQ<@Ȃ͒<nRpt#GBE|wb ek8v@o:?fÛ?ڞzG"(Y2YgݬӟGl)[S)Nuy[ˍHU]^*c(EP. e@{$Y1lee:U6?QQ?|6ɗ3yODi  E haKB0q~ѩS=8z^4?}IOeѝ " RKDRI;|4Г/1lYmTl cZYA$F$o Ł(\dAʀvIѣݡłcGHOO{u%=q*4GQpO|׼Lth4K,[t7y_E hoshjoýQ4VcF4MJP. e@{$8|ys8: /ݗ󦋏h<`p;Z޹cSBE h_{ݾݽ\ 5Ke8q">~QO]|DT“}Nr'7P]ͫ׼ʄ&@JP. e@$ sυ"(,t}= ҧ蓡M#wJi)esfߦڀ(%(\dA耮gkM$Džsw\7jk[ߛ.^a1B?E7xQF5[Nqsݮo o[.PY[ @=]x4E xz5_))'q53Up΅vri'O1rHvE=Bdr!.m!(\dA؀عs'ӦMo!77j,X@ff&4e9.3{l`JֵX,ܤ$rf 7O<ߣ.n.+(U?⦊'B qi,--Ͱ}\Z^e233y7)+MӶjzj^kl̘1>?Y@23]{UUg㏚'x)]\fic2hvsmoӲҎ|p."(\Z"==h&{+'ޯW%!ǠA`I?ݛub<mGJT .FDq,UIj畂㦛 1ŗe]3qD#:b :wrk%C ;QD*~Dq,Hо* #h×_Ţ_Ti=We]3i$.#:EޔfӻnHŏ(.xr)W3 sgسGs[xuȑ{FiYpifC8G<%+K&/.EQ<@ȂM?M-> azP~2VtiUohƃKd榙t $JVW7hf"(Y2}Y\}jUIkwx6 |{{E4&-ČM3s͡Vc9Bp`x(.xr)ڗ%!С+#* >.8>+|i.}!W܄s oxQ\D" R/KB>} !Aih`SG\Z:81#Wq^y0B@T"(Y2}Y~JСIk׶^:gx|9BV~7–-^s4>YYNY4JWl~7\(.xr)%!>dQfφaHKnիz06i07N׏9?r[M"/$0:{D*~Dq,Hо. 8tVV{8ܳy!#%sW6i`I`ոUا5b?P^uR ֭pi[F=ٳ}_lQ8yR9TW75 ~Q_f6 71puꚦȷ0uT, dg;oɉ׶mkPYkYxSQgSXlq翟 KBG|9eaa, ~>Fp%p㢋 e6֏4FIV `Q|6~t9N޳õ`u:tOaҿv<J t+̞gߣ[oG]>>M" ]v ki$}\p°HʖEDq񙇦烺֒,f)<\??2RcyH( u`V=$??_흺L}/AcOWn?'^kWL}G\>ZAآA⒟Oj`rȵۦM)mj-hFs%'GHоIؘcp3y@-MxRxV[EE_r˖ӏ{G EyCOU?$:#5:<,*J QEp?uun=VWo٬b׮nj꙯3폒w_\~[cd)~욝G}iq+שb|~aNPW_$/ Vlˆ؁m\&AAȠ f6뿆zV+if{:F Nvd$iж]vv6ihhHоIؘD}vee0"jɥ^Ͻ_>&q+NsKCݺ5,*AXt&Aq1BiiGe|m55CӇA mC83(\ AA=A I_%q3y@R@s|1$uHb߾#&TL&jᇥ[al|d),;{H.!e@$tp-zz'y5Q (hbr[Y1=Y9n%ݢU(_WNP|vnIЇ?L~A#H.!To:jed4}MX]NqYfv34b`2=)~1Q<@ȂrJ>ƏϿ, ?vtDKk{ kpqYD]]q(\dAÆ co7b37mEqȑ#\;ZvŐnCίmj)?SsA* $G}͍.a׿~G"]*q]\:὆tRjG5j0,~EP. |@O<?ܰ_edff۠pNNN7+XΆ֗^ʲx ~-ϻ~K+Q%Xe䒟o>P.-/۲e 曔!meΜ9Z^ &h&MjXnӢEvᅚfф#Z/꽻+,^ݮB!Ff3>ٷo3f`ڴi ˍ( df41G~<"kw7@ E]I?9.g~i(.xr%9LL&xeIGfA-]us LɻҒJl7ĺtzf"(Y2( = =dLɈOG`yqTWW{sN.["?E h$tƔ)u:gb~msmmyLz_Mk/-h"//z&D" Rg:#&} ?N4q_f:/5oȪXA]QQWD4;LQ<@ȂmdIؘn#9rDyF "ctwW׽]\} E h#K3Y0K/>n7p Mxvճ<),Aߵ#eKb}zw ߹[GQ<@ȂmtIMhu|9/M) %BX>v9,[jRXRݿHŏ(.xr)ZA~~> t~շނtZRoO SI$ JԪ8vܵCGQ<@Ȃ-BIQp}6deAr~akOkmܙq'&C? WC~ IDAT ox(.xr)Zpᅰf \z)6uVF>gLO֌_Cj|UW9LUچHŏ(.xr)Ẑ#1~{ؿsz}̛ۢGzX[;Tz_5iվxoxQ\D" R %ak,ڳSUWWq…<:t+B1-M0ɇ¶mgeˉ;zpx.DQ<@Ȃ{אJ3m4oċ'z~7e AX }BG*] EP.Ӏ>x V0dlW1w6ÃKl23sN_?@R^ԍF6@]NLԇN!.N4Rծ* rG:wEP.`4m+~ cРAk.l“O>I>}<=ٳ#'^]*[7YxB uM\̐?\{|XY~+ss`wkH}a:,}G ->;~W4:D ʽKW^ixML4Mo+k?FxP8_לuǟk2A^ÙKI>x H{4_X5!(7g?0 Q<@Ȃb0gƎ ԩSy衇\F,\[nѣG3aIII+ [Ckv&-M3 a阥 Lo6deߥU#'[xe%TUnl1 yhC>Kjel3&垼x,ToL&8|8Ԇh}ukӭ[׶^?mc%%%L4jZ=tW_}5ݺu!e( lu=|:w⻱ѯS?C\Z# W}\oiglC[Nm1kkG}kkQSKMڏHer9h4*,YBPPCukd4hyyy$''7{n,X@HH6QFCJJ tDz dٶxz,[Jάyh X#~wqe]vɧύz7^H yru qc6}{w]j_eйll=7s) ;wfFn,8®]ٜ}v䐐/''^8x0x}{fil!.. gӽ{9 ~54!:Z_v`6i9/ M׮i;CT 4!2R_vH6:QX/3-?Zw'O{x6;""tl()!<\߉ED|YQQ6qqi`vXgFYYKs շWRMTT 25\\(oJB &[oQRR# Hql[P4^0ĘDҳP'wʖeTVaP\{_#(\dA]nh=ӉeU*z6 +[Gω])\|(.xruv?S~B%HplU803 { w](.xr), ? ϯ~H]N!ow\-[NdVi#|3ZGQ<@ȂGF?c6YxBt=չU\-[EP. %anq.,Z[-SO^bOՔfBhC](.xr)%aIu #>AG>p*ps;wdu7d/@P. e@$qgSÍolHG[.]ǿ o۱,HGTdW&-Īߩ?s@E*8r)SNuEa= u'E Tlr~Μ_~$F$_="m4>>zvş"(Y2M1iA2qDL!RњƉO`gW](.xr)6L?|olu]TV!gH!-W5 UH-Hߟ])~'xr):c BR_S^6IܐZ}HGk.>nw\(.xr)ɓD^ TnW\+k^!28y#( TpR]A2z5?gȰ_(\dAʀs*/FCcƍ38+6hHO}vDq,HtW8]Ř~c\ZGÙKZ ?-$0*'}v(Dq,HUUUD^)DIV Mx9E9L0H&_7D*8~0ZF}D8Y.F!(\dA؋%=zgyV+f"(H" k龥,ٷ1=yxn+RqOSWTG¨Bb$E0|&ye۷o.Ju:[7hiV>dш"(Y"{ҥK<ƌCVV3gl<,X+1G~*c e'rNNN˦oΞ={u(7}[=e]{WqI"~1jK˶lBff&o&eeei[5ٿM0A0a-q,cs'NhѯFk ж.ݻwk=_eM2mEMS.-nB- {IQQ_n9~ZH1{MT)/Hߎ}^ ">+'9Ip`nu7ZsQ\D" B qK{ !(.eԝsyUU4@s ~."oM?sl̷Xb4xr)= AfF'kۘu6%JtSD*8Ҩ/G0.(.xr){v#n㭟KEYPV3cil'Z]DAQ<@Ȃ}= ."$)J9T,"$݇rA4 םRL&RL1E"(\dAʀ>&I?֠pAGѓ֧r?~gG V4z:w"ooi"Q\D" RtЁchZ/_9qpC޴{1l23Q^u18 JW'. Q<@ȂRIؘ^: ssNVe`ׁno(8lU6r^̆ri(\dAʀn$t=wnfC Gy!at1Cc ui Q<@ȂZIؘnt#06E8ރ+R𺋿 Qb= ui Q<@ȂVI 0:ul7s<.,84Mc߃j5[I)"-ʥ9xr)1=ֶ|ςȌ#/+ƒj!dC]B4GP. e@R:X{l-{rؽ⯂Úc%/M;\̡Ϳu"-ʥ9xr)ڕ9w 5kYůUZ;ލNv'2-0WQ.,׿>|x宖k׀ 94%+J菂#<*6Wuy)O|'Q<@Ȃ|rz5WKbvGtם=ݺxk(W uN*a.\#(Y0<8Û<ΝҥK;jIc\M?t׉#ow^q_{joz~+Q<@ȂݣG.]Byy9=999|wM֩`dff@NNNObǘVL+RhXf{D sy뺺 h-Ulg;E DiHEfTriyٖ-[7ߤ 4m&0ÇolĈ.;/>ҵZ9K!|cG~7oh}gmvmZYK7kz\ڋri(\Z"==h&~K,iՒ0(zn<(z,lU6 ߆uo|QpN,{g۩!Q\bNdvHKT(Ehma1d:w"yyCo[D$J4Fma-*PA҆DĮ`v R٢\#(Y2* N0'{ZoRBQfE_Q!ו.t!<&jb3\EE JBǙ𔐮!tԕRW\GbNd" 2 "DyI$}1g$)??_<"(Y2* i (6Nc:iL&+EJz{=Źt Hth]D*8sDq,HЭyy6"9E J}9UD\#(\dAʀn$UA"͂R.EP. e@V/@Xw6"9E J£GH Q\D" Rtk%ct Q\D" Rtk%#;d Q\D" G}c=lHX1B " V\#(\dAȀ>vg&88LRIXY[Iem߆7@C8GQ<@Ȃ}1k,BCC:u*iii̛7:-+ Q\D" t=XtiرcGIIIuY`ddd) iXr#2P..iii-[ɛoIYY"a4m+h3Nii)'OdMܸ;wnu2vepgGrxtDQ\Dsg6ZÏ[⥗^b̟?iu->*8sDq,ЭRIx-R\#(\dAʀn$4ZC8GQ<@ȂLB#ZYP9E f"͂R.EP. e@VMf, ~sP.EP. e@;+ 5M8~sP.EP. e@;+ 뫩W Q\D" RT)_n Q\D" RШP.EP. e@;+ h Q\D" R1a1~uP.EP. e@;+ :P.EP. e@ZPKsD" R* \#(\dAʀV%ssDq,HJ’S]W"9E hU:G8GQ<@ȂZID*8sDq,HЪ$trq(.xr)0*|Hrq(.xr)aaEC8GQ<@Ȃ?G}ѣGs&5i*@FF?%sDqKK!jL°aظqcM&S?[ -sVɩIDATDqKKЁF 8p'6Yvwc6IOO_eɒ%M^MlTAPSSl Q\D" &MӶi/¼yxoٻw/?p}cǎ>lL_Q.EP.g~ȹ;vr&BjO]v;h-B+BtKXV^:t@LL a.cǎlذ0+W2|ٳ'>![nwߥ$^|EC<sM7qUWSOzj~i.̘1c s4s=gO?Ĝ9sꫯػw/9rG}.]PQQY 8!K–Xp!r 3gΤ'j7\s >}W6c̘1?u7`ԨQFk`6]꒑} &ƿndРA̘1{#F7nꫯfʔ) SJЇ")) nݺQPP`X|G|͆:| >AO޽ 2d˖-c֬Y<ٳ /iӦ}v8`ӛ(o*ΝKzz: 3>/U@'''7GrrF0ydVk2nV.]ʦM};wdڴi|7 44r5mJKK d߾} 0Pٳg3Ķm q`ivps}vZIII1j㏳k.&NȔ)S6eܹ̘1aÆ2m4C<-[ƒ%K&<<^z Џׯ_OϞ= s`TUUqwرz.C}̙øq u6l/"VѣB BR q( OV( AQdŊLTTcBZT@+'yK={6?ۤ)NS( AQG B!(* BPT@+ V( AQP(ZP(EBP hB B!(* BPT@+ V( A wIENDB`mpmath-1.1.0/doc/source/plots/lommels2.py000066400000000000000000000003611340375245600203220ustar00rootroot00000000000000# Lommel function S_(u,v)(x) on the real line for a few different u,v f1 = lambda x: lommels2(-1,2.5,x) f2 = lambda x: lommels2(1.5,2,x) f3 = lambda x: lommels2(2.5,1,x) f4 = lambda x: lommels2(3.5,-0.5,x) plot([f1,f2,f3,f4], [0,8], [-8,8]) mpmath-1.1.0/doc/source/plots/pcfd.png000066400000000000000000000672101340375245600176460ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw|=!DDD@& \B&ՎW/zsDQDDi(7JB $$!dӳ1m2_? 93Ϟys# ),h7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<7<<<<ZP`ܸq/-ᴁꫯ0es1 5ЧO;-,X[@{;v uuu8z( 1uTzwwwBwJeeepssz_vv6|}}*x}D"'c3 .6Ompbذa6lIg g\empݕ(JsK^apY>s# k[.̞=1 1f[4:sK^apY>sh999!#"x'hܼyϜt7o"::x'm6Qv q|&i5'2^|EbŴ{nsw&X1cd2s\-|@bb%tHG^yDZcPVVe˖ѸqYq.3ׯ#::2 ˖-CYY;???lݺ/R=i.}}C|oˑ#Gy{{ӽ{Z[r%^zQ}}zٳ'+W8v=  ?I!m{~A*̟?n:t֭ŋcԨQHJJ† \>Sjۺu+nݺQFa-u ;wz-w>cu}hp?РI߿/ǤI +V\.R}\LvZҥK!8o6t.g,`wq8< www*..gyHP=##a=‚޽ۅ l ߃ -_3|ظqi~\Tھ{lY {}]( ?2}Ƃ ߊd@ PPP.Pcnʊ󫪪Ãݼy r o::-+ԋݻBۦM 1gNwppobbbLϘp]4,Xuy޳gIq.36R~/k]n…[rg(in ҷn:d2̝;...Z0`|}}q9LW>ckvrrr0tPk]gφR͛Mp]4$&&B&aڵ mƴvP(ɓADؿIq.3Ǐz)˪oܸQƓmp_@TT%tHTT9b@PPuwh?blm'N=Zaaa9r$Նmp_4a׮]ӧUǐ!C D2c[W1z;wz.UlcFg Px RSSq!b?^:D"}Y(J:tȨ~\gLmϟGCCF HW&M;<|N{k x PSS &Nzƍ8s挱~qY1O>uX[[cΜ9P*زe 5 ?#A <gpϘڌav'عs'5]ڵk???|'& 2 ϟ  ŝ;wPZZ wwwhrg,meeeHLLD@@BCC Gٳ'nܸa{k 8ۃ~ᇱn:l޼.\0鵸h8z( voP K>ciH$ "<ڶm ˔ph}Z/mbA&#Zqbccg߿? H̬%h#ŋQPP'xZСCK.QeK mܹsFxԜׯ_礛+Ϟ 47I7nMoz_S庞7o\Wܹs1cƴدҧ*ۥ:ж3{`q@s3 8pڽF_޽@sqU8;;#,,1xyy!11CNotNNz쉇zׯ_GZZI/\xL o@ gLͅuѿ-k>@!C@Ppmhۙ^4=Shp+Р))[ns we>Xs}C 17]]]n߾ ___xyyQU*}=W \xL o@ʽammvo׻wo(JTOe Xs}\3Іݍ70@>9@;'N{0>ƍÅS,4۷/b1+WCΔTT4קz۽{ɮ+\xL o@C{EMX~hs_]]__6Ǜ보D~PSS̮Cڮ+ ts}SN-mg4r߿xgZ3>chsߵkנT*5zHJJ20n߾ >zp$&&"##ds?{7F㨬SO=½NC=Hd6w@[}*o!`dUM4'80gjx n:Z9Tlll{A*]ۯ@[}\Av@DDDaƤ>9@\ڽV1n?߿qƀm } 2%|2Lzmm0gjx N8 ;mR1 9O*"-- puuxNk}Fjjc E߶*Z@ PU]͉70aMڜw7zBa m]WhM0w 4FoXYYitog mvsQhǕ@mUZ(!>>&~gAsNmWYYhOW|ЌUzN}s,3P KKK{&}=z`~Ou{h_ߣ>?( $4#F† O?4ɺ 'OT*н^\WYY"¢4鳷Gpp0222PSScJOunO_s79僄য়~갇i( 4hLPmS;<=}*7jʴ9Ч@w n>Hhfk7PΝ;~u"%%ER4mb껯w%&NhV}*hZJBW}*e[ҹlsmN}{Μ9MwU߿+WDee%8]#uV Eѫ?k,^֨i_E駟\S+--%Իwoʛ>#@6loz-S }.$$нSw)ij%JU(mR}o&kbgضP8݃~ua͚5&9 ں7sss 0ў>ÜSum;LLx[{#ud*r>A\q!IGCqfHvɓ @WgϞNGo }G~~efоp&Եaqa\?9>}@rByTޙAOFqq>HՁÇO?4;=+(4G GGGxzzvxn{\Х.VhQ@dh$_|\G"b}fDX҈#xaF3}BSL0طoA>Hճ~7 /]m\C]]""" :<#}!!! "dgghv9n>s5Ao Ц ?#luFF<3IЕ*++q!899aZ }hs t/88p]m.444"f:JL?///H$w}g>tea߾}hhh)S`ccUЧ2:5GF@wOeei%(U6(*n6vۨRm}"'ORu!A 4l۶ ugHU!б>6{DWM΄@ z+2L=O߄,GfT}*Tn褮>tUNuWWWܽ{Wv֧Vh[2?DB(*mё>s8:k2X҈n nrsskkk-y/&g-:8y$ʴP @Wv a0}tD"u0d2T2>)).4)3Sɖk&\H,WŸ ad/"ʽ@oCaeʳB{>l9 @Wqo]O_7I%Rxr>?3 7trdffsqq 222·mi[R|_󅅓 uVBB[!Ukʹi?>tE!55W\ADDο]7Ph }56 Bc[Dl)ɳQQ 0 Y}GaaCWXڈ  /&?=hH1Bed(kzİagv>Hc;ۚ ۃ6T!uQ* W|[ダ@YDd;B[Cՙ>s9Ӗ:Ly>`gff@B=z.V(bܹM6Q  èӧO׹|WB5І+ғR{OaUqU$3HM [} W7šB  bcPѺٳgC(b˖-hll[ASN:t 2D5*Ҧ6D)K؞ap4?BK!?w 3}ɡI[/EPHMA"~bCw܁D֭&Lb>H`@xW*UgggݻP*;O0D_RȲdp':K;z!;ܽ{w3C-/ 뺍s44"lܸQo} LhÁɓ'UGWB ˑuC~^mNB"оݙ>sjoעJ5ARAAA:0#tA%(ޥ9>vƑ#Gtz>2а~z0 y49]g$Pu buѪs(AwF KKK[k+={nah"6W /jZXX``[l1TfASr96l@ ]OWB /w[Z erʕ.wugD"P\\jUBsm$Z[1 ԄHƲF.Lm3\{K/6oެ" Lhؿ? Ok/DWB1eP||QXpFFr4&=!<_']`m1y0lmPzZ:}0|pdeeԩSƐ>H`@A]@/||_Vi謁݃ҽFun{5pqً%iX.ːgO,\nۃ>"p->}3fAuue P:lo&6=@ԏQk*?>r@D:#"Jsb$o|m+P8|xC·F1c0 x7v5֙šy3B;]<{SLۧΝbl׃LhP-Zа 8::iwj5mιZx <\0& "v=KՐelˉBՃcVJamnmگ Qb{v|  '0q N8U7p`pr&7eA(;\(R9>={666x뭷 +V0B>HhFK/a& _`mm9s\_WB*dxț(Q0Kk:vLفxEW s/ߣW$$`301(.ENU= x> 0hw mOeTšBu f웁 /*ޯ@D옲{M\!GUQ`,92ՄH|!C+3{䄭[%Q׃ kqz?k,ђ@s5P2Jru y~IYFYǾ1 C2NQ{b@^_zɌQ2Gdd:k0v, AA@XXz  + P*stt+Lvto^u j8"z wѐtlS,M?qD;Ofc(5lnM}CbHKo _ !Ν;~ٳYm]UUU9s& K)M1dI1a85~Opfg]|Y.oF}7g0}tl:Ic_YrB5WTT ??8pӧ)u|1qc Ý;@aa"X$%!>ز%2Fȟ#&LÅ/gooy桮W6Z&&&"''^cʕ4Ho.ZZp!/L DĽ%%%dooOVVVcn9r4(9-w"Ā&L5 5cqqqNs?^/S\N\cI"PCQu8N bD`ۻ]~ /[2J%QCQu5Qv6ё#D_M4oQ߾ Bo/՜9OebB hm_:I G6nܨW+HYjM?]x @BWG\%FiXdffH$"6B5inĄ}DD>^{(0>"ojg2 O/}+έ Ā\p\~im>#'^Mԯp@0N%ڶ(/g)*5 5'+F$!l=6m"&ˉJK_VЗlSre:m{8!\O_$tԩoUW|R_B! $:f̘AhʕFPbob1Y[[ӽ{-G#r^eukۍmcQ _'Ā4Jp}.e_]&#Zť뻉;|ܤH QV_|r5>DǏOI$D""__RxǍz}L,;VFH7<0 Iivt) |p @߾PXev 8P~/>p ̄48 п[9F >sg"D辤;:)sRtZ5={Č3PTT_=h"JNN6{ƆlmmxK)I1RvEve|RJRHLL L@B/+HΨ:q"MgΜIĉ-re$.F\I_kT=1cƨm5T&p% ?֭#{Z;fĒBԖ{Q-']@vϬרPHHH=/b@Z}HNN&\I]& $artt$HDׯ_7>cµ4o?O@X1rܙcU7hy뭷ܹӠoNLM5$Pʂ6$%Md}(6m]O<6.,͆N <p "ڄ94.[ wYB %Ġe.#/u#Hw@B~xn"Ojb@}u+eQMt4U]2oА!C͘pͶ 4LWKkN|Ć5k 0 =SnwI ^>v;B(d sPю*޽; h椽FH]ݝIT)D} W*=LӮٞs]Nuf$m@3GHx6 h~;.%Āwy! $G|'hll>}ںug xm҈@СC斣FӫJY}jE\E:>Lh޼yI.N;$dPUkbȹ}M#&I$eG`[Ҕ$ߟP~Rј1@={ZU}yyd̎,?;w:֭n͠MMND-_\reG-5,0 %J& $t+;3=+t4u:KLc^.7uT@qެȞ=RںeXl`Bc}0 vx#nd w}D2-^ WSne.!](%mvJ'5A. UL7Ի}5͏~) ccc7~ T5G~pye 5w@U~eGW$_Qls3g )Q{ lEpz J.W餯9AB`tE "BB!0m |5`9APKP[u(W."{ :HIaGyz!3>ypvYL~h21p@8um'׾^Fb,?+իW 5u{:SPP@~Ew)ؕK=[miT+7gGB |%.h @B}wb@Fk˖-[}힓#O~boߦ ܾ3\ z}Jƍ+5dBÈ;wƍ#7@*ڢdY}7tƎ9_z~W@a&c`n R*JDGGnj3L#} 1H nAՎ 0̺KKN @Z+A~RyXJKCm9Z{0r$kY={:1q#n\ AHM y~G[/=ʎ/  t 28p2U״ϭ BF./~H(+_\{mg=vB;s`S^^x,^; N>%' F@+ܵa|76ׇ\^z{=Z 1JoUp"СMѣ]#jhXQ,>ߡ>>Mn9蚺Zr6,p'ĀnKJPe,;Gfr>|8^xC4W{͚5X|9X4ϋǣšCw ǥy0>lQ:}uuu(.z  6lˁ=Eױ.((֕beתӦ-Y Pqv&LsxÕPZWшiZti`>S|8ۛ^$qA}}}8OO։~cǴ؜!Cpi%艣wbϋxng ^X 0Y%vl۶M?c&֭[ Y[[W\_}c={]WH=$bl۶л9R)ѢEdg4aɒW\! $Ts)[^JI +$-uDpp0h{;!f^ȋv/=+|OOOdBwB<$Ar9њ5DDo#$ItJeo~?;M;/\ znرDzȫUӿ=M +G-'h;SR:m}|W+W5D"_*$ ]݈;D"DtgB\vilJd .2eJc55H0U2#++ŋΑI"d'6' oQ(diiIޝPN)V|` QyzuiՅU6H v@'!!'4'ѷ߲P[l2@k֬iyaq١~襗ؙ?:0 mLHHύ׹"v,*pxc LٱcD"@VK!tLBa/$@@@_ucsyz{^حc)>ЇVw?!XfgHS$.My~鈓\@=V/"{;ϝ;uu7!TvLx\+4s&@3ѻRv;w.Çk͕ F[r*rhֱ-zu:gܪɠ TC:}BG~&!FpB@w^_5FF=3ڐ˂( Ð=9::ҙ3 =}&!o)PYYI @Æ 3ZOmM>{m-޽D/HDLmL)F)PS^GHrӕ>Ъ Uصkj+[ckXշCDʾ:u@mQʔtZ|؟!elvD?H)'@H/MBk2?'k2=ĦF-+Zob~" jY 6~NWaWI +ejeh?<5''G=O 믿NUUMn>HALуްarqqMLSdKsQZ =-DB4iRΗ5QDo߶Tgy$k9IEI$WT']`?C' dEjfd?QZZe 5JE(?Y&ܴ<=C=(I4hPS"w߱4jA|n<:Fl:|@/xb3cʐ0 ,88P dOkc6mڤvyƍM22Йi&o鴆TbF̤w}ƃPP*ʽ+꾪]jK{\v!~WU~eO6m"Zv-;yٲvӤls? 1o.|رc ݼPQ-x:wꕀh~ Cu!6K~wo?Nh̙T_J>o=hr:tŋ "/ DE}) 0gidFv_՝ZBW]tFAd9s(\۹-**ӧ4svӇ@{ѣj*9s&%%HFd_N+VQFP($daaAӦM82uF.]VЄmCT۰ѦMT)4^%ZuFF~Dl^?lS0 u:KmN֍W>mEFFޜtue<0a\Tۛ,--Ijƞ\!o1 r_vU΍ Ĵ_WG{7;|ݽ}!zU͛ΟװBxݦazg.0[)MhOZ N4Ɂzk[0<z/ m-KL{??3gjM!r,p WSWWv&cD7< < %a~ 1h53Ga/v<8+fF-w o\b,T=%(?RMB8Rb І5k`(j' ޾mJ:RD,c֭dBW믿q]vaҤIxh" PXX{eeeee(++Caa!2f@TS$ߣ`!xlHħD FnʦJFjy *Q E 娔KQP*҆RT5Vh(pce8 CãXa@~jk vJ}ͷ*ڡPدkd4mҎ 22Rww8lk>z#Iރ/,5h'g{mp|*5;vhe 00Rh?NzT ںܟu۩PwGiFvqH`|U}s캴w)]ҀxvkU w+RmR\A.iUj'( 7|!C p Vx )lwkZ99 8[/BsW]P:d"/D"D 0)+\ʹKpa>|EQ77"{ t+\\ ggdR)^}Uc:ȑ#F"77Wm=ӃpqNb'8;8Ch-DJOځrr7muVu3r|+]2'x9Ve(3nC)R *أн;C f qOk{粶rss!aeeV]+#=h.mm}11b"9-׶`a.գ!zE_@lCv$@zy: ~R<۪ {Wd\ `SK7a\XvVڲl \B/XBAr\ i4_}7unM۝XU H#7 49`r4pG5 O_#-(dJ M@m7m?S{ÇðĹ\ IDAT#t*l <-^3]0v-z#pJQ>>ȩɁg'l`T"A|D&C؈jR;Y!B>Rx[!]P +V4e-U tYg}#һ PUla,%{`8B#.BtbY1`ZEdw GQc1jL%TVVgL|h"Z Ro&~wapvv>sٳg㧍?3 9+S)A J0 JL Q?S@QyXF=^BG܇[ M> MR*RvS+w{YY?Ed$0x00lЫG1w\l޼Gرc;<`)ևtָmp$6O܌9`ժUxW_wѮ&M,Y`Hocǎaر3g6oތI;0}t > cuL Hax8Nϯ"##ӵx A?Ŏ;t*+m۶v ,Y.40r"9Qs5W٭6 E 4"K>=>v.u60- u׮A|CXС6 ۷(,hǽќGҏsaF88tp8{ޑ"T]P-ֺOsC >=)a&Fk39H{h7\g(&3Ћ-1p@"55'ѿS]V/jVB.#Pz%jkPz{KQXd.ɄokN-!yD׳ӧu`7pqa/yE`;3ۯ}c~z` S3iI`@, g\=r'+t2ЪxGVV&xqU4 yti/PLfCBB`aaף{ƒ%K}dlEpz N;!`ݪCX_yw<ԣ9doU5*}% 0x`ƌv;Ļwj©SXvvlmhicze`zW/835@ Z u\|"{ (%n;K]׍VBo޼I 辮@ ]/;~#B&!M "賵e~1c,,~u{de˖>5k^NEg=h>:}*u!C\4ãB20e PR #23P_e:ZB7cH$T1wMϞ4>!$+WRVVz3\F5݊E;3ȫZ3*b>~+0 Caei=%|N鍈L ѬYg4tH#銎fφ=yI _ .3n8@׮m1Yo6w޸5mz *. v=Pq{_F\B޴N33LBC 0YY bmY*5z|KV\ZZ׫BQ-R*" $% YH =$m̙w|>g9O37$j9l+-QU˗k-b!)):-+XnKnb\8{({a?A`ʀ4I'.94j;^'@4>ӚbNgV{)jXBN kHuYxd\Y,puk~X].6{BOst.((6fn/bᎸ;(v.ڳG] m`ԌfU~LBUW\?zsq:4qC:NtGTT._h~6Fv?OQV~2p@*T>-ܮwq_rV4Ɂ%K"ڪU_ B+vNMMmir:9z}A&̞@@jkh*oյw4^K> O IqSDCE4MtRZࡇu37nqe]]3pŧ ,ݭ]׳~M\\EEE47V?jZj[+LcA"~4}[h[ǘ c@|gk{o Ȁ7Ж[Z ~Wåd۱Z m=@dpC >wπ۷Cxϳ  $85:ߎY?0y/:~;mwor3fܹ$ 5P]Gf~&!׆h(**BI`Xr%zyClAr8J9BkcmU￀S8YsI:2i(h{Gw<-+:y[S 9= #4 ًpy И[hX,|m$BKNv8BȀ$:9 䓴Lr.K6d_ ;xƏg 3?gޭ1޶%dێtt 3>f|V[:zZ/D*??̟z M/R  {= k\EJ)SI4 Yۨ(BXWe۟wx͛1o/Zـ՟oP,ھӕ{}J7-Sy Sh1Wq68oZ׍/22Prssq:  |o Vm]ԩ>҆]Is6F|_?|8pyg+yiKL_ǻn~~J&[pC 8و8Nz#aza[7,߽STFBðG 8O_vP@u!4ϝ!rsᗿVKx6mŰ0m_\KH\u̟vAL*8W~s6?՛zuW8q;kxBEnF[7sв|Bv?OQ ѫG8<-Km>@TZeolj sڪyVɅ OLXX#8w=!>,tH_/}w:m !syײ uz;NOofƕn--->}bldu~"u^x1)));AB?)'xb "Q齻YDٱ,5 |PKahiZhlԖ-/{᷿4m&%\(vV,vAH@+>[kj߫Xc1_x[S2s9L ٸ_󕜮|0E-b|x~=[GO4a)Of@n,^#22???N8q6fTsKuuudgg ߥ!2|- mƫJUkix])))bȑ#nVV3n%}A}yb-Es][ 222 9_W~{+v]X,bp!h,kaEKc[nwu]0[,_l֭[Ǹqv ޜq.ūMu]M 1\hh㴍n?=hW/ڞK{~B99Zѣ 9No, cg ~~Xg۽?0} lH~٘=h_6|ГŪ:B>5=/B ^,2`ĀvA~'Oj{0݃v/()H o!l;F(ͯ5P=/2h_6| ^NB4_YQ"AVK~||<~~~ ];?Ÿ-Ă\(,7 78ó˨-#|f8^NyMV3y8?Oఎ l6#F̙3 VvF̊`驌1ؗ1Lf*##8{,Ƭ(XZ^_ _Eh/4b& xM1E[P&s8-F]ouĉ?ԟ!!DЗk{$''ÖV5l**@#8AVr:5d?EM?m+mJ.\@rrrOFa߽{ETFB~ׅ2uoez9"Ⱥ'~uƄo^o7r1ƎE{6| _hFHN9™ܧ]SjU=Na{Й.]7A/Kw?:bY9$'\cMNrʡB#xûNmHz7/+Ob% NmbGS\ۙ"\}— cٻ1z>z~:$oh#-@g蹛d%%%<RWWǻヒfʵd/4x6-k_KѪ".dm %kKpR֥ SRR£u)ѳK@@Zc4h]1lȎ=X֭[ǚ5k^#I~% 'yU2Ce3Lb2?RpINNsι&ɓykZ/ZTTDmm-Gnض| "@呖gÆ dddP]]͸qv} FxR""IDATץrHz!)nIRVVFee%#G4t;i=ao6=2"ENLLdǎ~͛޽{ywXfM㋊xٶm^_S=/?weڝ@}-@{>=@_^KMM[~l۶W_}*BqHHȩSDTTX`X`i}7Z4|F#{K} @ݑEgϞTΜys.^g8x?_u577_no_"_㦛n}u?~} tO>233cʔ)R:roeEv?OQ כ4IOO'!!#Gь5 Nzz:ϟ v3g.*@#~k׮.{ϳg Boba!En܌@ _h%8Əω'ݻwZk?ou%ܹ֑.})\TFBiz---ڵ ̙3M3YfaZٹs'---߾};9sاnEp8O~‚ 7o ^_.k.JJJ9sfl3fΜIIII[pw(?Bxbqv(zAAAޛ;wowشiϋ`,.^h[LA呖gÆ =z'Oz/{ygժUGCܹs?ٳl'(?_z%}v͚5KlڴI|Bk&w^aĠAĞ={7|?n7^[dٳE@@رc~_KOO|xWܹsLHsrrĒ%Kŋ=#۽o!~/;vO*aEee~FSQQ!vOS1vXŋ.6?RR0 =_mmHKKؿm߿_iiiV 7w-BC2,n1|֯_o455vZz+)))f+yǏ׿cVRbEB~6 cRRRxXpaٗ )*@#l$2lTFH3d ٨g'(?Q,T~!nFh/4(?ϐOf7P~f4g'(?Q 3d ٨2lTFB dvg6*@#Ay~23РM6Lrr2˖-3[̙3ӧSO!< Ʋb E¾ٳ_VkkD`*[5kV`̝;5kPQQ!xYfvZ֭[g}fN+qfkt֭[9y$~~~DDD5L/5%0`x 6l ?n}]0^͛GFFՌ7$1sLv;1d[nl۷hFEYY:8~8\s /xG#11l-i;@TTYYYfueNvv6wnW05`޽l޼5k֘`93m4󉏏7[V"00%KҁݻwSWWǮ]8{,wy'fkgd#rЗxgzK4Y0aʔ)G?' ))d+-NHH/J>}x7V}_OҎz~a"##innff+y BRTPP($EhB?+Vpinf+)._>z-,J ˨跜9s~놢_;0uT֯_c=FssJ ˨av B!)P(BPH B!)*@+ P(BPH B!)*@+ P(BPH B!)*@+  p31{IENDB`mpmath-1.1.0/doc/source/plots/pcfd.py000066400000000000000000000003411340375245600175020ustar00rootroot00000000000000# Parabolic cylinder function D_n(x) on the real line for n=0,1,2,3,4 d0 = lambda x: pcfd(0,x) d1 = lambda x: pcfd(1,x) d2 = lambda x: pcfd(2,x) d3 = lambda x: pcfd(3,x) d4 = lambda x: pcfd(4,x) plot([d0,d1,d2,d3,d4],[-7,7]) mpmath-1.1.0/doc/source/plots/spherharm40.png000066400000000000000000000561261340375245600210730ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxyy}hEb#Ď fpl`;ز%K&8$8’䋏c̱!`6m@F 횙޷xif饪kzzzꮻY|a<q^ctȌjѬLB==Ea,a2y&`2,OBL&a_=vryx+Kb1dŨPK]ciJtG<X,mUe֌7ia!vgQeFH:1#`$bV`QhO\.G4%};iۗ9iWVrE?j"3VP(N tww7j}k#{pQHkH SdͼhƂGM@"3 Hb Y|Ī~#mb4~GxRzhvs$\,D"u6xJ8NicNt;]Dbt:M p51c$ʞGړN9A׈fhAat0tѩvTz i{YߪGUYs+1^^?J"L<̨>X>s0,Oy^*{mpN$tww{hdF-h_[*ʕgN$MYOVKew'i0#h4\f.;R(F&x0xg+fuitPKX/j!UUv&HS6s`pB>-Gh"Dkш,K]aiC[j:{sy D"ekD|>?,V[nEN<\2ٮM Zۅ[o+:#kb!ZP0C? dG|]v2N>>S]A͎hdYPP(noF? *g!Zxh|ȹϫw5stG21^WV;"hnU\;3Bkjy_5Vr c=fB0_KcY >,"Q+%Gvp+j=&F̮N+&h=GB+ zxt:ݒu6[+ĂPB- J9P"/G.bYd1}eNc旛ujAypS<8ʨ7Dj,]o*q1,kCccXavaC?WDɿ(BE}yM|@{5{~tшTD"1fT*M7DOOSNn+VtR/4t֪ f"ϗKuww;b-8̳#@8 WU-GiX^ؕXwki2+4y+džrZR}Q~ߌYrk;ѣ޽^DSjI;ZA >)*X,dcNsmXE`|!SÈ CRXI*YCXj:h.#b.#+aŊ9|X'!=L-}޼ydݺu<Anf,YR޽{KXh{a…,Zg}RW\ʕ+jؘ=̆aFJn|uEQ!!NCvayfMBtx|>-[~⋇*,X] صk立w8[eq4̱XT>iVX|KAZ?!Ea{Y Gu!0x 8Du`V|Uk !^cEmt#:h>i>jXqҪ'e!zIф]~ X z0v BZP(FMqjgJ\F&O !^Ҙd I-qk9zZ5y;yI?~8FrÂéʳS k<3G"Z bUlh4:jxp$àS'Xw׬݇&İԶvVws=s%m=ۋNv2]AЭPa mLFNѨ& #jzXZ^TWR~rԮBIW"<uC#hB Ezzz&\Oz3!cX^\x *߱ D&SFeh؍VZER^&#a}hX>fl''IBPѡm(Z @#œ<~ 8x;3l>40*gh9F[S,h n$_Hnc[ P)JҳUÉRI,:Vln++Q*דR8|#{MpT](d2N6v{i"o%Q%O?`-NZ_ ( ;i+7T;3 x| M~9i$ t{A +bc+,ύvtB9Lai5|6Lu`ppБu8%]/Fj:Q>/P fDI@bEfD*i}+ 2"C;VEnS٥Zʒvkw7 zRDGte{Љ;q2ukb0<AT*9\ +V4vGՆ]ODN+ 7sU^ j;^㬳J#y)BsӐg{98 )7y~W#W%$#lC GHZ'o@/uo=~N> WX+{nMAkf3bXZ F7 :kRq  D.G|,2ے4b!$CՕ͚ʭ0Q%m>kE$/A,c~  1m_~"ϑP: Dh5daǴ[=YPI|~XdkOB#vFLlDs!Bq$PzQē"V ,/#B: "BBasLS/~Ѡ\I;IS,ˤ](F$mc5W_EBN?<21g V@HoQav'!Dx!:"BY,֢Gj[f7T+{Pf ȅ sY 2wZ$;wsu2k;igY߰xVYdty/+U[TDBhUISX^t F;%$UZNT G+" U`iMbc]x(O~իhUN}A lR*t΃Su"oQ8CX32!j;zXawA8VJQ $-`qUS iw 2pC.,>v381Z DJ%GO[5I.U1^sUD+$$b#GHZիs\%l#cc˩R.bM@ڻhItJȚR՘8 O%]b`Ъ6a/F^o'=j𒬃cORtM0uTn6@ժUE~5ezWh"P( NZlR(BŖ{ЅB|6 10 nz$M:5V,VzϕDK沎a)Q[[Z'rbvVQլl_߶n4h>F~l㿚h6ثtAb~~ӟyfJpiӦ ;7>/_7?iFoo/O>$Ln_~0XhQ÷5S8b$j"(w6Dmnz&u*"`7)SkBU1vVEef1 ";X !3=5QVŒ{Gm&Nh%1ڟ?ύ7Ȍ3x衇رcǰݻh"/^\~p A "+W*$uXa)-^@|hR› IDAT#m׍!]TTA>9f8ǰTfU-S B6"LJE5u!C.mGVDŽTJ/m_`v`׮]eRߴ,A52 xh4ZjJ6۷k dFlAPYISm C&lUƺ)2e1ۋ$ג%w#Njh7\CN$,JR),x^ZZKOprr9ӊrbEe ;|\ԺAijf"AnzGj>u!+n;xkͱ [~!Nߛƍ/׷};<Hӎ\CЭ@d drNAP H˓!3[WBG>R\ ]T!.D^d |u9f`Y{u"~\>`VH72F֎E @/,[vƸd*u`,/\fb58Hcݻu4ϤG @,Ѡk3ֶcmC1ܕdb\DpxQ 81h]m[$b>t{gS(\ymM'7\EF%A;c$6/FXW#d8!F}öG +VyBzyGZ3FH=aAsW y6rQEEHQD'bqh-[ZD|鶱k"+ c5 g5S کRx]-҉vHON᭷ގLk#Wݏ9 !9D)bOav3Y 2_t~C>(_#|] 4Jl~KkS7cXDN~gzp$lEbXVN(h"OB|Xň@ZQr<҅&Z ~C$ɶhe]x<" D>@H+e>O!=Ҵ d(BtCu`o֪)ZC7 ))rUh%XYs} 2q)qRu]:Xv+ȡLH#kIPpX']Ëb!vW!n;FyiA!UG .,Xxڗ׈,ժxQȑ,sk0V^Ң{*1_E8g/'NONUй\kŤ8ΘXL]'FM7݈s#GrzQ#d׋!CR s:H{̿X/QjŠw"b\7q\kȅCK+1`)B :! 1< m#Fˉ?Bl6K&) vAk4xI$L2fB2iv h;{iFw7Q g9}aF; ` dn8{Q KX9T ,A2ODb!DTuk D B DNGV}V w! B/cuiQomK9 rpٳgmQ!ks!Sf@m%ٸq#7pC2*\TE~ZFw7r$1l֬yQ ܃!3R\?cJMeޅ-ͰPՈD%b(kS <\ *rHo\c/"#* Ǚ,uc;oI+F+فtXP(AƪY<]]]m94Ph 1IbF#4?i@,G%|Rn;FXې ͈R}/C&GJ~ގTo,?KN dD;i( ݪV#!Z8|,!vƏͱ ӻ%HbHwö́vV]i;Z g!r{(c`fqh4&nSK3>|")ݯ#V_ E*Į DE&Bo#jxxӷ!M'loȅ+HVĢ{sxW[uȝT$DA_i=H8x5G0$Fj[2 L\.ׄАj#h\-d<4wIR ',ȑױjsGRGHJWq? Q W'~QBT&ŤMU= QǙ |"!EDun\LAC]|?}S~rG͊U q~Yb'xb2*\f7rl3׃vu׮qN֭[y;.EtQ5Fb?"#]!W"2KD5CH[2.׀o"^B*㽊}L|!D>nDE]d~w~`Mck6얇B{FړnPЮ"\5l"Y; &j,YDQv;nClH[НH͌!f~x񏿅L݉j*DނU ?X2\(Du!kDoE.*!_y~<QأFr\SvcHr|qvFT*'^4jB5 R(rj $n*uڸ5X )U>HHa.o>Dw "} |?_$Op '4f6 js5b'& 7u%AA>/rnPH$|9|H\8Bi0F0&w/%1!B !]w 5׵IfY\>S} "D|4sy)P)ϱ'eV8|Vh5eػOVkp>|>bd2YTvGqFК Q՗> /1ߍb #L95g})TA"Q"Ma%e!yHT(Us!AR5!ěl5S2.oJ=LRz Pk$F[FF~aqY> `%V{rZpv1`O4/U>(8BrYp/@H $DmBr)jhҌg $3&B͘Ȏ7̿S>`G *4|τQP] 5zv i; "h[v[ -G+ *rbcǐI ŕ $#jۈbBZY6[@9\ ݱ+i6{: oDT #ax;{$4'E jhl~TKRc B ۩"V Zmy7Q3r\dIJفxD?UC9X{d" "QsH9HTIHƉHHr$Do1B vD5i J:"!>TaU+ԜZ 7hPӬVu݊IP(g:Ֆ=xY}3ղ˯I~cw$;XO#{aB? 1N'f: S.G8BH!J102N)mGeއJ3 u-ֈj7kaߺv)|>O**wtq$ X7tBZ+uu.?@5g B_B {~LfQm|MGX*߃uܳE`ro5oo;1Ih5sLVIviժf; $M HRZD"O!bKh% !˿COyN\qoGHBK Q v>VnD) o- OElm1ׯ Vɋz;DDMq:\G&V)hiO:Ĭk ,Yxʳɺid1 2爅q xBнqJ?ϵ} B{=XzD#gܯσ*; UxXpK˱3  4pY}zǹn3LҋF|/#f"VƷ7#7 D ;}CTtv85,Q/~3e6BS݊W=q g">q$,pYrWֵ:$‘j422m=NǫZWU;w}:?gy&>@;['pdN&񠵗,]]]T&~? !40#Iފլ[<\ÈR BSތ&5*_rb.?(dXE| "D dDh.O86ս<ԇѬ{x{T*5n~;kx衇CP`̙ٞ,[P5Ճ9sp96"4L݂xb܂ěH/"J6DRo#H 2)”C[l\e_e\ՙ}}H:$/m~$wu\{,&T*JRiAUgWW䛼]⋯ ^6( D8`!g~Q e?,@b (K# wIǷ!=H\}iegԸOd\uU C#<2vmJ֕={6CCC کW m. u5h%|>߰xf㧟~dYr!DC?g-H_cBV7Kῑr0?9r2`w HD|/eOć."ik;4|ry玾3jx 1m41#/^L__g஻bӦM 諰QYj:ht1:d rMAJBGDU3!DA".r3-D"C̿}XEJtl6K G"xÉ u ͯ1퓀N3ajUc--5$^+xX\@ HTȉϼ!3 (r봈 BZt% /~cFE4NUN?w$fc$n$`d9}*yTMʶJPӟ!LU:SD}DgŚ!vm6!m>GTN@6>a4hu2xnT٭G."tQvutG0/(e?BPt,RU^(I HbHJ;7 vKZl'vʾZARt:]zլ&wjv ; C_}u;B߰"qQ՚蒷}s,jFFʟ.@[xꩧXwh`Ǚn8\MDa{b1|>_ӳGC5 shaG #-! R+S^[s+q"݆~mӵk׮l7Phim6&v 9K iXnDI;QdXk⮀HlYH_cH.$p)j(BW Yu>!G ˳XӧOx5ܰ2viR$p)A7T*LJ` G5ۡJQ0NexbIUym+4/U4Xٰ}5kV}mmwFSvM*;H0eʔv*wۓ[IDAT'|>_.B3ڬy; s$`!do!PUv%DVUP yևF8S lQIڣl}I*{pp#h'B'f|>ߘ1N!A'%ԋ(x0.v`]HG 7$#hD?EʪEIۉs$qW/eUv8dܹ _n3бG6d2qWLhtF  ˑd%MT*d2e8|!OppB"eC!7"ϙ;)4}9c.`y41F |>ly5 [#P,d2"T5.[53.;HxG31މ_$`*k.UhFck2H|r#!>؂E`M(IZ&%p8\ZܠcQYʹ*-=th5s5Ǫo<5L f%kn//5oxMOrzY|٨#Tms'6TvK+{M^7IbiPQoHTYZ,,"c.r~ 7CZJkTZCg?{˸>7Rs&CÉt:;•m? 9 ،lf$IjMoջn,xfe$B-_4R`)|? +DUKJ*ִ8Y^Ԣ/ W"N 4lUHQ'~3My{?Qo"*{PkAj 1R|!oe%|Zs챚lڝ΃={0}tT*E(j$`#:(ڝpRˉ?ډJ\ {a֞|6v߆L >Rh!D=!8nDo2ƪ0@_P:|nVL] <ՃRċ/H6_bS5\K]]]mKX+p2VWjSW^y)S"D:hqVF u|2_.D1L!4OnxD0Q&;ҨT{O>NMp-ADﶪs#E RTY+F!ff:#XaVhhI!Xu< d2BcoȎFӵ$.j}ظq#W\qNp-A7!U7ʪYO;oĪ^7y#jXӴjeӑDQv-]TjCƺ\[- 0شiGsgƛHB6vWPKbUjŢ$WbX v܋U"T"B-4lKmwc뉂~_r7|[}ra%nC6e͚5̙3O?Ù\KЪRM;9bz)zkȚ ]]}fm5ޅDyNFbwcFq gڴ8{4wG|~Y;-o<f<;ȡN#X%DC#@={567CB3V7 W_e޽\{3U:s,=0ҭu'5k䒕F/#eҞ-Z^TYJ1NkWZZN|[<z7RhU'L:?^'p @6*(V<{u:6׍ՇQ^@n͈;${վV9z(k׮gΜ9-Yg+r 'vҏdݻO^no"kadrٛ(2R *0 ~kq5׸vBsNR͵N؅BaX(7~*ЁJ%8իb``|##,sй|P'a2PY}}nC'\4W`׮]<\x|hZyNƫr\5e;tB:7|^x.5- *h_mhTI=h&>̺uXb3fhpIGNI8)[jO5?ZѮV\al߾~W_d Wt-5P[jO5[i5Jh-%aP(~z0z׻=aRNQaH[pkFɊny(+}&)k֬fU/JqM7ԩSꫯfŊ,]/| z#Fwݘ ]0adY2 l&6GΣAU~4% wABfr޹s'=+W|AZN=ݻ^smư[c2tmlHF5IFÍpa tm76J%^|Er]w]]޽{KXh{a…,Zg}RW\ʕ+ ܊#Npu90ȄƶEvyx *kJPժ9JsϱtRN:餺`v\]?~?M*z^S:@"4&)Nt:Qy @`aN_gƍ QTO~͉'Ȃ {X,rs-4hCG[&C+"4ܐ|9` tnz4 M6qQ Ǎp5Ap{RrRLh'a;5|ըsoux_d2Yyqimn gرctww3w\f͚a5+[sD쭑.JڭK.aԩM__H&lذF̞=ٳg;ZK5ׂVqr1VwjVQ%alݺ_kfR_l Ji6noA$FN ZN q ;ϳvZzzz89I$JdY6mݻ gfΜ9-OujFh(+5NJמHS#Gn:w2{V wR`Rt%g߾}zꩮ?'zܔ)W :%3T*qFRy{\-nG aڵ'L2e˖tr\SSb4WOdɒ%Τx ଳ}/aoi&2 X͛Ǵi:cmd4hߜlG'xlذ/)S{8 n lܸd2I</Ϙ1*{BI5E:0 _~Crʎ8N08r7ndppX,FWWc̙;5E ˕;lk2k,H4:ӡCX~=]tӧO{ ,JZ`0HXG?Qc?.]ʇ>!~]r܆F,^mbڴiklڴ}q#@+Uf=I0}ifpoS/ `lݺ5ֿX|97|3?0v,\xu-Cw}*y\.WDF̚5\˟Ta Tܹm۶qWO>Z+O}SDQl] x͚5~|{N8WU;w}7XޙgO ;h  ;w$ z"2]]gR /@X/vx'+&W;硇cX Bo ~:~: [n婧" F9s&#x:1|] t}Ht@#EnéL&Yz5r 'xba x=v { /dLx<'׾c=ƥ^ښ@ ʩ ڶm>,~H$RyWYl'\.0iN{i&V\I<ozYdIBTbΝ<$ 8 ^{5ΝKOO`z͵"aĨߝtXx1}}}|e``M6C|_D"U=ܪYnG޽S+MPHnWML&Ú5kX`H ·7I MG{_gӦMrr3uԎ"vVH"^K/dx.y饗HRPc鮌 vbj-auVW_ÃG08|06l Hʄ톊}nXH>g͚5L:s=#0x)0 GqF;V7w\f͚ꦂO#N>,Dcǎqgr:ba|xedÆ >|xXžYftT3 ;v}vz{{yپ};_9=<u#hmC2dÆ 8ph4J<g-)M}ݎb X@x1Hlܸ}b_"*:6]ɚ5k83Ypaڃcfy饗سghh4ٳ3gN]ʷ*ڵ-[pUWy 'b̜9Pn FTbÆ d2.Ro"$O~8?͟pBx ֮]˟rmq, lٲ;v +52a'rAN44W椓N&&zxA/_0mO?M  ͒N;طo/_~oyxK }}PNG `ҥ\uU0뺸&&&,'-hv h(]ס:Ad`&<|>ۡz@e$ hX,ɋ& [D_.lۆixzzi0 ]]]Uv6E"@$Hr\eMlllx2 >c@U!4MضaTwwZ777xCNգ`@3LD&8S8/&I. h:* H&xxxWapp}}}^Jb@SL˲066a `~~J?+8;;C:mۘ,A gwwx2SPBr\ՂD"^A O˲055sy)X[[C>>Za@ӗ333XYYBo3E޵@REyD5}K:B&''1;;!P(MӰq<xIH_6b1aggGX&HRAIMD$)4DDb@IMD$)4DDb@IMD$_dLIENDB`mpmath-1.1.0/doc/source/plots/spherharm40.py000066400000000000000000000010551340375245600207260ustar00rootroot00000000000000# Real part of spherical harmonic Y_(4,0)(theta,phi) def Y(l,m): def g(theta,phi): R = abs(fp.re(fp.spherharm(l,m,theta,phi))) x = R*fp.cos(phi)*fp.sin(theta) y = R*fp.sin(phi)*fp.sin(theta) z = R*fp.cos(theta) return [x,y,z] return g fp.splot(Y(4,0), [0,fp.pi], [0,2*fp.pi], points=300) # fp.splot(Y(4,0), [0,fp.pi], [0,2*fp.pi], points=300) # fp.splot(Y(4,1), [0,fp.pi], [0,2*fp.pi], points=300) # fp.splot(Y(4,2), [0,fp.pi], [0,2*fp.pi], points=300) # fp.splot(Y(4,3), [0,fp.pi], [0,2*fp.pi], points=300) mpmath-1.1.0/doc/source/plots/spherharm41.png000066400000000000000000001117721340375245600210730ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwx*%Lz' 1c PbZ@9!i:` 6cq-|{5#y%]iW<4G0uuuYm-=l-CBbade.(ڶV%i"Еfa~cXJHc6g-=C\33,RMtMM';;1lZ$!-/3ÍTtgvМ!zb1BPԶxI7k.Ͻ!ffd+++ϯKz+F`ӔWBz%j,Sm3UK#=Aoh+17U`|~YYY_Dh^Ꟈ΀G[R P\\ @]]]iaH$` i[R,mG[ Zh |>z7EV97>VFK}3:^u#.d(((hwEUvɩ'mۧþ$Bk"gնAwQ uuu~1z|Va3mM#77׫t~xmJUmVmQW F' m==M!S[[Knn.|>@KSx νhl)p_g"H^:̹}\fv{׵t"; p߿SȤ悑>H`d[e.< XⰹpM!sf?lJ:#S{3m =Gsx//t#6s;єE\02^5e#?p[!y:Ma=*NV?']`dc_55"R phMC\02ю{FlDR"mߚ&HEiv4_'c)E:P8k¢v[&ͥ5^;Kk;vFnݒ!ߚTǿ@ 5~Awl>^4VWW'ü5s ,Qosڍ- FvF8Ց[CGƙ%+,HCМ_&.?f\IB"*vt"^Yg=MON"T Ex_?;ͭf9[Lp{h}?KbFdUG{G)D{f M<h22S;AՑS.\{Ì STdfxR*#J?hOtWE*zfl-LZ\02;8^wEEkϝUzH'}t v`"hHcX}53 ^vH梵TٴwPh ),[悑Z~=M7t+ ^UUiQ#m-uk\Қ"t## D"t-%X**K$٢B@Ozu-MZ]=i2_,M 9fQr뭷QRқ2JJdwJJSRҋ{ҷ6L4J~?yyy|>"P%e]]H˩!QR~~~}QVnn.>?7h͟h4YR)&kjj Z+ S`=󚚚ԿJ_@,p7/Ϩǃ wyg&//oRel LT?&8en (,~iƎ˔)Sظq#˖-Nx `bhʍF(,,^D{vO02D}g p'pCNCDޛ RZڏ{ッq#m;y>y5&8H$»YggwŊ 4!C|r-Zʕ+9~=[őhivk]XPPFmE{A]G8欳.^5 B/lT`-0˼zD?fÁ\~u|V_o 2k[76lönˁ>l)nҥKoXti=YϘ1իWs 7GG{&glX$gF0kEc63*8Q[[Knnn[=8/%@wDQȋFv-?'À@-P,`o֭[k/kTܤm[ @Z޻|;`j-^xsOvap9PZZJqq1#F`s1,]o}7*nk [Amp@}Dm:6mD~C߀+X< |sȇ^܈=~@ (1%ƌӆ;8v$iRg+`0X" N`)Y۰X|qW4k&R[[k:~ӟ#u|@.R9瓁F^*"0"` l5:ӟao H %lMS;rut3!HZl޼ݻ'yDC'df7ӭhSH,5~{-@"Ӑ͑| a{ p|D;#ב1f@1s/4L~ )4ICQ[[KaaagғYwfF2۲S[h˚ӕ7UUUP\\"9W *O|vEg`"ODA`{d{x e|;"q^zXn=EH(#]m"J1]NAi~"TUUeT x'pޛn-sUנR dc erlByP O>Y"7ȃ^ lDH2~s7w9c[[vGZE]S!T i3'[fQd+? K.E r="I(Kc;-D((=!ˤ GޟkOhc[kH*p-#].n/Dr~'Vϼz3J;] TR .8KX6 7S.@1GV#SRv-T3x+lt'D :#hMiэnkI}h2)<:D_"}~ڐ"b<|Hq .DdX` Y%H9oBj:R]SSCIIOb ΄q&qM@O Ss D3hI?ԻaESm?[nlNvͭGYF*;R܄H+*QHVIk-j=+DLk7!bJnZTs>RQ0-ڃŋӯ_?D£9{#k\T/;vxz:Ҽ~ zQ.xz|DvGv[?ZZ0ivX,Fuu5@JZ;f%sR),,&]`oa(Ka2RSetn2<A*Fs"(*%"JO d E$ TcX}8ꨣo1\LGe #\|˃AP"Wu4!,ilHۚ݋{$=t>}2d" F"SYml<\s"DžHQ>ȩPЃPP#1)@z W\u?7ˏfs,Aj>f͚v]9s8cQ_QEG2 dAӝBXԌSdDiд=bƺ#6=!tUKЍ,'''Tvg~`dDU_`]6v-AݏP!% p )ϞHM?p-75?oB 9tǏksps޼y{":4@|26 Eجy !kQno)4E<%0Nwׁ%휜!DQYYAŒ8U%,ݺuKGY *@)a" -ȋ-@DF"(vnEi{ňEw>d5טTsXOV- vZ< s>Ȇ_"_b3RʻX9x ;!gæSNOI"f̠YtYrssӚ-?LjBHMg1OG)g#C򧇢5 /G~H>-|at%3Hg#B@*ϑGӪkD"lȊm9GHl (SY$S$\i^(@}cȣLl$mQ-TIEy-2m`0l8#D2]n*]x'Po6(BbD0g^ ?z"] } zBzo(d"!WDTfڰ">V]_YY)2H@㑧>|c\W_ZWj'OФ3żnǏibqi@zFK^r, wk)!-;:~{rSoڶ0׿Hd$R# )У Yeo F6/Hm* E*aA)jpR=E,XQZ΍gy_JsQLysγ-S,+?&Є/5gIO,\ǽmfa#QD^Sa񔔔PVVɓϹsw$^A'l#t[oBydm\ZyWQAv(!|yvC&DVUQOPsm~f~㨣NhQMMx>@ H9#O57#M>s/J!1AjAJlwĜgt_sVҵE ?+W' iOЭ Z6QAƥ;"H9.C5~:Ay͠n""et|i~'" @(Cď{Lf@KuTVVǴ%K:ծ"O5|, u&OnF?1-,eոɵO M(;4IעE ܣ?6{ERJJJXp!93۷x+4H2˗7x}ƌlov9GDm-'t"H$Buu5h'R#"(Cu(X)! QO8|D!@3^~E21 ̙3c}]vGcH94_"oB(c4y؜E(kDehrZi~5{n5pDz^{裏c1~-s*JS kgB! ׿fܸ b{b<ϢߟB5w3 2sBJD?A䝍"?A²z|s~䣐~$_BЗ2D&&Bpsgm/p}tʋbV oFh6!}q&"sC]ǐxb̶l^ն(ƭO0 r"e;'f"ռuKSE͸B6^H[uȌB!d جtD0I vYYҚ~Ӧ=SD2!7/B(a,"!?CDdsy潋QߎOA!i%EXmˤZ\|c>∣4m=M&lBD0cڀRwfȏy0cf^CUj:}-wW||=n;zd0&//vϷ =C$w R+jو4@~sȏ";BD"r|XD3Q6GNaJ g̱ ]jO?<`>l( x"ըȫҏ·h"y dק°ZPˣfE@8nwZ  =c1tDFt: uM} mj+V+&M7(-Guy:dmtG=Cgt ȏ>3Jh7 ;eR6CXLڧDھ5r  V>>T0&r0eʿFQ\)"jDx^2_ ;NAWP lԹ諸|+D6of36pXlfٲeby8w,#?ڇ슙O_% ;ȪEVD\Xl3[̵ӌ1l0YYY &L󿟮F 4&xgۚf lt[*~.:pQ~.HAaDCwߠkrk,BOUVC vGvBL< U-hҖcmKf*b5jGyٻ"1*YdQ9RŐb+Jɻ eX #Ѽ1w8 , ?*Jٌ<:B9G"BP2DW8:_uf͚ŋ)..hv`ⰽ'U+3QXXbLUU'|:fC,GD="ld7||\ oS}k2Z)DV )PƓHY繨4((x Rև#y ~f޻ɼ'/*0ҷm0*8z,R|(m0Ѡ 6ևB#^~WFUYȾ3_?BI0 ꅈ%lzCPUUjZq= &pmFtG¦Ev/7F\\\\ss̟y~D >D  z j9UA Jo=8ݘrE8i8ܘN4yw# ";j)JYK>a"0j{^ `V !rބkPԕc>m2ۗI.^{OSỲlC Kة$7oxZ:9)**jp{y_C Pl} Ji4RCZTfOy RPEHmFu"+QO/CEr6 F b[!/{y4,E+-z:A3_Jmy5Hs;2De~vMd@^s/EHUi3RڑHӶ5v3sڻJG7ܪ3Sv@"T>޵؉rzyGNAceXEV~:*ĸP+G#;Pqw.g\> !"?Mh"{9"BͰ! ! j5Ho45wf 2/[e~s͠#K?}܇?|o;Ń"8lޟ/ѕQ;odA'DZ3R5mBnm{NZcՎ>&BkDE^l/T"+q=݌?A"7!Y UWE~ < {]r.@YE]ODHs" [ڪĜD dODEfhz ,}ÌqDA|>?W'7(p[vLs#}d #:QI.>~*Cf팶1 e2LB=2fF5H(yFV폼⫐`^[kⶥ}Y aFW/+jF*?Hދ@Gp`3ln{3FvCcF(x,Np2(0ǘB8MxU2cZpgUj,i3GI+ c:jNB! m&=ǶWŘT"U;9q] .mZTHZb.B>Zo_ܫB(W`}۶u숅(hxʁwXj+ }oMFqDdYcP} sz2M6Pr9#H5&ѓE͛74Ctitd_2N :X՜|Tc"HVe{7Rȶ8Y#aLJԹ P1KCygA\F5"4[Uw;*B4G anC}twC##{ŏ&AĞw2Ǜ=lg0RC܃PՑsSgI~B:#CͩWۭ-_uڋp8L]]]}Ԡ#"Kt{_!T "0 28AA#D̫"1"B`9RÐR_wg >׵7>yRߙmcWP>)O6[=~cnGd4yzإ>7`Ӧu[<8hLmIw> hkg|M'v\~oE*[Dj"l_ >Ve!*smKbO漗!%lH _x1监BcGODD|0٨'"d 1g"+eqWJ[CCb/ė _.A?m-s~|JJltb4igIe|mb_ȼ'H==3PA^yGsO[rRKVwHK9\ DvX,dj+X&Uco\KJKK݈T(%g,  r ~"8=G"kd%"u(-y_. ]z@E.Yog޻a6"etU9?GOt"3*RAO Q@/1jB ,Zrl{m~.5֚qI;6cvY%=) d/ׯ_ǡkOCmօm޼Y SRRBYY'+.F0a999D"ヤ\W8uuuQTTd#t[x-Ci)E~^|hg=#7(Sa [o5MEA#C 8ϜoNzgҾ/#44qCDysylC_}pCE*uflm" #^CNtN&G5h2Fjvy..>0tپχf RƎСT%-YN*{9q-d~iƎ˔)Sظq#˖-`֬Ylvs= 6Yfmqd c'_:Yn;%RsagMFu1 H D}qVQcۙB`^E3R΅H4,Qm^_ڞ*q<~saiDKpV~ȌsR'RQJ *dY(R˧I8ɠ8 hXh-\HLP]}XokIEruZzֹ(˿o!Y 6J-seƍ3m4~_vbŊ!C|rfVXA:t(˗/OEA :Sd$h4 Q~WudCߑRR9۴|ReߋHj"ėQ]q$ M"86@Pp}:Ƚ6YQeBנ/>j$*n9V J;ף #MZޱ}@83?W"1]"h3\_9nhAa޳Bmv;T ݚ$Aoj*G}43YTҥKIٽ}ɒ%)[~@)a[BMŨ%QPPpަAZ޹hg1if# lAQ|&KpHg3"~ cG?pBDS8SH zDZ(o6`9OQ~yQF S@_仙|iw9vk`9qݛ4a^ߒrN`sپf?E=A\mG孯D|WmI=9+ܧ֠-D"D6>^q_sΡbFQO{.~`02:cqt)tAn(j WWW'}#;oGBL !xDf+Q.4Fr ";q&UJ%ihDF2kHPf<)(z "ԉiGYHG6k1W/2s m9f֒yY2͵X6O{" /(=sϊZF*aΜLX.//;!O<`dGЭDVM{$jjkk),,lyNBt:vFg ь~ovq5GG"ܓyA+IA}1N󾈐i?\VFp|:j}blj7M~w9T|/ñ# qY98+?"N U϶aSg}vsoQ@uCO*>DsZRlP:qܓ\I5H1ufDCF[ ks$̈#6r=S@+}m1ycx!"UE9)QumPZیCQز6lItN$j=K@* 0hRKfٌ۾Ԗjg֒&dA Ɩ[.?sm@DODTy,οzgs_f;wg՛>ht $Vhݻ½hAIII-c被P]zd@B6(j›l=Sl"#·@9޷8VG" a=_k9t@ӌQڊ8F bg#M}yBo[Ns{dEϝf.X0&&0"<5(^Rbě':eԽK$i?kYY)>_X*oB%Yd##xDR`{P[iyfw4,pX*1כ7MK}[9EB?ƌuW1Yd;31W1H~1*6lm:ڶܟ(`x&O1Ȕɶ :$"ϝ`;red `M7n<8e%h@$^C=B"z.JFzՈtJPjgjM1G2Hnb89Y8awZr IDAT/ӷZwj={5g^A?"Ϗz~ӌ* چP̸FMlUPsN9GKS?9?Aǁ{xm:[g H$G˜9 bk)&Yb7 P準[H4<峑_&[50}YqtXyCQJHSr[ 60pH\]_ҿl"U#Rf6\r IZ⤵mrMEq84A NЦ G/"PC=wsmD4aG%"kVD?\YP@I`?|'tMVqmiitTmE&\K$4oΈwTt"tk wq_~=" m`ZHTʮZUZ-G v*{1N|󳭾a ׶&C8v 8VMdzV6Q&~`ȶ(E)z}HrNFI>Ro#{&Q<ۥs~ufMU`*R`Р,\ "n쥥< EЉ|@%x\ٻ%48܉KzEG 5޻Ү[n-؉ت:^ Z2*s Z~C 8q ?F74 "b/@>kO<ߗ(@}Pz5 2=xxmEix_)̎ 3-Dv{R0a7l`Ze4pz0tMl_#bNzR25 $~lKy~^LdZ,njImd5RYYI[ޱ1 kg{R@dFSfb',rJFżr$N("(x \:DjbKPO񞎼S]9HNE$t2Dx("Pڏ:"7RVZ[#DWwFK֏C ~Ǿ8x.Z(w]Ie3N;[n$p~%r'C}H}s}Ef͛8˃QPc:|d*DNDJK -+"_ JC»l{pοH"%y""qHg(Qbը }) APs5tGŖOE^UhY[ߎ3Bolz/#g9j4mk*46y~O">eļedD_R[[LiPϟ͐!Ch v$WnR F;tɩhs9ͩ h;haMP5[)R>됂.B$tRu"9Q!D8'4E# 6 ҳ1C]&:1c6c϶0FFCYHNB>\+(Hw)"W?Jo}5"㕈ܯDD2gyR=EP@"!<"J#)DmD<7H.@N "BjC]7Dțcmp*Bd>d0Y ABDy(Z>D r83W{w**̙bRBdWdWl_ky먴9@Ĵ"~"y{""f#%p}Ο]^ވTXgG mܾH~l"(3s>E (q'zI~OG=n jz=e,C B:\>8S=Dr4f"vxo3}x?sчҿRp8VkpFzv&''^Ioڴ/ygQ^^NqqqĺdfΜɔ)SB̟?~2bرwq^*F8mAF c7kgRwGKi@65TW_}{#+C`?b("a[RH"̷PC%[B 4#;}\dWgpJqzI۪µ8"r}.u ǽ1\ PI[hYC$PlzkHm @|Y&?A3(Hy.<CJp+8#~)s?Dj{ XYAG [B]]]Zz\x̝;rN?t{?deeqUW{orW7gҥL4G}M˦>Sa9ўН]b>ͩo{;PSN87x.i*4 R_""z§mu#C8v=,sYm~qx1?iYʒ:8HGȚ(E9҇< D{AJr4A'HHs>"e<ΜwBE8z˜h^ Њ)1&̶g5˿ekA{Wٳ'sLaÆ1}-Yɓ'￟;ڼ?fR߈!6" RVAGۡTQH5]6?~er R9m 5('2ʑmr 7zY>45BRۧ m-pg25dD/1(3hr+jnR~*0YH7 iSmƵ^о&M ~MƤI6l("r "0xR! "~ etCJ s(xR"$3{QfFZ߈/CO ȞMݑ23'wyRt#`0[o뮻;]S@DW M%ɦ2ghf$"Z;jW">TRZT}\"g3YF^Jhང,u>eoB%f&,~}u"by 1T.|Ñ3?}oF#WGr?*iFE#{qt>!4>T)hF~}ῲ^_!rlև,Ct zm$vܦYLNڳnC]]]9#Hnii^MsssX40k5Qs]uo:"BYd2YEw#y $wT!"*GY74Z4\Eو>G~( ;v =׃HA$/F*lp"m:kKck?F:/su4"srb {99~ǿP[RQ8w9f>d}mH'9/bqq"cJG6+*ǎ?zs."e"xڴ5QmTɻ+~tdphk a ^u.pFHUD@ﱈVjf4ۈx")V"텈8\~&[?7T2}%8v 9g!ib%BߍG#[ $7 E~%5~HM(r:ƛMC$yGԗ.m5'''y~KK MMMAk!#"q+"4'AB4Q Kn7ZQᣏ>Wҁ#b1Jzt^JD~;pw!L!Yt!yp 1"m!M{3䒇&Y124Y Q?"yd{u˰"ss^gV6Ht4L$e۬F;Y` vNNNxE"I#4D}@:MbNNNDM"\477A^^W^yH r.C~!_l!l@춡(XH/J@fkBBA#k9f=n?JA},~"Qt>%/f=sh8lEY,rPd|30_$4)@' 7^2zˈZg "oZ}>B=F 3s;v|a03g$緮.B 466O8N 2&oi-FHLބ.P]"D된(!WtH4X3(f9aR6"jӺ_3*|DhY\d{Eyȯ="!ko֙NAbxBW wz X똀"fгg۶m)ؽe@4]xv;^t6Mh+DiDz{qD2 IDATfi72DHgyki^O T>mRnZD'u"ȵl,B-MІt,җ[/gƃ҇,y3g`| m\mCޫD1҈;eײMjwˀ\ $;R.vk@\Xr6j]\} ڏBh)(gݶ y@ΈsѥPI0UG䗇HԐy &Խμ'e(DYF?(1w'":ង$_{[߁$A Đ9%:o 38JzvcU" =6᤽(]eA;"'ȶoB{D>u),@PW|oc6{pyZ?C: d~Bu-J|@z!ueF SPjBU׼b5ҧO Qd8B}HOhH 7F}?@ s%2 %h.QɿREJP45=zzlڐDN]6̙w$Jڛ h'ms /;2R#A7 ^kDF1>^cHlhv6ͩkZSSCYGv">HC5$OT!]x="gM$ M!s{Zgؽ{?#_?Xwt"sk3nڀ|H13֠sEZ?BW!mmHk_=cO@ l '@,y{m|fmhi❦ 8 ަOSŢ٣Hm nLQdv fc@N( I"ވlc"2܃h*"5D䘍"$kT PBXt8KGHn[y7 :ځb-@I儦k8hM(ދH6%z~3)毄zcEnn99~;n$wy;W]uUcG ?DV27 ]#qR#bq" B#m$yTX$"T=" ׄڤk<EO:j]ebrsrrUˎml+я~Dqq1*7x#eeel޼'ۑ1۷xxPII륾COsD1YD[jnICs!a5ـB=t߯Py"? \k};"7Q3fYg(vu Ǣu;;SQ#HX]J5|,xEX6B@&ߎJݧ y&Ʌ"Y.>Y$ Y-D%cٵձ;|ٱ"++O?on߷l?; =úu?>^{kMIӜ hhhh^v,xPY/jt-D͐zT FWu*V#2 5dŊN׫ךi- my*wG1B7feUCG 6s M0Bik,he޼[;}M#Z{rn*gOd'/;Nv#FgϞy2o<*++Y`<g}6ׯO9d(I=ݧ„>,ڻι\>v"u*j6UN(,4c_#5NH腼;Q~lwC:F>6 .~8&pi{/QA?P fʶ#)TTr>Ϸ'zZOQH!;j ᘬymǟB Rʯ^ǧ_E=|ӂ C(D&8Q s&iڰ>F2W 43yNT)M8FvNJq$җ]__!E :Y; i677vˋ8gpbgzc$"&vGu?@{"ߢD("׭P(*w3s]Dɮ W WKbBg": j)jٱ9]Id :7 F2$nD.59'9 se/Pjo3Q!D04ʎ՗* E :`>, X~YaMk QsU>PϺ}$!T:*ԸT!ºPB(yhP@zRvAff&J9(}I)[I(yJb>C5i?PSKB^nPts%Ws3>McRp^}$yQ d#=$Q4Eg[+$tɿRT{#s]e܌)D)..6JCe2P䜏uyQZ@$ m(OEd&4P$B}:zA}r,E&d{ {XsᤥDG٦lhٍ1L)I)q|>̌߇' +++8<\S_!C )t ;k^d?E@%"OQ5tED$hsiy-7{TG)..@K(ZO62EZF>@}7T@Y?O#tU1 |u<4|3ǰO)C)Z54^7c1#8Ypbܸ" J⬰J "Bn@>M#)7rlH] ]ݻ3 N:Z֡=q'ҍ7L ""~YV ٢Fa &=;"QE@#nJ6 Kr&F^Yr%MMM\p)Cn9x߄sQs_5;qyC$"KOA2hwMֿQi(qGՈH[r_DŽ3ʕQ^HgPnFHO68Pӣ"4[H~UK66FYňܝI G[0U(6l[Ukhh࣏>b\x)CΐI mnY:;ci -:}W\q^x!a=hQ15ӈAɸBN?nw-_|+k6R$< $\|^DFCzR"#= 9? Y. DaƗmjV۹s'| w7:!e :B>u.ܱpbʴ}>_LcAg?eMD(.EgDp&Ѷ9&ꐵ3}|^믿FFF6J݆"_77f*އHw(%G"^$QOȆtt#?:o'Zjg4/.Z{Tqiph pH+@ Uظq#ӦMMZ ڂ8)zp85{Ⱦ}9ꨣ{ٓ믿 e~yA% t=] ܅; AKCNFP%hEэc|\._|1ƍ/ ofHRT u&222~`u.DMf`@AA# εuvvv0,C,(.LrSGr[]1ңG[ J.@Q2$]|fx6_Ed|\@nB:nC^cFFF#777f&@׳c.첤G)[%⍠M׹x67J<_2i#U=vݛԑȸ %^FM>CA/@ßsԭ%߂H!3lL-:s:‹DtK$rx^/^Lss3SL9lR#A{ms---qu]go FeffFyDcM JIU,p_Gn~>hi.A+Hz >%S#JJVG~o գNI983Za!h^.+Wsg 5x6qzΞ ȳioB>:A[P#{Ay?ȱap?Wuԩ))KБ|! bRM/)}9^oDHuD4 e {5B6F=Dl_8~3Pᙈtmn,yvOn J.C<ġp@ܛsd4t 4r:k?J,^c2rHVHYGgs M@ ssni.5F͆heˑLQ m]m&r뮟Cd 3qV(QPI$BJElT^Ν䓛v4hSj$D.9qپ};_|'N* ohh[oG+8[o%''9s9B!mHsQQnuX`%=62L4+j%tdggG~>쓔䓿C柣&GW!("QwQ "hK"WP_FHDZv9^{uh&yUM g)ISQQA}}=ӦMs?SrW3}tmưax9sYpa'GVf뜩' DZHatUf;S:c{?7,_"1уȥ"%rdW+A?EPQD}P!VO*x}McL ǒĵv4Oի\rIL;vPZZ ÃUׯs9'5&)AaL%`,o ~b6u& ;aΏ=r  /\dxsNzzd(I859 9:V K].z H0:rC; kΒ&ȉץ{nVXE]׈CuVƏ֭[d{k.x(++NkN#e5h  yް̈́;lbz5;DTtYUW<}=JT=Ns"1GHz8XP< P@57_^oJVBH o웟:C `͚5ٳI&}.ٳ'EEE5C2qDnʬY={v\ϓ,A<vÑaGdЩ9^ĚxL2sNnm~~'ңZ|"\1*ށYe<"w-A2D@Kү_?N9.Y2#e BjGhpbؚ_R>գt… 2:$O4!Tx2PGLT|xoNg3?k"~.[ZZXp! `\p7N4AG:NNFͩu/%f"r*@ @MM z6{xQ~"l<<i\zΦrqp2{{pXz5]3rH~8DJt$%nǬs&jve8gGFw;%[qᩧO)% flIDAT#얖nu{2z=A744"#1j#;xt<=ha |F 'ٵ,]SO=C: )MН6~LGvvv\QaFm"k׮eڵL6+ҡզi~M6n:@CT{Miii3#}^3$piQ4p#&w'#m۶f&Mԥ9#i~-[f͚`!CPRRȗ89ًgRQh+3s;1SQQACC^xaJTC@ `ǎTVVB~~>%%%ҳgϨ>mhב 3`,999pUFcc#K,aԨQwq0ΐ& k.*++x<\.z!Cݻw/ӗAة2kh*3ٯZ zٵk\|}4"G@}QQQeq <8D6ى'ObLdXतaf߿'&]H@@`ycذaׯ˾5ى$Sr@w67 Y'އ&-[F9Za%3gRSSC]]/!se޼yu ᮻb„ \{RQQAuu5.̀TǍx&Ys"̮xtRؿ?eee|[ߢO>?.\:Nvv6>^x!5͘1nѣGs5K/}8~_ ͇?le>y䤓N ׳gn[%\رcMjF6ѻwoK*++ٹs'{ !eg`s*i~<999 `ڞӌӌ#_'7@ ƍYnSL{ƌÌ3x7;v,%%%|'x<~aV^M `Q{̘1&MwU:#l۶<߿Ǐ>6dj6;;_ٰ͛a]vY{t^z)?ϧ)xҥ̚5:*u[>_|͛9#%xsR<ӑ9U`` '~?+VqvFHǺuظq#ӯ_? j \Wv<ے m0iq,Y?QF%|iĎ4A};eddaN<Ą>6?Դw^gÆ L8Ո4iNzͼ3nܸ=zth ;gRpr֡?O?e۶msu׵r |HyG* \LKK z+.0wܘ& ;L/_NMM 3g$++m۶uJ{Ǿh@Ea`,hiԔL\c=eee :zZ븏Fb-[0k,̙oo<~O?4Gu'OU F**++inn6*--W^]*!32I*7jrz$؞={Xb\p={t`it%h`֭,Zӧw:á#RȠ4m ٳUVl5dm,d񌓒F `ݺuܹiӦđ4A;hf@e>(/bJ 80X48p\$}& |T+9f~#eҥՋ/܁ե]HK]pE33f`ȑ\~r-pwrA TTTPSS墰ӿGH%sӒFuu5˗/g„ ߁ѝHt]r8Ъc_mN%M6W_1ym`Fk :n{OAAAP6 N;HNT6|>K#Y&4TTTsC:cI{h,]O>aÆ|THtI&VZŪUOdС 4K{j85yi֭[Yv-&M!V*YA4#xk.***xGa|rՎo $ ')//0mڴV# +BAAW_}5ӧOÆ ?fٲew}sm76V9sc B"'^$ Zvv6cƌa̘1HrÆ |gTAAAB mmiԵܹUVq;J#FgϞyA+heee zpsVVT@ $zEw#++ѣG3zh@$i&,Y@~~>{I0!@ ի9pSNMHϬYZn<4iB"'^~?[la͚5qQ={dȐ!8Bئ}`DR<ҥK8p ƍ{}i@ ; PZZSǾx\vk>cTUUqEѧO4A@ ]; 2޽{wHNN |fπx':n4AFGEEnEqq16zn qil2 9묳iYHtiD@ @uu5SOeԨQq'jjjXlgqvhi2F"\̪Uxꩧ$??gyWwdTWWj5`,u_}7nd /eO#u&4gkTEVb̘1uuuTTTo>\..+Hu|\ǹOH.}it+{{IEcǎmb> SYY$l%Kp 'pQGuH! :nEz쑊(((`=Vb͚5TWW~7K#,G݊p3EEE\s5L:@ #ػ/d<L4wy[֗sHtiAG3/2999,\:#$ai}Œ)X~=UUUs9ݹ4 :4g{=vO?3}Cݺ}O:oH$2gygIe)Hd5]s73<̳ 3<,ygygyYОygIj@{g%ygygyYОygIj@{g%ygygyYОygIj@{g%ygygyYZzs7m"@Off&iiiM̳i@{VoD"aHP(DYY)))tIKK@3`@{V/ BA"Pr;ˮ322HOOgh27c*վ@;PQQQɪSRRHKKdڞD<,.D"E}rjj*: J$h{G1=E" P@ @ZZiiirXlJ),Hٶ'xОhg@:jH h{֒hb;2ZmɻC6PL222<]۳e@{Ŋ̈꜁ms<2 Ŝb۞yLgD5sMd`0㯹?6YҘОUpHF" BXBkbi5n ?rƳ|>|>~ihϕJ$I*Hg#Z:<6?ِהJ]^^Nff&yyy f,SL2oPg%ۗDYC s3Y;Ȉ8VȨx-ZNOOl6XhI$%j@AX8p8Lff&>/vȢܺmthi$:ˎ,zuuιٕ,):жH,];ڲ#cY]RRsP(DiiVl[iӦ?(Z9jԭ"  >fziitҥF p8$ڮ%Uzz$ٸC$ivrM5?BMlёkP(DNNN:k臺`0#==@ SOv ÆE \ X,86j/H,vz#g1li̞.={m%ٸu3j* + f[ $&XE*HŢ$_tN&B ،YH8v.bԩH~8<4 `6-"T+ bsKI⨏*1&Xl?h`nnnV6SH$RAVi.´N:ib[ǀ@w'@ 0 :Zp4p&?`g MN]ѮއP(T$?;;iad.uI6q;5Μ`;ScUM^\4`#03HO\r qd)WXƻ(kiI65YuIEEEe蟽s>4G3cڶ7n}Mk rJKKlrn"##,|>YYYS^^Nyy9~U0mʕCWx#V Cv! 3`"p~D 75Ų`-\^^^oWmO6, üݴ*1xmnrΜ9W^y_+#;#>qÇUs)d#1<  O~?wCHs%LC{0 xEq# (q g~%2#b9#|Ndkx vXfu+VpǰbE ."U`p>EE_RT4WӀhZ]ȑG2i#U$Ua wD ڷ", W<Ğ\';#}dQ|W]1;$.@&~ mjKɴM'ql襇jA~IMM%77KϞGbq(v p1(^C;7Kyi3==plJC!=-*giM]n(p!!I=4~A=XOf_wB>׹9nYx`BCtKLklV}>VR}콰RUSJ$[:As;~tfUUIͮZz E{Ƚ/C!]8]i׮ c\s[|[i:t !$Qڐ"q XG^ղ (k{$LBl[&O~a;:BMhcɦ{Gh͌hW\h8[__hJ=}(؇8%I|ʙ2[L;cΜبKdJ2{ݻnQ;x!4R #)(L}. ۠p:[ӤCH c}E_ިj{fI3T:[u53#0''Rވ:tؙ#A@&;yд8I"k^L~dѦMg:tho(uf_W֬YӁ{?h輂-0LFWއ4@ .3/EWjV&];3#${G-fP(QWP5>Ô^o(-ʩ tCASW [WN6rq'׹-Ѿ;~QOw~`O:H `X::yTg5$Jwx^=Жom ݐ h%*eՅ`zp;)cX}#3{+җg!M 62/r^" GΪJxCs:u.>_WxqWۓ0| Q(q' c2 {*}bi)Wo ҩKKq8,AC:W\q-}a\sS[SH_wjMI6X?|ڴiw˹*~GZNG37HXB7[#BRSb52;#gYBNDH 5KFǎ[=쳬[E h07#;ԗ'O g2:cm:RRZcTn>Sׯ˗/gذa|[wݻwgٲet O? &PPPРq%4Y`ugvpR!;;N?ڊ+C;s r[;͹OAaM@zyƵ@Li"=O!f+ݺ =km Ìwb(nw)F%D7!4XضH ku0fق(tӁMܐT :G֭9ѣGvʒ%KXdI: LBvv6ͫ㍵ܡs(W6s<Yg]4Ii%ҎGk-M@YW4^EqAL$<ס߀WsCXzIҦVgmg#.vG 4uC/Q#i(i g`%җdF)((`ԩtڕs ݻ>MbHv̰I&oS;m t:ҏ PY:bbkҠQ46SہP!h߁͛?$?x|wTT#!DKѠ%0*6!y_ho;!&MGn#T^t rئ.ars*[׶rJVklKdu >''>w \u?a٦S%^ Zf>5g#(b zY8Ѓv(iW"PMSc.(a8bvhO^{0cƌ3š#7|Hm$EGlv1>f-֞4B!~\uHIN_!~ v*SXYUk~OUQQZjfT? .2#(X@w(^ZҙEQa8iQem 5(t4NE "p8sqi5HR|b8ӸK馿VLgA}1"#=XQeg,&l2.H~ED$EX yyUдL⋯Ar4 BR Q42.wDaѠWb41p+55G]UŝO)Tu.C>08r11xp1[% Uf_Q)t)++KJ,@#3j+_ӏНd6uW$#FkCgmдs'!9A8&( ߁e~"C!rfOmV8}w#@.CצO2hq@u#@}-7>'IT[P@gRpس,SQF,裏NͦOgffV%lS:lhwjv]V3 +**(..ܔ+gG[ sFszGSlx?@,}2vB:v+@KC~4HEx}{\כ(hn>NЬJSi4kB:*VY3ʈסAqԿ;3ȱg4ȂpTڶmKc[.}:mT]t vDW4q;l,V (..& rEcyz_A=\ĉn&!fߨ\Rƻ `Zk/MwEI 'v\B@ù/b311 ״գ>f( 4جC@x1l[DI<;H93ݻP}i@~_j|R豺[m@;--nYdrͯ yy e+7Jzԩ @>QaƣMt/AMk`@q~$d?ңi5ؙ 3h,hGNOO0F$/A1୑V?9[ 8/; -gm&"n#m,w][z1Y6];a;t!n~sr*J6j-բ.j9dH$BII  9qZݚ}bve {Ϸ7 )7#Ym}=$@ʛp~$~ W @1L~u r(in̬d̞=^'|s=T48ŋ/E׽-ADZ3L {&\ %!0Jz]5l~dd-ݑ 999 ;[Nk[{nDUmQ[iJjTzsia'bm{?l^"` #`y"ș(b@f©9J,hzQH߂2&O@.=P:`ԇkDG+G+؈ @@slj.C0`.?~+Ea}ۡd6p+-ܠvDYN2,ueۙl֢:VdFq;!|VZi٫O?=KPDW>d舜PgPoc.E A෡)km(ځHʰzG1(Z"!c(e(>zO_Al7=o=ofk*~cXFl:7Zq0JXľF3ixqAh˝wG}TyQ~0PK̶ĝyX?زU ~8ݛ}}FC3}H5MA@6[d7r!"cYRt]"3 `bBP܋ֵl֙mZn]CxJJIX#|x(nٶu Z+ ;]1s%iuBZ(N{bEig۷Zň1@p$C25h )ϙ+dt63+ނNhQ9z\dRz0т,hZ!MFvkFÕGcmY@VVV wܙز9^EF'hHBZ#f%Ҍm=!Vh݌$qG4Y7eQOCClB$)hvnG"}l kPQ.rZED=rP$M:oiضrJ-[ƪU(**" Evܹ3}I%5܋Zg; @ PJ2YRܚ1h dgg7_oClK"n9#vM0(H$Hn@X!>} ZTNsHƸE<܋4"?s|<i p"6m:QX6>=.\fr1N8Fyb۩HO䝱8:ҝX}k ' I-sl'JygнJΟ?ɓ_wd¥lDL{m!I;s896u٬H[%+++X(~G|ARSS|V9mS(by 1]g8 I#wb)|V!&>9nAuЊmD[pfk Er$a\{~x1bs=#یр'9`K /?ȗϐu-A^oK~~; 8I~i %%~"[.`4Rs (-{QGM~~wbƍ$5w*{uY&Lo嫯tXsĉٴiK._~<= خWT 9UYE%8g!}؆@|"!🍦C! ,#mvb9(~ }1or{6[`6"+ Ѻu7~:k2[ϴg}aܸq< 05-w/W i)Hd5ΰtf8W]II )))2WVVVY+6~222*u溦S&X|9z FҖ3\t:t,NR}8Ge݋@ć ́/AE$+~w#Fw b@AB߀pёH] YhPI[FrEsPh`Jy쿘S$iYa1O'@0QsBp3/CL(|5E m'4(ڔ48|bZo}55zY^YycuB;uTvi'{ߗ2zhZnM^^={k׮q)pD;tR; 3+NWu"HB"))) O-t A} hz+LD݈=@W$U#]ĄiFi,= GslZr3bsfs.- P9py/lιC=?|/>qlպ s\TqPs]3G*rdG`nbM>0Eܔ"V~E` JG=WvhVi\ KQL@Կ‰ıӯ ~ >t?C{&p=O,[6 GCY2mEEE˴ŲZreZ@ @`zz:`+$ ! HKKkb*:E(bpbr;fzzg"GzC)mzb?8٦ *FZm ?j?nK7o}W@AE,G`CM;"f?4p[{cĔC(8dk`֧>PH^;p68 9#ɡ OUS W4sHK#Xclrz1Uf\X**3`̙ i)RTTt@ Р-x: Q(cDWP(ć{=po >shO#¼?#HHAh N ̫?˴dHEExqb+4>FRMT?fb gc1KtQxT$M9V! G qff>yE܁f}QrYfHB|m~ݏ9 @-[ՠ̠k k.Kz:suPVtCGԶ 222HOOgȐ!t ĬGh?Bpː?݁!bGX(w9&)G+T&#]csN Vӯ^uCT8u3v5MB:f;T!Ґt bi b6خ Nnw~}[n@y~*B!QXDۨ8GO0Dl{4h`g| 7^}&`ɺU htm<Kzbе(~V2 6nxh*MFSm.A.GlYĎ7G}ZF <6"|? G@ =Gl?xt6rZ.]ZmqR{m@fРN0G|1LU(*d +3O3PHnC<4}:_nvжӳyx;<)|̀֘h %/87ؒWMɠKz ύ-q>Q2r LDY99@>G~ bkbdGi!m݌p"Y\)(o wC:OH㞈Jr^\73pP אVY/s>H0Eek: X}!tD i(k2 鸋q\f\sӑ141H(@hpeJXhp|2/4dr[r[lc%%|>_̾3j3o,tSX,tp~sI.d^j!~2@G wEHvGbĬG%(tn.܂ڙOFT4BnE2ռ@H<HG Ĉ[A {oN b`"6rD]Ee[显Z5E`@@?ܴd!B~twocqdJ3Pk`2wUg?bkpYЯh ;Dj:e%fT )Fhmxc:m.TW/B@y7rbuFt;[Z4e~r9S[!,Fצ0fB@x٧/4|H_~ ^F !$11Hh1c`P PXhW.}a>ۈHx9\st4? #-3דSY0(nY$v鋓v{ >C)H~h8i(w4f1/hvaih1 Nb #TlAM\jbɾ`l2Ǡq25 ݎDX:( h=Jjr ދJvELr[A>!@3tPy}РǮbq>lHY۶Ub#A@68k@ՕT2L!w!$gzihb}le\tאNoy PCu3]S4 GE%=H_OEL~>h96mƴmѰmhKV@Oz _,e@F+IZ[nv;jxw"~hF-bY#?I86S@!`d"%Hĩ9+H} RHC]gŒ32g !jV92Pj$6.E8 4}4œ@zP6o< ϯYÙTM]׎~d!A+X>hp51} % E:v~30`.1YNOO'55MGWki0Ь*E5gggU jerrr:!Ě.G,mş+Ѓ?Yc ^]"@ 2(cwN*fv9rR Xށ^Fjӧ#0N5E`ݼan l1Pj[p4-U:(@w&Ni-dx/'(¢'7hAIJDz5肢s^7I5mAQ4I,))?LܿQ>@;Et]tS[RRRf&d`8PcݩZ :z(b磩wgĞDH `[$XNDxQ@, ћ:nF} 5­ʍ7Knmwub4ˆMg Xi.?RL?@hI3m->fvAzvғ޻ <~զݿhBl #7@#|qnBED"?2tjz᭹@VLFk]sBeee58 3HD٢OXmʴiӆw?9 c9B(IŲg"`m[@gҎ:{rfCE{QrDE vJYw?X+@7HvE e%}9b9_ eQN2AZigg4C ѸR4t'L?T =I9Ϙ>rEt/CN~_3S4P|9ϻqPH;ѐ.^жIcl:.Pn6;{Ջ3^eȐEisye2 )m׿yuGaqmDF8xxQϓ>s@p*z߀0ά^='@Ieo9&PFpB514'#1ft4+(Eسub ,: `_E({;1G#ґ/snjRRLVc4vorWiiiZZyyyѩZ@ǻbXj \]瞼Sq6b7 |%N KC[\_T':_A-H=ᛈaBJ%H#=8!#}bF̓W~]YbN 5SaB_|g͵#@gڼ\1u͵ICm i8E@z% 3P&㱈}ym1 N'u23F?k[dm%8kwBVenÕ5nжEvaaaB]3vX>.\8וA:]<6k.^ӏ^!V#GUj]V-dgg3o<{8b[>%tGLxW4I")UuyfώoE$Do ,O-@U~ִߦ 턘ye]94(dw<E\H*JCaw M}&]p HUHb1]am%<1*dm#59 ل"o#&,y,[ m 'Wy=,X<ƍG޽]?0rH.BЭ~8b}FkhĦH4mɪ[87o߾,X={d[N ))?Z=j>i_nKEnO OGzJT;'Vyr}\ c(,/(SXvMC jAXT,rT;%K4m E{L1x.gI#g5 #v[XfmM՟+D՘sbmĪAh kv j/R>cfϞK/km*Y|9Æ |g̟?<o]L6""@=H~?Dm6:ĦGoӹsg֮Oǎ;); $Hմb쉤!99F~Te}e22n6|ב0 ]hPXEtdZ MEk|!a6$©\ e܅3rhͶЌGsL 6#p?yl {h(FR_ ֡碁)ퟐ s8kte>iii~1][-w~^3￿[@܀!XMxi4qEYv1;BLX?#f;9B`/)Xg^hL)ldX43 EZ. {;zBΝ f1G_9֞(^[s(:l~P$N|4HB೦-$xg }6m h0{ ͊zއt OطX"rtc'|2Gf0uTvʈ#?~|8ݻw}zUW]ŢE۷/}SOq[`vvv s,{*$zDͮ7ȧ0`P>wEaG4ˎwD: mhC9H97#ToP]+VbW4]!#bp}8؃qcA9 NC1-ƚk8 [x4tDޮ}֚~ָgWL.{*sĨG~֖9-s?\M׏9dQɖ{je-[ ĻI  KOOOxW1W6(JCFn[敋Xpb0GVx6 go3C:Lމ~@,䭷AFl8@ C}Pd҂7"TLB3oA$E LGiMiٹg| , i=PT]eNߟ`w"MvBO8[e`23/Y7jDOWcZh{ IDATnKhUUŊ jC$ БHYjZ@aMhѾT^cՈ|zm"6m*Ƒ0ClS2GP4Y0vF潝?.8 FR{9^LvC4 ցH ~1-GrjYZ# )Zf^ 47#rݎ$HWoo;Ā #];9cssL$M βWL;'kBe\[¦Sߦkl--SSSkHhejFl쒨Vΰ}k0"4 wF`= 鏦ͰԼ(U֮ӷ:Olj McY6Nh40p?G1TM%OH(CC 2Q:=߁H:6Adn!vj6l#@y8+Byrb}: { 83&rVݩm-qdphr-]=Z'k6n\Vu,P2PVpe t\W#k67cW_d+\u(//F@RS# =?!@E=]7 hPkľlm=ȟĭ3qjSر bY*ނ G`2s.k{ .Fw#[ӑqJn^4ŷ16;1l/!zsL42}5_DlH!mqV KmSij94 Ϋu7[^dSĪsoy _kŦVҷo3VP 5UgSY27@F3ֺi38%4"-4OJap,+<iZBQ?MAe02ZT$=Yaՙv5y(g>ˆI@<!8 n@6m u!M%lƉՏv9),CZ,Q2JGF651\ t?>*UsMX? nLmVD"Zj,^`0H  ''cŌ?"nQv#bp3k;4%:4=" *C1hz=1]QlS8+X PRS~ :Ct9~x6/ٿ#`1t'p3\x$z15]9Gkې~|DZx%qOGqc?J0ʴhɦ:E\W-Eh);?>#GRkbu -=ܯ!Ezؚb}Iv'deeQ^^^tDޭa#Gʹi#rN{!2':ar!%4[!VT\BH]V @XHs}/)i}ejcDl:JJ�Xdv-oB@b[~ /4x *9i_~9 s}S6H*}w|֊mpB֡p$ m0mHA22*X:mncJ$ZM'D"<tMq0,D6Y;C(bʕL6 I61:N h韻xĠ!_ o@@D GQLv-mlܱT]c/GOE x6N"5G%vDe8c>BƢ/̾%'s"Ӯ.M9ko@4`.nA,'ĺCӯgۈfF~v܏ 69 {zcLcYЎų\&@ 躮RvՅ5e9wep.="v;NFҏ8@Nbo>鿘@2Cf"8's-dH H#OPHIދ(m2ߋx]b+BZmPqʡN3?f "f<I P_wBJ*ҖKрu.}qkpV7s'wA2+8~h@*" ҟwߵq[c dN$qԶJm|rjۿUB:4=P#)z7"`+lF`SSbeh*@*vByS.24wK3#K$M8Xk`>;9C":,̵y v|$~S?y$k6tg:x#Ç$B7 V#h:"6_QK bv }@%5J1-q[^|9_5sNUU8f̘1 xGc__feRBvvvNh*յ! QPЃ`r(z՘ǡ5P-C e/ Vx+aҼ֛Ḛ7b!03g{=Eʼn}fVEI"q(>zGwNE}kG?`[>uWzl?BΦ q=l+7$CJ~ьӞ}C?h@ hpIg1bD5}Uwk ns@'M̙3 Br) 8w޹YrW| 3gk;`Ȑ!x ~=ۜaͽ[JhJsGWTAm[m\FՐ݆"bߡ)ib:;!łihJ~3E9f{䔻QD^3Ps/ϜolLV 6z9,WYBiO"8: (or nqdބ |:  s[|  6{9JKG?r#v= u!gѯ5UrG2$c/fΜɦMcʔ)5޽{Wn_rW˗/\Yewdٲe1W_k1]֊hUMܖȺ={o-F@ueH*8' `үg m:Ewl4C{6sv<ỠxE(m(>w+g!}/|_%C-gk_# \M{vab,D3[e݊3XUPWb q \yosh$hB0}PS'#1 h==Yb.>m۶"FMa^]Mey[}_rW]v//^!CԿ1HխbWN]RRRZ!$ʊwI*nD" 8 0+rcH.7#;b]m8!6rHX[3v7"ӽpEUdM81!ST>0^,l>Nq cOLDu[L3 ,W-F\^G 'c@8Ĥlʹe9N9])9Hм2ūlc|^dߔ[k#Ozzz799+0[믿ΠA]ѣGӺukٳ']v# .QQQiXD(--% UD"BH=y0@ 0 %H#T6l/; injw= h=S \74=wRdpn@ ! k>JPtDsuCS8,M_nv'i#Έei̧AkvgF,16o}lxlE?;@g&M\kXgãIt"HY]ײuu u-XEPwE]u`+JNL}o&df uqLr33R+++lQ5aQ4:u*֭[,977VC|l_@T"yyyMZ rss)(؁/&_@H Ch1cж<0T2#]H-=CciX(-F -R3 ڝ#~]w ^=#lk#M:o5et+j9( Wx㯑-&v:&~rϳ)"w&7#Ѣ5\rϽ("55ѧOj?hG"#öU?~<ÇfCZ @,:l.PYY$.++#777 wadq0!!_ynG_<0^օHˬ«f B؂0~CLCxbD xm ZHvw,u72u腚@Nщx%4G;_[<L3k\`/V5AG?>½$ -&O#7}}[BJxYE ?I'0kQYYY-go c>Fͦ:/dҶFgo_h,1K,t}qOFU,wFL;s1r#{OĊK9]Àx-bK`폤V Afܶҍ+boSq Sl %ha8-$];ȋfi9,/w\vt w;f# ĺmȷ9B5]x*A A.^Fe ` &L`ذa@r0Q;l(dRǎ˨QI*"WѠhfnS*V̬e/;^ :*t2+n7*8d-nAyh+nLs!ε0@x@TwO-jzk"u36Dz=(m3f{.D(;37G=?HxI; 5pw\?s$Ah'>(V !ބq&=[;7Wj^٧5omeޣ9,Y=ztBjP_ZK%Vj(l9É233)+[ù^SOX>1PvZI 17D31K6>-ǫ~w>"Ē= 1w8墐X(#H>J]=O1ڸG߸k %LD;ʄ^sw7jwMNEܳEc hCKcK%dٝ,i&%%пϟOii){~ivW_'JAuu6+U$kA IJUTT #43-/٤X7= >r m}PG@1I/_ [0X#FrO"b)N3"\#y#AFXltB I\w.; 6Z*@ -hwPHFhXט49T|?v Cǎ8c3f :\5 gBj'bPf׶u?Yee%)))5Ɇ$>=0d۟hj!^W[: $ey #:kCd{7H~ _rD,wDq_Ng߄Hޝo$ ݱ'UZ}3ֶ6OBȏn|h!‹Eb=V;o+@:'@?HW!;^3Ns1_Z3m91b]ˤak)!1j2L߿͖t4,3rrr ? ֩vk\zeLM!` #/93bGx#"lv=ݱ] tuǷCga1U{-e#`XHb8-{@imoɘ[&rf!iŅW"p3:c[؍#Ge6G L)9 + kvuag7O2JK2}{L>ǓO>GXַdj[VŠ骒,B5]IVI"U'bVqm&(++c˖-O駋ЗǓ/r龙2]vE_1-hmHߡ_V*5BH!Muu6PD1b*КTÀoxi߭15'o B׬6/Ezs-ܜ9\/[:CNM@))?aÆmU5gL7qqMUOU1x,Q?:#77P(j L:"޻K.|{Ga̘)+ی!m:l#A@ςM""Lx-x%Q|0 *wrb2<0.w}%BxaoPu xGZwbFjQ:^e.hQ(q#F%TE`7Qn|%wcm^:!ki]i0eSsw;v;('^UI=I!{wsQ`?w?(}sxTd5l]͛K۶mi%Se.tz#73|. ^KQQ%%%LӯJhLbXN:"ECl.~;3eʔscΜ hs| hۊg -`l]ks(D'Wfk51(oTwl<4|bҰBdL7nA3ƒs{+)1w"bQAL瞡3 ln_B7mPzl=͆ у<7ޘNkZ ~=_?{̙ŕ|r8q"ӦM3Ϭ7bKD{j0:9DbobS7233:t(CM6qA`ɒ h@`b㵸my(Cq/#>E$<샀$nD,cQfd B‹PIAmb7Ls4wD(EiܹQGR19Ѝh1]*^X%ljW! ved4'c /!C/Vm~U]^^N0$77Y c6m4':P(D  ###Xի%% g0Eǡ/6w$S]ĴS{Y1{9*t>i1+Pu"0*uܽD@gVo5MqwD D _1 :ALs ҙ#0܄$+oYZ!!c!>I El>,~z6Z$Nv3s➷w7si|݂eIѷo_3#Mɖǒ2e )(nX*f&gCmhP(D6m?)%Zlb9Pg9Fƍ6^d7{͎3 ͷ}ۢ"J 2NGQv+l8 Oz"ދI/DHifSe7~~7 &xId,&:n%UA  DօwHoAYvG@V/b-ch-6<-lDjݻIK Z|dXIA/)]!~1ߺC=RTAG(k)KFn rBtlos15{!'rX[ єq\t(nh 6JIGv+NGjG#/afiwD wo?8ж=D&5~Zcg5B,-]=W/#=A`hrl^ |_$yq"ZHr4"+2FSHoakZ8Bџ(ܮ=S5z_&Ƴ_Ex0'/rq5Xh[mu\f A(hɎ&w~"xcY@.P2U~1+ї U^VkҐ%\֨9W"vbVc$چ/vcy'"0-+Z!!wx"y>[E ۅHg.B:i(eoQJЍ"EnE x҇;S7.:п1+@ |̡r;tұG-ZlB箽#OQ$iQ l2LKZhsdMX,_=MDXjzS;xA,\Bi@#Y!JT?nVvaZbn@v6bх&:7 0-x/l.r\C*(#pnԍ+q}k:^Y| ;1ZCh9ڬƕ(ʒYHBH?؅]ݹ%HzR&x~KCh@={x*Ync>BF&?D mn@Mz[@o iߚʠ*عy]7|,d/42ۣhwPX[Ϩ`_F.ίF,n$!{XH,@AsĄtRSЮ`Ԑ/R\ƾh~5(xiih1) Ld]ݼC@HxkfPH#~k'xyhyhm>hcI,FG \@ :v:g WWW8着jhs?XKwUIIIN ޻̄ *%rߵk2u?>I1Qk}xYvwPqE6j3$,ӮVs/f-G UOE[QH^G 6>ίƫl"wCα!k_ ZQTG&1=wҩӑ̳v " 9;/+0`"_BZy~kSdqeWQc5[twV-mH`0HvvvR]@w6m}#}G{3J^x ig!6k@dgվ>F#P;Bh2 上\6b9"j1A6Bu1(6BCTjж? t6r}vW m-wg"En>6{~{3Fv5&,I;ylpwucArw.=?DNλ'1Ob, I#2hcۺ:[J"[#H$Ҥ7.DB*++wC:u7^(,5ތȋQd Zjo\@% Hе;N~a4M(m!BбipM]4t~5h5 tB HTL7ýH/ iS.?sQU(-wܜ@iߪҸME |\tA ȑE( 8x|'y%ǒFRUUUs\% J;};#iV о/TΟ7" Ffo|ZcBpO^-(|n"P,sRDXas6fu$>k^Rf$M܆gw{E\Z s7ļW*7rcZ3"f} ;"Y*-jTܜ32$A`[ouGӕr&%5҈3?Z~+//*KStE:UoH`%xgv:mΈyޏQBZȹԍc/9d$kET#0Al'W֝׶ :nuF3, b]YYTca3"${!4b[Tc;Jwh' [.tu9341ݸnF ν~bӦG`BBlHZ[8b}(-Ks'"L |>:lk4fpkw9aƍL4bš'oƲ,E<'''fb,ЩS_S([n N {0㩿N]H~Vg#کD5$ hACښ/r4-t945;QF(Þ)$ }FNݵuk[ޞn.b-un\!NCe-6䷘c-eh8b֐@oǶgH$¢E>}:W/`椓N JOO'Txis1 tC)ߔEm5}CVK8C1} nCڪ9ۄv%bz=PpOpGqi7 z#֢!I#vRfhK^BJP 3sJBeŐEKXH،}]oE@+3'T-&ĴEHrdzG7K#gE9܀_«ý;SW]u #G`Ʋ8 (++cȐ!|TUUlٲ]X?.:Ѿs7t~2 آМVQQA^;-9Jj#8:"pU|^jr FAQKquBZqhK{ED[1"t#]F4ḃK_p)H.Xv臤9஽+v{!W.BjX+zTq3hUhA0'B$e?!Bl؀v߸ _wӣHr{Js?ȝw1;~\~v[ta͜f^J(k/QzڴiqmٶJeEgcsrrZcuu5@P(TSykܳ xb*㫈teO=;r~{޽of^B̊T-x?{:\bG#]Ruq{z[AA&Yn `96GYTobIvBqH29Lcwi$CXrwEha% :r60fYYYdggUS^ *++kBM[C"GVRRBv?VAg&g ͢#C-~_|SXXW[gEERǹx P0gv/c,{a58g*HXe/$XJH~.,UHy-qסQZ?+v{?,/q,[;f d-£-x5]BB,ydq}$ZFa J\v؃d322j$@K 5M)hBGSḓi-E;%%65,VdHKF?oJJ }X^&_ ڂ?1PZ.ހX$;;Hn@Q }ގb;5p&t ^QBX:wBң3suF;{,HlFvE]o95dB=ňW#F=-n $Xַ3CR$iC whlذΝB]y IDAT ڃ %[fkXh0ԗVب]b]'V[oa61 JGوY/C@w1Oγ"=t= j#H]XRj$\#?ឭ"A`^ =H]c;³_!C/>b)hNGN[jT?"dDZH8$\Ge"Z3kq/r7ZCw!Ю]wbZ=XY{,{k0d+ K<꜄$@ @fff|( hQOgn:u-\tCP@y=bFݡ险8NCg޷CM#",4lr2FhKĉ v|w~w߳H8 {Ov37 ׮jee%u+ΣIߊ Yrn|׸9"p:S|j^Eڼ1Bu4Q砜g˖u1kek몪k6=zt1h|ZUŒZ fB`}@Nܿ^Zr*b9yC|w@XҦ0R[zTΘλv@sMg#7eAnWPw]э=S(+DrG=GZ(  =2 "TҔGzr>J"Fl&PߍB { Pn*v:Qom lטVаu@mT%ixNFbàg#5Bbtk  BV?+cE!@g Z?j;$ qcLӵG9 wG 1EF׮C2&z(df =cUNgn\͋%gX$3QWV bL1B丝lĢDTc=RW=߄bB w9HSoOyy={ȺukIՄgnݧM-Z6k5jw-iPP(TڐKh >كHCČc f(K`g"} !PA<^}y("O!| շ،$Eu;b6sQLwP7O 8c8&…ߑэӪmt|8dkkǢ Q#B Pdyt=^$77 >%=@ڒ_:PRRL߾Yz` g"b 5tSt3n'3Q"6יYV#iFm"J$qlBL^=tX!@@,vF12^JC@=1ՠ^\ƫO -F#Ie0J栤Vc͖mjvчuZvP&\GrĭnW{"KhWo@# F2*]bǢxϣAG$w܈=|#˾enW~F܏o  &rC,`Se3Yv2ZXwXF%fH2BP  )++#++7ᩮfe˻(?tӣжy(zEaZO"7j~D!o %lގ'pᎹ]3_@꣬w?DBTdz>#Pjdt˪yO0dff֩s5 t@;!c4͎g<Z-+^U{ĀwB̺Fs*zoFv.SNA$9|{SX4cQ@WNJOO2]?y%^k*ڂQC,rG+_kgh&*++#;;;nlYH$B~~~䀆D())+X;K6 phWK3 a󟑌  {;/Fzb${QY}}2p#b=еG1Y2/@MHV}pX֡{C;erZJ~i V.vs~w4<Zr{~Hk{?Z.G m՟e̞+ka 322j~к %dffMZZ5劊 ***BꎘE"V)9UUUQVV?٥kiENNNbNP6ȹ4X ŷn Cyx1~H{"gT/3vܟËto]X?\9v^`ϠnT[azK5fYYYdddk`f^N8)xiiYj?8Q"CHvÍhE| ^}f+:Ν;>tƝΤIo/RUUUÚ1egdd4ʲ[˶|[Ȓ%KXjmڴ^{-]tÆ iaK.SN9–x֙b@ _#:''qXYYYCl̬P?2e<Ì&bP ݇3e?~!l["m$_d!&1wERHJ6;x{qoPH.Ƣœ! =9~Ķ{t7#c޼/eH[o.]zww@>|E;Oh-1xm6"^|Sk?!@~wOǢ R<Ea9o߾ӭ,:bĀ9ޢa~$ؘ>#Oŋe]k8Sԩn9˗s]w1aMF(vۍ#8ٞɬU2Ƭ! (--%==d\^^^lϚC9 y#!0 .DLo)b`#@4pݱwu} <\{]Ǭar"8QcrٽR^~\עٗmJƴ1}QUhb(ǻ{'.6 3Hws }ukW"#hz;"~WGݣFډhg>ekT :.+zwߝj-[QGUԩSkuSYrek]s9^xzn VίZDjjj5MJ6^MY5G͗_.B(2 ,:Zk|ߺv 7 9-:%T}/CI/ix5A/'t~tqBGy!v ^+(䶠yyМeqfVonxvW#@ϩ}jw[4\ 3 -~vbB21br!b3dȾZ0`(dXiX64-b$tO?H$aW\fT&M ~gٴi_P]WϠbG<5#wGX?k=}]u~A@MA{rBxKp#f~9@ Yx @B7V/|qb#`nBLK+(uAnrgs9AQ#sHR4H%]{?Q.G (o{`w( r"J:EYw?dl²Mʪ -9m˖-quݻ7۷gr)|75bF_΋/ȑG"cU2hӐ(//@$<ɘEg&gLᬯJٻO3XT\'I[Sނt e9uz}*mFvxA U{]'1Z/w6=-"тQ5M: m}E@e6PHjj9%%?ǚlA,]jq9߹q㞹-^ѣߠd 3^-G +$K:Cz .Bu;Q7W(1k(+7^hbu5껉W,;Q=c ;J)LMMk"5Ag苿c}ϙ3grI $y&VNk,R%0EN~u?IbauEE 4/kxI%l}Q|Qtd^xc֯Aca1sb>ho@z/o@÷!@bFĢd*r\ވ~zo7#%\! jKzoy]-o'㏧[n:Ζ_@B!IKK#///1\?}~t9c}"H8莔JKK8p?JJ(Q}V[&E_X\F" ރӻ H{[˪F[GQ9"g~xzv鯻" %< ٸq}B.]"bLnhA;]9kg Ek#9FQw] }?P<'fgUw/v`_ /=j}@4/~ (n.ϾɁSG?~<^zi5Ww4ūA[\VVVMչxXsC毳۾}{/yqױre5pwIBR]+ Vi9ҡ֪ qvk#x<tB J/!]m6K~߾}9CywѮ` Z2d#fe@;P-=jycގ\|jgKFH25a ǡ/hA{zaР(+K^$%%*>+F2f9YvC˓/J'ath'`S3 5N)XYYIUUUMh*_ǚ5=իHIi\$K,&,EJQ';CNsh@|ȦB~gK~˸Pt] "GZBDWֿr<@/!=ئOz_ ,F&o#?%yH3$L~RowU AٌwC LlϥȐeg٤H<o1ʪIHJKK WrcLnrwX '9/¥==xL ք@ҵkWvq:? hKmP@nH;}kTPo닑fz;rr^@Q\] _׏Ÿ((胸$nBlf$Irhp b"͸` ۡEqo4>7>u{9&/p"<671eʕ{-q2!|?l:bl+MO.A4sfʕtD"1MZ ⿿l\i0iVСf5ZYUUUKk!]1H;u ^xx9BY ٢}kAw gxc[m"f0b***jj"̚x 1NC7,Αy"h!s#Zu*ԗ G)& /_!  ̛7篯_S>9 ڮ3G"ϟOee%W\qE'l#*%Fm UGt?Ad*vY`sYZZZ[y/7Hz0}9حqzĝ7$#Y%z>[" |9uknd!x0ZDCNAXĈ=_xvg{'~rGP$1܇o"7ZLp㟂*t}Q(Tctǣ(}Շϕ-H~)6jƊ,5Egv k|6BHX ޣK.h5Z1@orp\}fAtbuuuRn/ʼn'[o!C,ҧD]]w\\͡v$oC }9y+DI!gpA @:w9X -~-\2`JKK&ѩS^|XGĮOC1ͫ:Ưj=Y vBN;ynnwDAygD{c_/hk֬>Cavo0; gM PRRRS,Vֆ̪-QJbE"ڴ遶E(f bW9#W>bw uPB.ھq-Fai@oWtdK8߁q+=:Gcܭ Wh GcwG>np׹9.-`%%+k>okoM3]:|72w\)**svoI@ǰp8LII yyy5i?t~Dž6ֺ' k2~ ӭ z!М}B sˡndIwA:*k埓KVs91~xY.C E*dJ&~XZt\otVXUt$kF 8#gWbZ=hc;gru2& }c4c@$`-W\qcȩk_ 4uqdܹj*+YgmakmY2ms67$VQx+5E"bs./*19d_إŝJ9J6邀#Wiy(puHc_#KG2%X34Z ' [@iUVVF}bw7mbBag}z.ӎQ wHy8p Cuߊ~Z=\MT 9C1V\}V:g3cиs2VO8 1GBЩ_ALx/Ѷ?˒F,x^_zy gHǽNWvF)!pG4!P_\f͚Ɂ /E"tZP#s APr.bmv?%EHƍl?k]w#Fޅ͛7J/Ѥ]`S>D*UWWh"VZj:4fI\:X^C5irssͭa uhNAss: gR;y5;{!Z_O݈{}oF@$+[Bh[n5@삜e UUUQQQT233s=>iJю[Qr J.Asy=ʼ<-dnhp!w.C1h1eÉq^tj޲qٵ}r&jēdP(Ĝ9swqpV ЍYcX\CFg?:w9RíFLe( IDATcg]oPI8A[h[{H7킘gzMEuD[+u-:|vG$h96_D`'p+b񺒃BA&rmBh">fEEּ~v.K\r9Y!UHTg;F͛7of̙~ ۯBb>`c0>kַ8X6s׻S^&6K/ĚS?Q[؀E;bm=ig}wq-z\$\aT\jƉnGa]pwA@͒;!E 1a nv.L3:blRёd.N,jܚmݸY Yd ~)s o}'Bkt2EU{wC?z 2uZIKmF&8" "`q2j59[f!yJ/'к!t Z4C`#ECTx]wZHh>ƣ99-~Eg҈OFslNh3ōbʃWһͲODw8' gsG"ӓZ <[UIj1hss~U̚ݘEx[\ucH$1r[ C&cA:k?겯 bi>G 羨|6Y܈@ 䈌 m T:Ы;gЭLU.2:u\SQQ*'?bſE`z+CU|-pu( ;PyD4ːf@Ț5k/##F{kLaVZZʜ9s}ӧOcwymۖ:pwj*nz&Lh6%\YYY\cGT%jMq@%k:CzzzNXF(@C`1U{ĸ@1fP޳ٻv#6$R/G;1tFcg#9b"z t)o1fK폓tXmZ҆ =+ Q P9;" ^^̏GQw ?Q,vh*thP(TSľ~Y|Јʕ+5k~xB sq3qD6oO?@=8q">(֭iXxp8zv2@;Q/utI_*JB;U7~'5WXNEGPDw}*3`܇kP6s:ߵE2"=EZ@J:6۳ (++# 6mv`1p#qE/Fh# rMA!v7 Q4;6 e.4PwZe~\d} /"/< :uJ}\j=zȁݫWZ?N9ڵkpV mpB [Nз[Q"֘#2^Bϻ!ﶱ ;TBq!=x,*Dն/ "Cj%b~ok*!2VsWssF"rrr%---&M1cUh>Ds"Ҝ>ĨC:(|j佑Č#'a,wZ@s;Hjz sϽ,BKcǎ 4O>ŋsw'<={b VXQC'''K"j3 c& $_0X:I&TvSG}4￟1Z("fx QB㋶(4g=ҧ^_@XRX1"Y_VgchYd,Xs'6DSO=o`s hS;+cgٜ,ښ+| ==i?HqYXBÙKGxtxhj:/Fs.fcǎ5S TӋգ/w'|GG4@("#P$͵(Jf21~_l}As9^APܿK2el1xp"MY"d, |'p1$=_jWYYYu #5Mp ocg֩SGv|5lx)u3 ArD}r om'sn'$Z)A70\5r;Tʭ#q̞=T*ɹs|Աtt fIX*A%UÜ"ZĪ™(Dz "|o)H'yw|Aƍ|7<$%r="zbإs0'|IfѢE~,dW`VV#G0~ᛄplkC6pgy.s!u_N"f:rQXG&xbwu][FaB: E36!R6RRxWvu >7lGnܸOCNl#KzDTC~#=eF-g **+K;fO{D:$<-f8q[N>,7swlX"..Iz؂ؠZWo" ɫݮ3D4D!CaHD@KKcwu܌.))anC^]Й%M!f)zDJB(B@뛬[ Ɲ 6l_!ǚ5kXr%$uրfP`m2Ci, D U~9 ؓ'OuL~1}DCx]:bcw~켳6G%^$!7S'nOOy _|?36m ]Hݵ".|."g *U}vt`7Fn޼ɒ%K]F* N\Ysgw;lyrEfX؜ <+#gL@̠7xfD3_u߶!tmCC9=!BKu=IΝ;γ'-/*vձ_a2UxV3K'II \3} 0r+7Dtimm4 :4\r@ dMíqWu/ '1DnYzr G䟯"6@7Bl=i;ܯ!w!t#j!|Pɧoϟj38Bnŕ$Д穭%''GIiȠδc0wNKK{5kV7}| ai2D+%l7ܼk?z?ӧW3VWPW'ttVr1/]]]~Y2c ֞@PuF#IUUUTUUt޽t:+e:~eP: Yzu۱L>ݾX,s1bbbj$%%pvkv.]ecgq_ E$&E8p!rCq8111L2)SDxJEEǏ'::FCbb"t:D9J| 4FCY1NH]B̜ZsPBlwenD.g),{ Ce~Ii*s"Iɵé5f¤|2Vr֮]˪UO8dWٳp* Gl68^ih45L\ TqfQ^~ (Wۣݷo#TyD=;vκuBߕ@b%yo3T0r555;wGy$;W`vv66m,]^z+Ql6L&Νf'--ӧO3k,|*VII s>,Qv4(!$w r-M@̺j-_~9!5_pJβ`wa0 hѢ~ U$IСC|,Yx$!!!$<** ՊJ \ks[xN :1gڕȆ\K\mP 'N0nܸF A۷/h$zF#fVˈ#5*dvqL0OpWkns-,+11hjG]N^^^ߓ\ t+Q*)zJKKYxqW }~@$1 <;RսAnG_gPtgUa rq8Z*Д$I={ׯ hnn޽bӦMtvvH~~>a$I455a0hiiA2l0z=^JBU3Йb0p3' tz/wmw7ɓ'IIIGkU6Ll۶z>.;_g,Y$ tMss3&Z-: RSS]Pwf_#Agt:"77 U9u#1U׸sl6~je׮]}0 //u1qD֬Yû;(:x"bulлi9s'njѣG{=^__ /@yy9ׯﷱzCBBͳ߾}6jdddV`ƌ/ᣢzIܙg\l_]›.Lܐܕ]$QYYɥKXb++w+>}Y^}U+jQ;SOe֯_رcDpsPdjL;:gOctUz(ىhހ4%%^*3tG3111a j***Xt)jk׮a4;WO~~_hk\\\̶mx;v' #T"_WhZnܸΝ;IbR]]Mll|.?}hRWl6JJJZ̟?_qPުDoرc (]cZ9<ĠhHNNFףj]`ァX }u/<@4֭8qRa 1rK(**p*h&MĤIP***(**"**^ɓ' ,@)f$IvcTnn҈U".\<-[Z旿%?=\dg%::Ξ=jW!+=5Ew'pN+ 03zh&O%@+qlZF#P92(U7w \C@lJ;k׮QRR… IHHp%@@'/s!9Y֓f/ILL9GM:B]yŞ>$I?:.]w:`L&nݺoG}DAAA/QULRf7 Hč7(--̙3hZ{b6ioݎnj%rjm TIDAT[.9r$˖-{r,fFU DT*IIIv$Iܼy`Æ ###|2IIIjlzbh=ERXV=JZZuuu,X{0 %@"JbԨQ٫^$PWWdž cԩЀFA&*_hĄ'UXVN:Ettt*q  (Z_X,1bĈ;koo`0PWWFA+S& IG U+ZZZ(..fdeey F ʸ|2FCZZ~ i‚QҥK#}cS!4(zʎAWWgϞd2Vj$''{U*x[uvv*lb6Yp (zw^t:?OVVwrz;::`jiF{{;'N{e~B䠨8xbbb2e SLLǏZ4i&?E2/^ uBxB?TL8+V0qDv܉$IܺuG_S^^۷Ö111l6f3f6{[, F***XrJcʎB&OLRR>͆dܹsHF!!!^O|||sD}-=Aqq1iiiL6-DJ 0d$^Y.Offf|o;\~SN1o< DvV*"f 6PXXŋ|8. @+s z+WPSSCee%| ӧOg{;H$RHIIDnjjt 6 ^lƍL6oCKss3'O'`˜1cHHH`ƍv۶h7Xp!˖-}D6(Z!ȊٳgR T* ͛7پ};SRRRBFF>&.^Hee%999w! q۶mn;J E$T*"lڴtR^z%=܀ٳgÆ c͚5ܾ}@cc#ZVkخV3g`Z? TBH[[\zP8qI&1vpUahĝZ7|(4 ;vH{c6)++&{1t:]0@QBD⮮#N!bQ ^石yfL&k֬ ]WjG9(*Yh_5k׮aK-o>Ξ=kO{ &경i&:;;ill$??0T!(3h%>>c:t7ϑ#G8|0ǎwMMM<ܺu+ &]srr(((_9s&%%%aB0Qf ^k.fΜY~=}t|. +vAI!v;wYhBd̠ʕ++l6y뭷B>O?47oF$]֭[C>У̠9ߪU=BQ6 /9ߗ_~իWBHPBk0o< jk %š?%%%`X0ܹ3l(JCAAAah(JVPPPd^~ ;ёIENDB`mpmath-1.1.0/doc/source/plots/spherharm42.py000066400000000000000000000005211340375245600207250ustar00rootroot00000000000000# Real part of spherical harmonic Y_(4,2)(theta,phi) def Y(l,m): def g(theta,phi): R = abs(fp.re(fp.spherharm(l,m,theta,phi))) x = R*fp.cos(phi)*fp.sin(theta) y = R*fp.sin(phi)*fp.sin(theta) z = R*fp.cos(theta) return [x,y,z] return g fp.splot(Y(4,2), [0,fp.pi], [0,2*fp.pi], points=300) mpmath-1.1.0/doc/source/plots/spherharm43.png000066400000000000000000001360151340375245600210720ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxwEƿq6ɂ z3"p(33PT,N98E*&dX6NTm30 ~>鮮z}-_$gyg)eH$谽+gyYMK3<,ygygyYОyg)j@{gygygyYОyg)j@{gygygyYОyg)j@{gygygyYZg;E"deeNZZ>o{W3ϚyY-" (//UeddAzzڞyyY,  D"@M@v[8HOOp{c@{ s3fXh 0@`c=ij<,!:s8hxs(//QeV"@۳<,.D"AB8`, J),H{g;yYf~TUU]QDRYY3ڞ5gڳHU^;cyffk{֬h϶"3 ~*++mLouNf@`H$BEEP^2FV@<bM f[RRoҜ|p[{䌌t(Ϛy-ZmuoN_hہigsFBݺI^_jb9}>_Ғ,v@d3rkK$϶tt [] Jg䶨x3y#$MV~zz:іh(ΰJSLz{@sOא[@Gɨv=%%%)3o2#p<h7uFZ,ؾ Z 1e- R^^Nfff:oC376;+ GbꬍM\>n]ruh&>:N/2.'~VW>/;Rt57xTc^`у kȆ ɚեz,Ȍ>p8LYYY+k_cnJmKg Sm^2l[K noض+#pI1@bDf4tJoTUU0.tIE***X`˗/';;}^{}~mαP(T9f&K538#Uzk@ǰffth\;k((A*++ҙ 6nȱǎd@i@& cƜν%adYոS1'Fsx}߆b Rd.6llth P#K"֐NrSX0OX -=n?k`=O{l:ЏwWmANݳefZ,ж%> ,..e˖Ighjj6MaͲ+ϗxU=fff6ism9ݿ۸ᄅ l h~ | ¼y ((ʕ_ӪUթ>j\ٕ,..S(++cкuk.VZwA8&==Gy$iShE"Y^T3}mi^z>;O"I@`(p5b ?|#PB.0w[ iԉZ}GA{G?=8#}>ټy3{weN>N:#G2n8V\I.]mxG8)++KڂcEf$mu9xfGgH | |\t::nN>s>ᇯ1`ש!4u[nTݜߍDl׮1|=~;3:Tj* @׮]駟ҥ f⡇e˖I]mSt]ɔ-\wlϤQS@{ƲDt1Fޭf ϯvM2:H3,N(E+11ըH=Δ9R{өSofΜ,"3g#|aa89) _\Z9p欋yiNa{<_~)bC'!0z9R>7ݫ>^CR9Pމ/J_teĈ{ ֟7|5-Xm>AWBh>}`0N)``;NC[sf ]e֖]ז(,pҥ v,7V|3k@cd{ أHwZĺݖjE.ࢋFr}w7>17ӶV_fJJJhѢgЉX %%%dffnll$F&|ɲI`7S9Ho;ԭH z6C so4<4Y>pږY[RX؁ghƐi84BZ4ѳ> ihQ K eQUvS_fƍqZ2,ӶmU툴,ew'JJ%KyNz())!-- Z諯@:=1H@t9o>/wx2Jfxs#n$Fˣ${WwMvbڵ Ec-0m+T#fh7"G(/Hi$\ϙt1e"jH&je:SL]h;u)(ȨQfLעyo-Р<͸bE-3duh5@;?޶-f\?e˖ۏR\Hbd")@ ,Tug (g%UHKh>E/PS81 N<4ȡ}x'Kp[E4m@d f (~4 1g<+ hF ϯ#K\~5^i, / 7gUcP}v24p[_Ǣ܀"c~Bo׸`jZZ}Fx3͛7M6mmwpBxzC=Xp^YBVkՇ$,E`Bz@cGs1ȉB:H g!pDB1mbҕ =~pB=I:~sT[({$"g9~#vr"Yʑ& ]+_k֬YScڬt"cm5kW'C\s5kJmޛ'x#FPRRR羆Zt"f JZ_ɐ8)hZfmD!1ߙNA5HG[1G‚oQt:`<>_b:ti=z=@=$NX%ÈՇH@ Vo#g>N @ P"F|$r0B@u(kQ2fqwZA BYY{8k`vNY}pR~2z3=6okL#>wߝիWo%wԵ;{TpHvmh2dtm:s<:ŕHưL)CM S]:PL5݇wE{:bsih|>~;fϞ]#)XR6X~ktl"z|??w[$F~BI Ǧuz"9a h6R19n68i+3> +H.=\w?svj#> 25 be$W; ;vXƚ j_|ٳgWɴxE#1;s7Yp?أ?"U:(|̂Ep'z {z UbyFL׹ gcPg+8ڵomb`g,WfpBC8:lץlrq,^0Eq_L94yѢEt7GL `1 Gz"H9͎rͽq.u3(8u[; z;sX2d ٝvi_b]͘1ٳgsUWqF.bO̚an[c4Auf_C,0|[Is6#An: ރ>sԡ;uއe#@j7 )e85:'Ռ2#Y0Λ sn-XQ#>S/b6Ư>ljrqww k /CR]:bӈaoewK?|~ h+T/hڊ5~6vHyˢW$%HXItA􏈭Mtb^v#4׹ BI:#H8-oO"z1XyGзP^pd%3V{hAT|;o{M!hfq)3wO>D>qh"ZjDzev/.& IDATh;WH8;Ei)G$WH: K~:l3uxRN7?Dc~3~} hw[ZVVV-ye꼼F(Ua b"@Gs Htk# -= 寰y:'=G?9H@̻ bw#}*I۶]BZ` # _TYdR36ZzOA0ݐcf҂et]@C2x/9vB7sKA_s"BZ܅u+Yw%z09-ѳ{gh͠ҿzZsTg4$w7>BṮvUi31"AwE`'ކ CFnbߙcGpkcm)gO=92T `9n$>L73[p}AN>>H6hM}n0u '(zaiV9ʔiV{yf ڲxݪ |P{v6@rԷ.5k^EU?y s9G6m>A o3Sܕ2 kmǻkuc^X9%Xs '߉tN#=HC(b)O!v=Bh1]ĮEy p vAQ#w/&4t^?7nc<^Shkv-64ǵ46g4;#}y9]sFs}'NK=+.B{r-@`8g(B|40wlj:4睃mgAIaгG[1bߟ'ʜOs?DJAwD2{GuvUv4G^^^Q\lbu沲y3i:' !6=$+oiR& v8oD{ +ض]q-I {!gbT4mm7$!pngd42tĆ,F~șj5h-x[^ ջ^~]vAtzh u|>k0; cxSM9=p8C hfY#L]i4 ~_3BAF75NV )А^$:s]r7n\:d+ĀA~nVuBQȱhH~]k|bPxk@\ Ӟ@d2SHs뭓0 L9"8ȝn~KGO,k?4w/h6APZ1A3 c#&=J Zzub,:T7|=ǓP;$1o1Ҋ7 "-:”2]L[h<+4AQhp=$H4> @.HJMg=FXD"M3u@ @YY?Ek\B: N9?GklP@x[T!#cڕ/".@ pZc#흎y>`F ~!p*Kc)d)# : 1fVז gBM\ix9'|_UM_~%uɼ'L[YW)o6[liscLA8=+Yi9on#Z #I/$S]Xkh>ՙCPY$p8L~~>/5 y;u+x;g!f80.CS=i2OAHx u{q#p6b#6owo@y? F!菗<@ZĆ il%h@( TKР[#69 `PF9i8@̨.^'NСGJTQH }lW2 &ЌfG؈(< gFs91| bߡ4>Eaa6G}t=+>KMP99Rњ@'b2h9##Q:s:z`sP ћR,Ķ^G,rʻ(9ҐH6:Fɿ MWk܃ALA+bݙxDנ2h0@~TF:qI}7:9ce[p"[Y0 tX]}k2퓏::D@!4HG`2dѾ}!{Q'"@dUS L2y1(A`{" hӶ9H?XSh)澖Lo@t?4WWl"hVu1K,95`0ؤʑ ;5@7Ej*f1)x!Z> ͠ޑOOر=3fju;3<{Giii&Gٴi+Wj'd=^7tFb, [KDgNB{.QoѢ}7AA{1gw5^D nAg~g4$W܊t!F<rA;N6%8s{ҟ7#M{8^E3û̜9ÕSN~C81ʙV"VYa # W6gVU/B+JД._@sN>jX%3/B~ҐvCm%4O@x)94`EfhCHD5("@չA hxh.G3Ќ 4PM6!]LV|%܋# 3g=\>l/_^UVUjGy$&L 0iR @'b``xud j\19uڕK#lH/C@> 9G9u~:\B̯DSsH3k5r'b}ҕ>O>-U 0A me΋‘ a~_aln0ew6ДGjS4 ,GV!mi(7t?0?f!QDь S UdbhWZմ$f? 毢c̴ D9\ ֘SNt֍+{{]8dZYYcǎ塇KE"8oUJZ(",SDClPDGeeeu"999q_$eeevE;&sE9:X 6]6wC`Qhl~iq(b: "8bcQS#Xw!̘lF.\H"]n? шF3+<)ٷ";Vdz"̳yI2UA4ryFGŔ2׶YwL ;|g^J42=`evYWX8& ̇ ^x>z+`VVVE]DVϧgϞtܙc=+W_}?n]v%f֮j-[F~ׯgqF7 e-"HvD:ԈgNRrssEq/娣tNH ܷe")DSZK8:#ٌ:Z8,@?gG:)xrBE$(n=飽kZzܕ%K~A` K6- E!C`p49"  LyvQb1=B!+t3${w$5Ft M=z!p>ui4ULih)0YO{ndE<5ԭN]~2+Bh7ѳ9h ɜhͬYӫ׉K/i­T^dĝLk ڎf¿}:Liiij){nwgwclnCq4g=M$߀@;xn dYGSuE-C` 1<>qdzhErMz"}SHOEκgPDǿ7"}}ȳ '?t\w`d3ٕ w7L K7e嘲-s.3e}1u2ߗ 69f r.EI!-%y pfV3UH.F>(\7k͟'p bbi3^]}磏>Hx$Kͬf?7|sJ&͒A[`|MJ}|l^("''FdF2w̛ܹp)#sQ'{M[?Wim|'݉Gf{=fGr"f}EQ S"؈:Po9v4r}}8݀]92sn+S_ˤ<6&s|OSߍn6S60V+ĄWv2$͜{ήͽe[Sv\s~dAcLs] _#P#`iZ@{.aHhe"H2fGhP)28ŋc}siii hͅACfkV .`t[cͨWP(D hƱdee1m4Ǝ3EO .DqnFR:ۈ^'&zF ُ^=@iK<9ؽ-TYB"E #098P.(Bd5ڵ2u{ISnaίBcǩf`Z@s9g7yٴJ*qXpháh{ԷĴ^(.;]`#iy#͹?yh&d5 :G+=8>Ԕ~EC {ub4d!~iPX(/gѢa^ZZ4ڬڍ￟[n%IJ5.))1 cP믨/̽>m(|+f]t !83q{ʨD?יz~L"Fq2 "of!G!CGp@*= 눘 +FRݺKpl4Ls d){|r6d-DrMNJs~7 !So:f# pvE$A hjwb.JUNf6|4C f6K|NvD"a0!G'==A7%@ہ1t#-T3I$d-ڢYxuo&Npx5(Qg )CSӼ->D:E:s9~ r>җ{k,DDgRĆpSqrzF_mߕ-?ag> !W[l0 OBxERqC ]V"O  !m0X/F|[[[!2e!kcs$Ŵ7^LA {@# Tl?  RC be_&j7SS;{4@9lc.;$o,E\,lOYo1ЏPDNK]CL#)-+KA~BUERM,-E>o z`Ĉy釷:;Yqm8j xW˛-ێFi: cRm;L"v3L@L'|S4wPgm0bף>"(%v]1{+}Byg!Ç4uאsEnz5RX"SfZl VGhc9v!Z؎;s_4;kZ?yh[t,sٷ[^j| \pA2=z4nݚ ; B=Xro ѫ K6@UbRt V C,?gbP-[:~E# 7L9ƥ0֛k_K(̮ݥ9QS;zj%b#{,3F4 @7~qVڹ- C~#/{Eq7M0}qb3sǦ!S!Ԍؿϴy/+[Gir @^WlD'ԑ8`@iLc.J6kHn B~~ݻF|eȑ7믿.]0|?q]w1d9:0k68q6, 1sPPI)bfDt V#@n <#@BD,z4eMFL/b{ϔD y&ZlEl2_  ؏"l')PC !&|o֘>miBĀBtL3>Č-pe<Z#@d~\#Vk4ȴET7'(fۈf; }҄ c%/@t@/h@:ަ|r0hf1/n+D~)# dzA>3>t@4;OM!\ve̟?M6/̨QիWVbذaJ.]jҭ[FR5N,@[I!==m-guW^y=ڃ_ b/$fw;4%?45폘qM?@Z]1iؽX>D[cB imu7g![t#s *Bzs6bCq2M=nC`iC~`ʌ5)%51u*D(^yN@Lksː1 ۗ#VlC{A}9# ϩ8x>zn;'/=V(F53}@6j3>Kcٖ-[ܹ3?sVT<tܙs|r $k6G}XcWOQoa}GS11.@6䐚5 jNsfu A`~"POEw9n `oMOCab됎1_p br[*;KBLo&bEO%O:|?҉{6th%ln@}4X@$ |LSo4B4+q/=~NV^gў@ؔ5s~DjԾY Tflٲ,%h{4h}{ms13OeeAǻҐ6őh}lYbekc9'5 e#k$.-!p!bq$C,4>`u 3MB hESlj֔0 'L!gUaN4yg%ndoF^W#\S`aw.DDc"m j@Q.6Zf9Q9|m+zv &A6  g#j_,މX݁f1"V>:^c4@;m\h6⢋zq}w([֔ZMƉ'ȮƊztt\C\[Ktvfffu|<c>Pg0qsq$D}7朏s4.xphqhĚ!4o l !P9 j&g!ICÖ(O) qtÑTWW}݈?lm? 6ο@ޭ0YzЀy}^jqHJh܍h)DUX" s`Ǚ5YS:}w'rYf*рƴCKMVzocLSvGfAf"y^3k&bw ~߅BN@C1"Ė:!f+@馤2Ϡ~b]; bjHj8@ ])bC }e>1pOF枎F*4^ {`CbY]8auֲP۶A?b"G__:Ex&b}ALvsР7 y)ZU1Fm fP, Qȇ^j_LDޕ4U֗o9vr = kOoWPKf J0m kL\};{ۺشO>Ox4XةH]0@Ծ !g"6\=PEE$|:bFzb\L=vGĺ1,F`s!vm7T=o`p]V pSy{7QsNo]9ϾcLHim1g{40k gBĖoqE5VX8IW,*N^l0=X+LCh}(EE[Њf\;֛ب)tJ1h5u\]jѐMgv3s~ Ѳ; E;[[:!u_dB{?kaS4-/BSp"1DrbiB'ab:\#S#LĨF}5ӫ k ʴ (y%^H$ѠvB z=ZlwȔѴkoj[1sM>蝈N MF\Y~:?oZr6;˭mK쮒Su7hf ://4kYJ)8lp8L۶mYn)'t˨B D^q<" u1[P>CQ#?Κ:2:0j.+"+4F .Md?l*rovo-I/"b}8|UP|AQ-˼Ls}v۷z !fL7"@Ŝ&Ʒ6;jL=W2JpMla)FXabDzsɎ@s^6Gu׮̝ɴ7=KZ˭mdVD"5N,P6t۫zWvxӢƺnIIV}єodw|Te酒лT `UTDUWsW]ۊm^{{e]ZpW׮k(齷&sN&3L2C̜̹bNk1l"бhFX7K BxMhјB6_Z 1SMƳ:IJ ##  w}#bw3b3ckv}B?-7 Nma6iHZ$mBƱhFlvSA^^3&L\%9YYmz e eVǶ72p8Lii)Hf͚^ɵ^7Dvr}hj>w!mV2t@wB)B rbU+Emh~,xm"GzRWnܱjVEDs !ּ/ZL(r[&kنnk2Žo:bܱ 蛢vn,PU 1Bqh{q}TGo7XrMV]97#rWFACrEKKKI&#C P(TWfopW qwj$уD ir.VbGx7U6L"ݸ|>" ~M9 ow@O 6 R_^4<Vc9/-w-"*"U@ծ1C3tkkuT,-sXCLGĆ# VoB xJXXvtԔ֭c񨛥* o`R DxGwنt2LIttNC׿ dXg͛;=xhr$_Dlz1l+ݗΛ}"jnD ĽfMUG<@F~],o0J!߀a<AgO1^87x ocͧE2 F:r^6vXoӣë#9xKڢd4B1 )ނЮ]WÔsC_ Õ__={WF)9m茼*L;xf Bzzz5};[x1{_!C̰xB,.nM_["W4eI/pg$4a<xUA7 u6"Q?aOН>[lQΨkmyx6 cc ܜk|7ixEU>-OiR֡WnR-|֮}=<3nܻ)kO8ڎlyyyV_ٲe EEE3 xyꩧ8ȡYd/Ɠà/ނl"_'2d0Ęx`;nfRD. Ѓ۾9xav":fQ=ضtu$}YdBn\- }~o'WnEl.ELrbj׺uY_VX&dsZL{^ZeF]Q}Xuh'kkšֻQM%Y8] ?k5-6ZgΪLwp!cxDR==M~7mx9)^xG$Cm>bwYxЎ -kGM&Ot(}0yZj ELA2QkToң-wǮ@N{6C=Sߋ[̾&KU"ICZQQ͛Gnݺu/[s1sLƎwSO=̙3+8S6FfH~`0Hii)&ݪkxEEEEE%Y/dذQyc{D#xC($n{m brȪs\e̳|GTΛ@j ZnNj^BM~_di 3Pa\!ikпt7c m&}صuӷ["An^ơ=ݼ7՝?Z`~vc]iUܘV(V5ƵzL/0/J Q4f^s(fPIÐҥ IDATk:ݤV`MJE?={2p*haud߹;שKtɓ'sG,)m{"f#?"Xtݓ0 ߌA~SZňMފXZ t߂3g w0H #n|2\K+_;=:c:x-1 5h'/@gː.@ywNPC}n:DGo@=c'; j7vPxwǫ RqbHGQB;XϡzWdw1`ji2v(xVTTT羥;U~>%GkP絚#s/[ 6!l]/nȞp #fh@v|ӑӪ;="} e2nwcl0ὄY(-.1˦nGoݝi:c"Ud-2X/xsEDB E&^ٕ-tc ݳBx`:z'c-|{@մXeD 999 ҩ8vn*_V*wQ!>11c F:,ITO(CS7T!:"&n"<4Ĥ-9/b!} m1YHy !`lvTy1^=PW @1wvc$K P=Bw֧5^oscjo|w$ٞvO=۽~G:JJ7ލ2BA=b{v55 vQP5 't{~_n.Ouv r&.Xw%kT朗*YsVq!9z)xXv/X0VHNEmҊC#vb9(x<ĎD,/Can+y;Ҁ_BN}k[KUPVr3D먪_ۢUښ,B~< |uGt,rb;ZNCt$s{ rLOwۓK-8"{+jV}c/$v"fc4G'd>䴣㼾ZrJ:u]iiiHpJ]FV~ IޝRU^AElS Ѷ=V>&i#@ 8f"1 :A6{tE =sԝ{lI7HŨQoxjs`vu й 9Ck~ -sТ/9yhGEs&)G~fh49x_w+| ->yyneZu:=i͏U3rsw߻2i:t QgӮ2̌'ZbJԆ;--RKKlbII It(3ϼ/ l[]0}KPCϯU -0@?G,Zd9"* AٌVzy1\x)[K׭n9g+ZxܼM~Cs-Vq#4 *<i$7:Nƒa+w][gc5ЦMA`biyxpE=[C|ӕ]Qt:BZT6ǽO2؊ꂤm|iҶOwۊ4Nl ił p?xq1h׿b˛jbc[Z$9mqHǫy .E Хܟc'!9a;9k!mh<"LGٿ!cЯt8-tx fN^H0.,C^Q&wk20<͛2Ԉ+**B I#Ѷ _@ƠUOWyu[}xIEe]RJs/Cmb@%@2A@ EZxAwmGW㕷lJ hBL.!yZDCCbscINk4Ľ`m :lr&G!VGXu:ݹGh#mx OF{4bݷ#m:(7A;R@y}fwMV.rF#<҂ng:Yi5L"[bP.<6nȳ>K-j9Zr蜄PJ`|Mf +"BU TTT)>V#;눕UO<4^{z#@<6 ڶx@`h.A=PW>^6abJmt(\DzA0flFL=Aw>x-"*,ϜV!wHNGlk-gs܊\ODKĴ sDZat~}c@1OB uoa@'9, tsxЂB QL";7hk[<.E>/sXlf6mڐ"$YSDSΣj+VZŋyk<Β%KxyU=cуÇ8JW`9S]$S~t?q2h0JK7!"<Ė !J3i>>cAxm܋]l5r-F MCՍx= wJ{e,4}XX?wqs/iZPsŦ<{E Dܯ#t_ljwQxo]U!EL9boFI*q-q~6<1 K.jj8&Mħ~0W^y%mڴSK2i$.Ҕt}l&Mj\9ӗ&tޝ+Ӳe/WC @Z  0 9ƠxQ? p<9m.BH#'Dn<kRWsCάQ;66$#z/V*Ewf Z77 =|0w`X꺙}kȠGQzz&Z.3x򊵚Exm^Mh1 1R$qE=flzp< Z>DH9Io!=ĒGU7V%MnN ݵ% 8m۶qW"I9s&?cƌIisF'qS YYY*fp@ @~~~u^ӯkAnoڴϿ>1HclXm''ȋhYCirF>b]sB@s҆@`lڢz 엹1DLq(1?+o7qotٌ':WG"SB |~ i1׍'YyC@:߽f9/>:wG7sy7 17gZr1W/!Icw7_}(DlwUV!ǚ6 n,Ɠ#ɹ[gGZCJeeeIZsY5up W_`cǎn{p dgg?߿%chufffR["u'*dWڒkB< xݼЖ|K>E:|ZVw0r MH۝/^}B}.!@|}E/b ^K,kZ#kE2<'|1rd71q1`Qp  XrVVVFNNMnӧSRRqQ55:NlEEM6M D"JJJT?Q[f??kYf bI~ތ/Bp6W| ~v8 Y2Vcju;ލgҘqAD>qy"/NdE||F2KJB,g<-9Q$CmB &233lFhalu16 Ǐe˖r!y'ZӠ1seeeչV_H$ܚ.4h&{Ơ4mYo^?A,2$ӞLĈ~O$MGZ'0FW `X&(CK>k[5L{/4 tixջD6̚-_ ]5F,B^,iƾe]Qso7HK~ S[_vˑTYv/(:f!Z!OsMGPGs5'[ю@:iiǯܹj1.9Ջѵk߸х0eee0WK4 0YNn9aL,w]Rg䈲[൑2 HbYW'"&rj&t!gG ~(ʈᅓY2eLmu kigrb[4@"&eވ>I;7Z O [#6sczݓ ҷOq};gsW|s >وn7u_"8]s˅D"{ӧϑtWK܈M]5 M!@T@?\}"1j395y3۵ζm+5<ϥzUșw %4:#;'ݹ_ERe_l{" -2zs~h4-H[=h/;&w,#1aĉS5aX@z&7)M߉b欳BYvnW|"g/w}9 "=pǸ %tz+y{Yȑj3vtQQ:ڬ~NNN5ͷY5Λ/hth @fA~h=bF/! xa69oao"l"@L"sx 9>@˖#}-d,ٳgзo_$zˑEa%x,/z>nf `N:i(x,,.ڲKP?b6w#~ -G!-5ĺ/vtY"'T]lM1Ku/Z# `D,^&%y׻igYhMRK e8o-͚%!fA (#jz motW䎱 mz!F雏 ؝7mCyQd9z (Ҵii۶;wbcOGLK{;n:mu5nl |xE-ܮ-XE%nnurr{nwCs4bWm@a/"@@A(|4U|^(jNnnZnyGO&X/]V5k-[@ t|q}ho]!hj7%!-JF}7^Gb" F:磈MM`QxF(9E8@6mZѭx !ZԦL@>}| [1+j*zЮz bFP], "p9fs1,;A] NFi( YD l#i̙ңGe:x#Yn^$XvES#Dbeڴi SN9O?wtn>Oݼ$h_>$GPZǁxMFp& -NwNl/ԑ䩽; ݫ;1R֬嗧6.+,a~1خ_o/j 6ܾ}; TTTPRRP {HqU# Ex0JwBu9>Gw(9Ǣ6wcNJ `Jp`X"fTXWrZW<[1c9^{;ͅ%ؔţZڢEiWFskJi?L3PV5h3/'{-嘥I=' mZ7>Br+r"v?hÍ7O>G,;5Mnnng'95: )..,ߐ:EB-z\ia\xK%zq11h #F;ߣ@v{QtMۖ_^o!^? 1у T3w.n͚qe!Ƹ,w f IDAT\kџh+DZvGuZ˫|.\DVVV%A@9^ANܜ=vK.b-E-/P{^:z!~'軸k|)kpYnAR=B0 ;;;n_i(:fN`0X tmsg#c {y=z^E[{kZ ab< =ү/6S"`NLwv(wK5 }ӟCeP\\5q$ QVVĉfm4荦h0^N'@{lc$ iC<;S1c?/p_S$ I*1H~:-6nE,9JZO=C wIYȉ2[ X?EzFzʕsc62^~sXa~ꪫ(//g͍.++EΡA̘p4xA~W ե;}Ug ))x} [!f^@I^x=h.6}ҥEB[Waw)u]b}4Zf D`{$}lw]v?tfg#&/"0qD i~EWcpoBz{  h's9Eٝ%H*pVcT:̖#T܂(Y3I>e/w[SĖ/:#i]P݅h @~qUoDGcnڦΗh+</jb;nIAy->ڎ(SQQTw7!fE.W-{z <HI߀Hf#Gr}Uh:b QP$U FwhXB~b 1n>G5`9"q-dC7o'F85lڴSXkC/@vO>deVgoMӟT1ųF)qԵzM BI< G!]_h+b1p'K8tE vq, Ę!94Ѷ.@܏c$by(yHJLqoذRX5+*̡;H.(kjx@ ZZ& gώ'{qY#9["@R$z/^GB!$܎Sc/B,4GnAM_Pˆ/VVDɬ>͖kH$R飯b5kVuFaa!_~ye3g2vXnV"k׮eS4GCl m6222R͛Gǡd:׻k@ /lEP K1>C֣;];g}ĖOD2,h!n3gfuc~kҤ-(" iAT䀛QC4ȿv $H>D  hĉb7A ۡkCݛ-Nv7ѢtVc~9?_vZk-//'--M?"e׵G*BK%;h :*L0H֌ $Y\^^@]۹65Vx8]$Xft{mE >@h%HCC9s!"@9* ʕ +f5ihPb=buB2T7E(l^ū<]< U,[V{*o!CCs_tqimFхhw> F"Ę#F}3нjx-ChFȹxKcQ#jfٲooʪl,QmHO:p8\/A[G0X|qO?'{ ⼻ѯ[h׏hl)-^lrC(Sy"&b\_*@ FF訐'E2!g"6YG:L Rr-F߀"UB dam-6Y nNNNtAmSl۶WFu$ByHhW|!@jt^E BG!=Z_@r 7ظQ #1,a٩Kضm;vqv:VwP(TZ@>gѣ@,+^b/"9z Wof)+<9JDi@Ę{SUnG[cXd^esFFF僜xղt7bf"]KG;(> +SfA}f%ДHjkv=V-^/tV^믿΅D ^Q\{n 9Gb$>Niov#(Gx !Y;"z;9n#mrd>ܹsѣGm[6Mp8\o$4B14p;Tm]2!zz;9E9xMUKr(EY}^ >ץ["W%d P|$ A ֺbO@rw#G^}+rD j7i6wML |XV!ds*εB e"]E ku .*qٜW؉7kX6nNh<_ M\н<ݛ49FbRSТ|5r~α /'ls4 k"Їnk__5`g.Z/'(Xtgz $V4;;VcmҠg!Fs"U@bb Eň@"R ^[ TBr`9 6[|.]V M#ޖ7UOA ^&bkǹ\(^7j ]ܱVY37_G }ӬYEZT|Y|~0mF;x=]Q?(wwhguҜGL@9{@~bYr,>n4iUͿg[ MnLNF Љv7@i,='T6dl,K,_b5J_z=سìCP$h /Dr6|},bZ"0|tĞ?@dw"W_}ƠAJdq-v.C!HGnȖ˚"-ko6Zh{EE_] ģ;ddd~QR?*vIv׸ jnF@-Z#9$Wu9ԽlEz$x2Ю[ߜd}7*דA猌*kOT޾}{v;-@[ w"Eu,$yx!z~/D~kQܩ؎ _k6x5'vG;"Ԭ-AD|lErltҧй+Cl~jbɚtoBx7L$q<@>mVo:wg"'daQdcv=YC=C=@tFt;I<3H#'2}DN\t]%4]v#cѽmC}Ђ ᨒ@c7[+K5LM,D6iٱXv0l4%@ѬY>7nlM}kWc7EГa5)'-" ; zG Kv|!=1TRM7]ǨQ*TW֜G!='ڪC\,+ GqUED[1ha ?28(++#--ގ1?>}2@ڗumB}bȑIAߎ@#m F9qǟ[wz RډkVɲl[k[Sb˗/UVZfхj3B hP_?oC!nl! w;+(D̳bJ{ra9 ^6n*gL5k=v5fB/ P9[cmұ8}qHEeEc9蠃vHp80Pmۈ bCQF7t/"v}"A+}<,^|/q]8ټyqR΀,۞=eee 2td iѡz^̴o?kׯ{/*rLu:CHXN:bE1U(6v5^A(dr|M@:{'W\1ʗ!Yߎ8 ^$ElR{Wږ߅Xh -THcT&>1Naa]iٲ%Ϥ8˗^(noÑ]Fw{Dļg#{?$}KoG,{2zCY6P̔fХL<=ܓ=Ze&KACzɲo3d ڶBIKG d]C솊c~Vn \+]@Aazl23| 4*M@'pEVTT"Mot" r{*Eۻx-@zC1lԛ1"jƌ' {ph7i @hZ7Ga,Bψy*wnv槟*ς P*sy]lժU̘1C9MPlm﾿EΟ11z0O@E=nF31ć!=Or9ꨃx9k,$:I#lǬ-#^\3x%L[QqX 蒣QC}@- ,$a ggg=ٺu+:EV#A,$0t=> nO$A!{g染 XAΜ9͛73tI:~F^\\pйעis.:֭[)-2Nw9^wh:G,+<}ű3M,_RY2QDh]VVƔ)SСOXw5Z .$z*Q`:},(|Fdh;bo>Uڦrאhx6d/ED т=^ }gNF;>f*xw褠[]4bEfXշ~˺uX~=zgϞ5qXetU))) JYYfƌ}@?==zQbm@"!ե@}'Y["45o '_LD:(&w/ `YcPb],EAX_=}݆EZ5j&i4t4̴iӸ:u.XLDJCEv˝wR%A'VNE,0o<-[F^2e SN[oSN);ώF /--%''fB2Efͩ4fdd Yh6lSNtҥ^m26#2[`^qe>z!pyI-K VHH{?} A1jpŨ&JJVļd!9ڂ ׯg̛74w_{otLA4uf`iӦѴiS:(N_@NeHNc=uD\< BME:@_%xb"QsBIlPtXs@ڴYƒ%?%|M!c+^I҆. %}m޼SrAѡÎ #jЉϰsuY\b_A4rCO4(~bH5Ž^3-%fџ-iժ˖LzP?7%㨳"~XQ^S8fƌs1$*--墋.yhт{eŊu]a222\?]5@z o{UйD{Gųde.Bf %⊫xP(P%ލסĞBc6GҳDEn6x,ڶmKfpNN~d";;( 5M>RJJJѣx`Rz3K/eԨQnUs)ꫯlװF$D"P&5G"]U+++t,g/NښBJ6 '?*AL$D-sooP5# ` 48edd488CA8&++*feeez9ԣGW^seɒ% kŊt^]ve啯?w XNOOOF朗ΘF@C[*юP8=sַ},{9KQE?^V9j!|3*2tz K=;+k=XkēH$O?ڵk9HOOgĈIK.,]C9KV5Ο'̙C޽S6TZ8 ƶ &5T PTfRѺ[*J*mgH)H7!G1S"|ꗆzo m *=ʑՃ *&@̹-0_N8!!ggf z[ડO˙2e mڴa:Vii)_|14mڔ={ҥKZn+B("pI(QU4Thא '$jT:vgTر#`&*Y4FbuITtw"QO#8眣x'c7:XutDC]f7ndڴivan:nLӶ}}ɂt@& C U.@yymB2I1}{'4(TT9--$%K0|] klM輼s55TiVogD+ĒzH$ٳ9"Y T+T؊%݈*Eq9r2~TD q_gkwMAkTΪa\QQQyRG2z)/~m%F!1fwh̩տvM x?L*јXF(b=`ݺA5C|!Gb?w/Xȑ#wխ.k,ͷ.;*t/EKlݺ)S0h tPo֨бNR64kɢdmG&D+oP/Pg7!86LJRcGH#HMjGkk"sXx1Oxщx?裏VdzǓ]~L\< kg{њ,ԹycE l߾+_(AU$Sx2>8s7Pӽ 9,_v1|9#:v"'z*/Rl~qj|Nz]5d!m)3C Ś?ԃqbKJJ?~=J8/iњzRQXɿ6Kάc՟=zcvn4v-2̹&[j+W3`Ĉ?$u_jJ|c4Etm߾3fzjrrrv<ؙ@òT0 =&b. `gjW+###:v0dԩ4o`Bsa…dffGܹ֭s.TVۙzols}lG.Jyv"D濮ŋ3w\D"~I߳2 G}T17vkԉ*zLgg@0aܪU+:wL~~~NX3LؒSJ/Jx&:TwDFفv=YYY1o,Ku:u˩`Μ9wyr)viYmgb222ݻwep8… oͥe˖tܙM&T3@ X;ʒ  kZ䬏5dͲe駟8})3L8cp%KO?U2:uDAAA}ngk%4T !Dt;3#.)өlaH1c;ۘ(?I{EڢHn-cSp Xdj2ȒeY1%$n&ʆY&}K2" KB,cB ZaQv Rmo/1n9yξ}n\Mfdd //P(8uR)Gw h 4 f3ݻle8-7s%6f uv>\ yflݺkC44˗/*   \pqV(ԓ/q @O6` bJIadd* 96aiH cF#D":t:j5AQ;)֙&+vK0p<x7{̉U 4Mccc8|0 r111Z@(B$A.C"8FD3-6!;NppLIcݕ1[ZZ;vx"|'`rrSSSx⼎z^^L&t:!Hxsrrj ( 2 6lXDf=L}/(7ڎ4\ՙHMMubojwee.\pf(J[ضmrrr?*c~{|] V?ϟdFSO=>B9yU  ..۶mCbb"Faܽ{@QCzyƼ*g|7Nn=3 paهyh4"88rr, U1 :DVVD"SqUTT )) J oX 9siN];)) _}6n܈!8p_t?;6ﱔv[p\\=?22|ttt 77k:{nz* 혚b3< fEQcި{=9cфI|4A-e[v=b`xxiiilv{'9..wqڌ3ɓ']:TVM?>>?o̝vJtP^^GCQv܉Zt:dggh4hnnVe5b`ffAAA(7pp0d`hlv`20;; @ՆPPPP,ĩ_~iiihllĹs眾3x`㋽%''kʌiנJ%>|~@OOpqi|,ccc.=eJ8ofkNs!=&KBp[ho$==FK'f={_5܊s%Zl6͛gO}8yJ>hsω@<"`Zhmmb={x$h718z(B!QZZłNtww[% r#aoKN-asZ*E<9x2==&<ؼy3&p I.jqYʕ+śo}wHHH@ff&Qj ]]]Gpp0u|I^$dL#000Mnw9;% ƒ ##c^'qE!5J^s `.!lݺUZGee%z=~i@&!44k'XF)XVM QpQ_Ŕ"fݰìred1hf9BJ+QآjY!biFsŋ8?]|G۷:c_XXopzbض ۝ B1w`07nĮ]}ŨF|TOœZJKKWUɓ8z( LT*ܽ{Eek®݁wׯ_G@@^|ENM}{ reƮS j5!  !JVK/ gx477cǎشi' Ih4 waFGGC*:}iiiVe (Is1RZlg0ڰ~$FIk fŮ]xqUs >t?iZESSሉAHH I˭Z.aJhF{{;q!QVV`΁?9Ƶ)q!aeANY!** `bb~!oߎX466B$A.C"}DKK y| `O!R?ZJP(EQdذaS>tww#33ojoBJN@^^P(p)HRSSSPt  l^hXp X,ٳLA4aE` ֆowyt>z* (Ʉ&<HHH;TB4aE\9r ahhxAQa|R&kBoزeO'g`n199k--//& :ŐH$&$OS[[hZ䰣ހiBx YYYFDUUռ^@kk+OQ܅8NQXXZTWW#22kk :t4MbkqyWƶGFFB$y;l) Eb熇qeT*ťK?%p9A…  DVVrssQYYežRdpp_|k_RRss>~8 @4FGGQTTx%I89|0***H@Rb1IA4K)ERSSQUUPB$1H@{JHO00 (--]UwB4@ (A > I࣐M > I࣐M > I _VIENDB`mpmath-1.1.0/doc/source/plots/spherharm43.py000066400000000000000000000005211340375245600207260ustar00rootroot00000000000000# Real part of spherical harmonic Y_(4,3)(theta,phi) def Y(l,m): def g(theta,phi): R = abs(fp.re(fp.spherharm(l,m,theta,phi))) x = R*fp.cos(phi)*fp.sin(theta) y = R*fp.sin(phi)*fp.sin(theta) z = R*fp.cos(theta) return [x,y,z] return g fp.splot(Y(4,3), [0,fp.pi], [0,2*fp.pi], points=300) mpmath-1.1.0/doc/source/plots/spherharm44.png000066400000000000000000001207741340375245600211000ustar00rootroot00000000000000PNG  IHDRhHsBIT|d pHYsL1J IDATxw\U߳33[HBBBJ  TE`o_ "AK* Hh-m|ޝLl25Mf{{9ϧ@2|JUTQE@2\ TQEUT5݀**2JUTQE*AWQEUT(]EUTQtUTQEJUTQE*AWQEUT(]EUTQtUTQEJUTQE*AWQEUT(]EUTQtUTQEJUTQE*AWQEUT(B݀*v$Iz{{顮`0HMM @`VECUH&$ z{{I&q:;;W("  ]EJU xX,F2DnWSS3}*vfT ෘӑ|8b>]HؙQ%*hH$/[~b1z{{9$*iWJUd2I,#~$Yfi)[U U"'!tmӶcuuu)gwʨt0TY{ >~vI$U]!*AW 2Ef$?v.$=omWQE%JUL&)bjrS RP%*RE8.$]]]q"P(~<&`05$o{!3WEEJ;1@w1ēL&H$B}}}%ɔRNd2=X(%/ V#T z'DȌB-Z#v0MMM})QYuuum0K{IU X.$e!sejkz{v[# K$I*TQ  _dF>ˆtuuhhh fN27% MO{bY{YEi N$@s2d2I$! D3 L]oH2]΋*AȊD"QXOdFofQFz`gmfGdQWE;-r5p8LccJT1dҨM"4x{zzS^յw|T zAȌRM:::BDf&ӓ _%'lvzICUH$L JPD"3 A%G:i[_(ʙd3ɱM67Q%!Ȍ%ʆD" Q 1dfJI?v eBSţIeJCDfd,9-0m`gпFX OpiPҵal _ U6=wvttT9z{{ꢶv@vdDU3)[_bWۣ gHVuA+$ioo' Z9 pOd_#ȈLI1vb>muuuV7F(]0b.5}j3q˾,;kjj)8J% r{$TCJG+ "3_9;`E2ՀΆldWW@E 62%$[J!BBv%P% A9jfrj3r6iD"%,OH|p6VT<*}'|v|@KiJ$UtXS<J8昫Fg.viFCPF4L5*5\o'lRRfVBKzLU z`ёr c.\ف@ 3GѲPdZL )?F:xU.-&lάB#&kl2vtm6` v S~>U'Ef޼<@kKi{~kBh`PJZRٜR}Jy+tȤIB ibs>xdC@(7(T Ur] C,lS)GU]$Ef'Tjk!(恳;hRL; tlEYI;_] #J#˥kW@ D1S&KW( ias"Bvϵ-5oGBc*%@K;[UB,w:϶Բ]3Y.hٙ9puƒ=6Xjkk: ;+ije]s i3?J'm؂`A;'r4e޼y0b|޼yrח|t (µP^3L.˜IB[I45YufD!wd vծT;>駟Χ?i/_ΤI[={6O'dΖRX@1Bf җV-J"[mVLD΀d2ɡ)'l2f͚ŲeRd}f.2.\… 9CҦ*A;2P ,88/`+hT ^NlyRQhgdgc]]]\S^t6tvi|gذaL8,[+l ;9AG6MS#555E9抁Yd⦋ϻ:Q,i'Ɋ HX$VƏ~d|w+St(S-B$0PqӱX,ܑSsJ]ɺXmה`O 6lPېIB3,xkYdJ6ߠ4 Y;7ؒ> CV~g I?)8vr`!h;::ttz@sIXb6-󆆆Thϻf𓶟vfVLNimmZb@ rQ*il6yجƝŐٖ#yRA A)ڦ&Awvv0hτ(innP˨ЂFPZX!Wr8V?tkGF6Ҷ~G2-dW#ۋwf!`ڟ1SNloJ}Lg.* ]76wgl r/wj=b+w.42#1fm D{Z@qE1*7-;7 3#[g# {!w-C|-ӏIߜT\!H@MO6p8w}$ԳOKYH !m+7*.wrVbhLǐ&X,:k92?XQrŸTrbG. [hHF@0B##6\J!\φ-D^DH9^ ӿoN9Ȟ6`I&m[-ZVvRfigٳaҟ*v,q~N/њ-V;\Vntʕ\qҦ;mȌv&L}GYDH$RrBY,|]#[dDIЕL L$,X[oe˖AĬY}3[ &p 7p'F7$Ld2*H$R^LXEdgi@OƜ\jxݓmll;h.D"1(i0SkZ J,9PUz&4+=׸w4EY?uQ|͜tI|_%KllF}QN;4 VX&h?1[Rv{{{ioohaq Z:AW,KSSSS?vwttPWW)~0|:i׍ʤI( s֋It 79spqm8~G}}=/r OCKGr~kuuubr[h4vXJ@3#E2 0PavE׿tTۛMr O=ܳO ls9KbBN0T[Z\P mElG ;iJ E{{{BIʍΜ9s U ŕDW'n Ԓ]A똴Q̎l`H匼(!JG%薖lMi ZS)3JR8 !S[WPC߭ @RB2F>7QW>kkkt)f]&mT*y]HH19;ޮO_̹ f #~Ur۞FLmYHb a%vƌӯk*ӑn]FѢ ib'\zva@\lwm=J'1PHߜ5W"r J]iكxՂ' .= -ȓd*PH+3G*d(#P(TQ 4G2vGGCMFLߟ/S1v> A! eLKKKtl?HCdEI;?;`E )y-@t(P )hTc1[[L HngkOzr"=&&tw:(wtCߙv1UpR$?QSSC$k-U/8PV9 )h߸ft6HdQ a5(yq:::RG~z.ೌ9񴴌et(STg&y[Kb(oe[mp82hl#~\ Pd{^벬X 6ښ|Vn`,_8tMZ$BP%>dQyY _Ԩ3umȿ{Xd ʹi_?L, hdɒsΗhiرy7|a]]`H$-6wնXP[[,<#is1lڴ />K.ddp{}뺊8 q<c.Hd,Ykl#B@bA rU3RYg]w={q$:;rm,]*#GxL1ɅDJ ״A éJq̦'l/r^{q饗ڒd7k֬m*^HNaAiY[[[P耳Ҧ@ oRC厙6AuFWr` p=`6p 3yG?*zpl2V<27iiً'--rgO?] goyiqws*w}_26m3 [n-k*ނ$l5:u,r\zx^GGGY}Wp^d2oa{kx뭵1@ XVDڀK'("1n@;]v%w,gImK0!X*Ū/FOp X@N +?AsfԈRڹ*٭^z  KHG]K2aSHr[yvmx 803__>/p6+nMeժ6#mhfWH_ww7t8+VlDr(X4 ādm4t+Zo}\zYbA^H;}S=r00$:GEO@,fQf͈""> x8 H?L{>+mm5L0%K^,{{ dgՁ$a@eơI'"Ž?JL bJa/?8JOf ,"P1$:dEdh@r[6`7ЋYo!Ux^ `)"ǀw"0p;"Z[y;ep5k֑,^ʵ#LCV~M(׻o^t"$&#PlEKK3s{+␳e媭QbT; se;/J1c֪PۄAdKlrsOOs7gd=7I$Wa&ER;8ҫy˖$}YZZưx>ڀ=s{Ioh}Cv}>3===edu,pR{{{FEEkA;2fOʍ0o4J9?qh(d9nE "iv 7g j]t)ׯ/`ܓ={rVo }hIDtgpy4"F;lA.6O+٨"p81k^3+namAG_쵭.G"HYAN!7D5Y 4 "ee"{P( ԩ{ں{HLH$1dYk\{C<&׎&]Fk@ltQ{$Fo|O hk!_.y؍v>xn3,dnb[_ nBVkEXܹ'qyqMdlٛQkB2>({p3_r<?QG/"H2 /aލ} IDAT7D^=tױix8餓܂޳\@ο{֫DSPRʋH={צݽ~È0wgT{_s=yGQ?IB#QP#'!B hGȩxM^Dχ'yH<6K.!p׳rg<>L&עibn%*R4D"$|:::hhh(7+ ˼/ZSO$˗[h_VDhh^$0u%xDIm4&D' uD[>|WϿw˜b^%CKh$SEVsIO#b;YKрoݱM훑n}~}1r4 m7?~&W^yeXY3]_Y' d?:﷈[<IrǜBa_BM袵;gD[T]]]`򡧧'u`yD<39Sr!0w>% ~|ӟ /dҤIOBC{:#_HK!"r- exNuyFI4պ~IS(7\EVѤs>sP5׿?G{-6 BU7 Pt"J_&Gy$3Lې@bHt>,&@`Qq1V@</\s} T,"R LU:,7Pc5޻ -~F :D*-Rv)" i\~70jnwHxDoDwhTd>ͬv$q#B B݀hhA 0ZZڪɈCy"½F1ĵ]t{?_ $1MvO#kc(lŝ^$Y_4#BI{GF2$ 1qDΝXR6FCB08h%ڢe,rYtt}oٲv;x|?T`gl(Jd^HO2|p:u*'NO_"ӟ3g_|1ƍ+-Ct. @fb Α)8S؜P.=?j"u] Agas~Gi>t@WWF 7(j!id=֢+{:K|,ҧFV\"f I ӑ`1GWĚi?p]sݝ|B$ن,7sZ]nv/绺 *4IeHKYe9nO|׷kԺhR:\ڝ$9>+44sPվsQxϖދV G>|˽VvݹmӃN/k^]hmKoreaMW~0cYTgHC1~Fpt鯝+jX&"6G)}Yfzơe0@K"uޭB*c h>iVT g"›%{h7" q 꿆,o#Ͷ?q}YVFiЛy,n :UXV w!9nBdy$"]];@o"RED1 @vۀ__um{jYwlniIwQ[':i{[H%z#4ον&מl[7<Mvr1 $݃&IKHIؘEٙct}|;ѣG =h |k/.˵ˍl@YL-g)޹krbH~8 Yt#r./j$H?BuDcѠFDw݃8ލ4uhpN@b YQ$›5ؓg=ș(ҡOAƑ}?ED{ "^w4uc6 v;JGi co;[M4sJo(Rc=p7{!i`_~ʍ[ sc+ó=EϢ hD!dV=؈Ҽ5";jj oq}k-n<$LO6˺KW_}uƝ+CM2Ê Y}1Y$@jWhh4Joo/ |r hF+h/`CId ݃bhOs}}5v"s+;3r,@Zܹد" FDixHx]WND (=ha " ҫG' Ay ft*j#GEV܊d5If{ߜ6"xѝ]k0DP=;W_|!d25\S%ڿG ;4/StH&DѬ5___*z L/CdŽ͈@߇;"~D߈HxnoDP4|D~39fsէ$],ҿ"m?&TMJ kkp_a4!xSr)".qƲxYY\_/u߈,JKGˈîMO@w"s3avm;9r!d}?)(:&&0ZV"gNFDPDbq'/H8 Yum x=3gΤȶ"`0X8?墋.*!Cݴt/pdk7]5G#2umE"4C Dw!s29,u7-{ R4p>$4G!=uDҧ ݈|z ЯB4Hs"=q vW6"}\X,〻L}]ߢyֹvP7s6Ɠ/CȲopLs gw7Ixdm[[&0^B$$M-wx$<u/A>s/tdžnI?b2*Dk5MrH3>_}cI h` -vd%/AY9ޏg aGqDFG#x>,?6&N$Y_s1t"G9'Iawdq@d=}vZ4ԻAP+UW9[[[b&Dr#[]EwS2azDV$jc@d4ގ&h%3j=^h"uヮT &{; -S.&gQg!\s1'(BV\O??V.Hpy xn{& b}Qj\?l.ܧ/E & x}}}Oӧ7*1d)hg4sF.=YыySڴ-ӛ{d=m['4`ybo;g--,@:"RhA۱H>须!kn fvi5h? O~vy뭷3f,"^smva5z9JMzjo8Y >莝gvՁmg{/קS/,5ȹk\酈|{d`r/^MoN [䬗\|}Ms|@`7/-lIb 938Ck#[%Gy }{quQn: A%Jks6W5twwr/<#pǐD@f+"@=UnF|T"k3^A{@2k"Mlj S"DfF=ȧl,4l=e"fUkA펍Z1ACV_d)6ǠU?/ "펙k^q9޽ڕDRS="Xb"mDĺ_;" BnZ9dv!?cl;n zl :F'6pu'9 Իm3~ Y˅-X͛73<Ç>!sW\q{,f{GuGqϧ~$ :~?C`ma 6i65gٳ;GQ.TQD2È,C@Z ?$d+Da?DD*QtG%lEKzq?-W"d5O܌g>lοۈM>=6\]?Y;Lit/ף p!"yvqm&[)MQv3)V"\~'d0MX }gf_v}r6Œ]~S|]98+H #YcMNsd7k֬>&NȓO> ҥK9#n9SYmH$EKz 3D۹kgq6Sxn˲;H4gR䂇Qw@$0"g $CXhpߊ>hзAkd-ZJA6k<$M.SPݟ ioDdhqjpm~uD~Evml­x?<pbiwaZz}fdmw; TחAg cwkld>i*|V#w;]^A]PdY}4~c+$"B gśeBS ^xݾxG~ ԰|=.seŸgfΜ>lN8>ODjUas\#FJ"w"e2՟8 ؊,sZR%/A'd-w]9AX4x_FVWbodGŋHqm{+"{۽zD\{B@FA> όPL3+kj;' D=Z+H~̝ O/Lnf{I$}b_%!CЅjqɤ{A_̝;Q.b_}7! r40dz2H܌SG k̉&x^l+r])w$^mtZkP4ɫ ~;*C# edmF`{%Ⱥ0DIw|o'Lΰʱ&}C8D[.P7q&PUaHn +ɵM=4Yx{\ߍBנ#x\?'6齮`7i-4]TKНEOlo Q2I P*AsRqa7'}T k$gBߟ?YT!kFHˮ#d zDID"Dx' AkY#lkK1(kkXhwxŔro+*{ϬX?LN cm2AH;`4=)Ǣ g_D"Bs>< AY8"{ŢT!| +oЅ|wy;nGE&{Ӎ{_wy1+9~P7&ۤkѠ * Bv )6lH$@㋩Ώ~t5-hY~+6n IDATPQ I݄Dݍʝ{x/tM+e49]fmED\xwfY ٫Z0O$ N$R[[[5j*8X::lM(HA#hEBVf"ڿFK MFdq(Fw 7M/ny<&^jD{nC]qm+ RĵFĖb-1hI.Z\\{~0"ch kE+#]9kt DvmEn<D*D }?ۑu:W9awAxVt6/"ⶨ7>+D&0P0Se;ˎTAׄPWWWPh؜e&I 7{I<(siS~ f46AHU#U< D&`-CGtd  \ r⮳ t<ʮ I-rZbC2@.+f=vҌg)wr/5NEQڲO7vxi<FNͮeTF4wogBHזixq͆uh} oK5z=oR]y~ hB=!ןaQKj" } Lu /sV)?rjBjFW z'螞>asI E>No3/F 9w]y{O6!Kx#w0Xn$쎷M+}[$m;˳]#|}-ְk]?V*h\dBϙk7DY]_w&M(}*"Ĝ/"k:x7%E47dTMuҟVn~|`˖-q7/Rn:;~66,\;{~ng %J?e# {mjw!$ dO@Gh~ OL ,,@u-Ơ|?E?\,m (bĸeʜ#$o + <FDO^hpX:w("y$[ӭ׻sֽ,z۝MTpN ߜm؀W9w׻\w6C$L ^ ~t JCfOI kȩV>a$r>NpmtÛg>dǐsy wsN<,3Zp @>=ۤ~;7r2sLM[t)W^y%_=~;|s̷mN8ᄲkjjٗPjI<@ 7 ؙFI&D";D^|1Vd5ـ"6pVwjOӽoZ.pö`2 ׬ޛMBxdw߫[[ r=EhY8G .DIdov6DW Bwvmy9ֹ` "!MDw"K{FOY[lD&7ݿ_B1V#WT,SK8wYoʱxVd~W+ AAM4 F~x{6x!HFGnBQR&ֽ|1µc!JDiCr=u-"LRax}qK.M_tiAB1irFMMMQ)ځ@ #p8V\^!T|o/?[q!BGY{QoE Ճ43`mkI:Ĵ+H|u(kiuOE{cQZ{z~mSeLMN<ÇsuVn&-Z~;.2:n-Z>9>貵qHiйvU)dΨ!UTTF>;} |#_,a4ށgeRd3L^0,&4j}|468d쯽L'mx!rxݵ~{_R"Cvn+Jdف"R2s5!h%`t+U/&D{sQݐُVw VGRhd]>!+9w;ooY{C &{ !ӄo POZ+_$sh32׺6M$6<|k_Jc(~.g/]|# CK Oh6͆X,52=.ێw"z߇WD֙d}E6DѠߌoQa$#[b)FfMUE=o s6ϿYFě3еgګ(mK;n+8h&mp!zH{>}oJc,ĐDP׺ADh0&>tV4t)6 xd/6>7RQnFgVgvA-VYQSo|o΅b gƍ ;EL@i+4ҴW鮱Yc9K-fw/c1r| YܽrYr^4Eh22=:cO|D$ )dG& .pg#`2 g뇕xUwZb߁@n0UkmM񶤐1h50k -|K3#U(n?[] ?Y xx߿Dds6gmZo6SqdER h)ɫI [Py!cDk(]EԺkt]6!gO Ckiϖn+$2JJ 9c}ŁQbdk݋+'MvWM>B\Mw?mfn=+od{#Y1~/lyۘ1cFs#P( m?)bUn*0:[盜L&inn.G*Vy0,K2gY hIlVmAX,F97!^j|-5/G#(DJEk,PHG99V#5D=t!5M4V PB#(BbX;dZEv?ңoru,qM 㐳,ӳT1刘qmrP?λZPRNB ɴK7W :2}揙s KCCӦսhDni -׿Y_L52r9DhOEh s6Z^%=ۅWbvD7ew97I{2"n}#ϚЦwߣb2kÐsu 4 ZN;#OPqDaJ7_Ƹk.v(Ӵ]yQ'<,eM[îf yk# m%;dIgr&.CE4kM^=y?ymQ(`~;. ꪫK*z˫!eAtP,|JAMM Gyw!Ahh0-F$כMg'CF =,k9kc9i=%Z8ϳC| |>Ep22i}|TYuӌЍlIwzN FcoQTZx8c?}#T;vEklٲ]VV/O?4+V`ƌSJh [)m3@M*Ce~V^;%\ݞ={Ϙ3gcN4ؗ`ǏvNb~FrssCU]BUHu7b"O-ӛϷ7Q }zbˏΪPiQhо /ЃT *DF=FQgh4滐L2!g#e޻C=vkB/9dNs߶/:; Q |r_/@&mňQܧWl청  gGx5*WF s:Q_?gWh cΝKSSSHnǎ,[s2tPfΜINN7tEv0J VFQ xhjj22pO"zu/GBb?(J̝%WWU/= IDAT#>s {Y#CY">1~ q~} eF^a78RvjgĻLRiWMW ev aRHl$I]$%юdpT;0t=&-~!YڸC g v2c,Zz]ge$21u&3Z&_$ܵ}VUus6@ņZ5V!;~*g^ٲE!hMl;PԼ)gbh0ʧ !5c[Qf̘AKK xI LNG Uxc8obL1zC݈nـ^*a2Sw.$3J8~IMA^7X_nTh0Jx*B;|q(zգ>]w0j}m/jǻQ;׵q(A 8ߴirɧ)zy {q{bG" &:^uvJyX]/L(~]j:'Rت&F n;8~cK̘_c6+SlA \#h吝-Tx)oFsZxWq윜K@ u5￿]x)oubGj*]2dYyTyq%@ۆ&ʣw\9ˉ3#A7WIBVmڸi?ňR$I:]ѽ02zPZeR(((MU5j+˜؎[zk_iR^d4K.)v$wij.BPI߾q"u{>;,#, =z7 ᄇ>PznM3C G׸j8~|5[nqGI?Oy 3H9MZCbʑPE2j)ge^/F˹{صk AGZE:Q~4v#b@tmd[&ē=}]^Uk?*5󐥿1v 1,A&!/Ggz^#1A.@_KH nly= HHփΤyIV TjkEkR܁ ,Q]Eo3bM;'!-5*GBN_C{lEj]%Cjq *gHE?$LʊK?N Y|9?{g!BѠz677VZmd*mDZ 2M4M>୷֭;S@ !lEeV;g KCmB3U*.y2ޤm{zmS̙]#71Xg ;"c-Q?x#F\yJyN5wQ@3]\o?°^A :s?]6psHQߴ㪕OE8_j9yF;Hg{ 2Đfi=FXU Kћ@̏O5FZ148 Xz45~zxA֭cF%t7@T{%"~v)N$ z5J ?GB+J*nC we {+ FLV޽((z'G߆#Z< $1ЗhyLZ3m f2crYgq_r2>݇pax?zϻ؍*"ҿ $K1#Ʀ ](:'RAT6z]ݻƟH"$Q;msc7o֮hģVlAh+ 6dr|<}ߍnjIj02qھ!HctFHO~lGbB v⵫FCYȾV;&}v>mWqJdά |GՋ/#uHimi/5J:rF}[@Z*QK|CRqw R ) q5bpr 5KBtĈTTzml=!cz-1 vf gU9~rĤ'$W_r饽ٰauuہ^I" ēʵ]})AbkIn8~>FN;،c6vzrwihPGV-4ѣG3f̘Ld :R:5/6G_."m!6 Xi3ꎔU߂5a4"0c} I}x;#Ʃ'#qVrϿ{݋9HAm7!dQMlAV}{ڛ)z.<xz-av˃}W_(((W^\x?4}wvͣ>… M8x F͕W^rt~?^m<>n@- b2JE@$ކ!i;,TItεR;I7*mC刑1̼yhii Cuuc5Z6oޜV=~kP8wa1nsdN*v<@ jm+x999IȒ׈~dD$|&p^;$<=N/HhsH/-Ǩ&Ncg}E~O]sLSR5Tէ>m =t9Z%Qۦ!C׿CcbN8YAFZ+ȾvSfS__ϭ|Qt"7h]byF:q!j,j|&\d|AoeZ^@ߢWōG ]rpf$71Q^oēS68r.6*&%]ԿI`^n>[p_A ?s$;Ad"xIm~_"7n7?d۶|mttE&|dq@O6JAA!'~5G:&Sc|acnI.;9dzRbٲeyw}A:#<sNr4DׄkVbW(g`kiЍIPJ#xb2JaTgiTU}I0YzCcoG#Z$g(-$i'˻IByP444ZE#FGlbĺ#v2Q\x DkcG $sU^;\P~Mn:H3f^6m4$yae'XP.h+t_vF)ABYA#2[1KzfbLVhcQ/O~,{PJc~d1bh# ok@8Շ4Jc|O#AAnNNG6)£<9/RQL׬gϞ Tƾ}iw px=rbQHhdC32(+7"3Ǝ-4!}ȸ&.cG_2ae0'*d_ 64xIE"Rx.u]Ș]whB<^URĚ#"p?ATz~1jiG~7jBy3fחӬלZ(45]-[4FG Gk !tDT]s ‹UPG:?L'kkk#++˖kf#l햴f4CmL[=r{6.RAjR@G3zo0ޛegITa\4~nF \}7}Cx$N|)?xFJ~InAH,PUm$?>Zז6R[×^Z̍7ޢ;1^$QRx/2< $[Ff oÇ+p@ kewtt1w;6PaxT1N1h;mm ;N766ck`QזPYysssƚAטb>1=D?ģJ hG@zѠ<dq3m|فJ\* S/z'2>x_~ 14Jg#gj$܂0~P Ϲb|oL>y+;F]eQX[;jMAbw!?"pD5n9!:>`,W\qbl*kVXI8h,MOոڳ## HImusBWoFѤLER笴#Q?F sկ~ƾ}xᅭB>A=hSa.C ׭H|}$6 ?EX>!j'LÙlˌ1Sx[Xyi#GH2 "O;Hb ]5CۮXòe{Žhv9%"﹓;e~qhZdHT1ΐ J.''Ș`ˣ)F6`a)!2iG1xG#:J?!Hǐ;Z$:GDnhwlZIfffOkg)k<*+L>ٌ2ܕ!]_@ 04=#!*y`?gu~Og!;q#1HO+bّ yvr2HImFNsaa =$`|֭^W#xf>|8k~ĸq_Gbɪ%ծICVi!+툗]P XoNSn¨*\n&?DZ3ld CFFyFQQK¤Ij) Uk$7_@ aXSƍc&R]C;ːDbs# fă擗u+,fz"n^2Nc٠r9,luH=ﯾ*v";;zzeݻws1-ZkƲeʼz/i甒t7Fh9,vq'fPh!}7شi? _O8WX؏Λ-x>xߒԱ# ĢFjVR /w /ߍqz"?!xb#Lb`/g}oxBATeHhG^|q!3gΌzjvqcS!U8x͌XOIIsJڱc˖-cL6~ֱ6*`WSYA1/Ikii5GT|F=JHmDz͑zn0id88+5^E3T3?}曯r=E]3X!;㴂=ڻfJ+/[ov[oŸq8c!7NES]H3VYKh!#u.R*`2 $ݰoKmlfh8qKjrIdEmTg!XSNL.sXhUW#% t"0KG,,\dP}#,ܐ 85[3[$Y^CqyESYQR"uvZ+D1by"cŲ)..v20 G{(͕s˶Sh #Q4/[AR@ClQ=6+u쎎[jvƱ&Zpb7`2nxͱ`_Z'ahHVv'Gf&L]_W4VI9cL *Ca;Ej[LV1EXsql`h(2&nN.c$j8&UžpƓ|p "K0d׮]ر3f$mHYm$G"27E XvʴB cHvC&%VrWܚ\ rsrw [ꚪw 'I_߾};Dh몫J9f n4꜕N:Y`fRe5N>Y v˿ Y"Wnt.T!++˕H$766rJ<ƍ9z(v_|q^/7|3EEE3Jo&;; :>d"eYN`W4)ny |"b Re~Kmx }\,M& a F%+K7J#B;)kT٥Ω;9A kEf:#0o0^935U=*#hlj"'N61Dq." ={v\נ. o>8 n3 ijjʗ6By>*$Jf{(>]M7U̠28kZqw+HHUV1tP&Nt 4={pgxweS^^׾6R6mdE}Bm%QXd,L0nr\UϋxRcM6 ų 6z*L$nTEqjUq>x ֭cʔ) z?G2|p ԩSسg>( ,H8n#e 42 F\{{-^)7<=YMjnSOjydc"dH8Uk4$[?R`5 i&:ĴiӒvS)mԹfJ D>Toa%)eM洂1ҠɠE^@ 槱.Ϲ3+l ##իWӷo_կ&e|A[Qbeĕ0{tqdK=xxF9Y VXql'dN7K6[})_y/B;cmhh`ڵ۷;w2~xˠAbӊBWSSC=Zl:;Hi!|^oA!E5V{`2J#dN0zNbÝ^v ¤x$7;+`d)|ĩ پ};wfƌ477j*rrrKcnK/͛7/DS={6ӟb?lHi:whu)aƇ1^~Nf'0fUb5;;;T'gnIC|1$c(f>;c$3`ŘqْHQ^^NNNf+>(t}>,)g! r3@'5h#fQ+#Jіvvv-*̐E!^*4f,PcUdzv"&n;! +;vիWs eXB0i$&Mĭ͛5jT tCQ`MfrXdIQsvHfcqNyDz1QxQ]]֭[>}z¡+ ]>}xWB/NJ%Y8% 2Jqq vLM܊%$wՙfp2nByJ8VI/v.SZ rZ=f@V/jv].*LiݠU6 w N ,uFIx1L^+W2j(FjHifs,̠&dz񼨝6K5kYf yG#=YqJh#:::x8p'O\ ]dcvvv͗4BVbI-:'FT3&ha; ;ؼ:ɳ[__ڵk袋0`@Rx:7Л6mbL2%YGG6l`䐗G߾})))q9zyzIٍZAM2*a %ܤY222BIi,q(Zeyv ;wdΝ̘1#͛ٹs'YYYѧOʢxbN;fugϩ MtG-xH:ĉ~٭f˖-!wtU`6&l۶m۶2{|z+a`+FfZ<΢ϙ2&l#Ѫ*d@bTFVZgl޼ٳgo;VVn6/_ή]TD@@ `Νl޼x3f CՐ Thvx)l" FD`"6GNnȌH4qw^6mĴib7O:wy~OE4ͮgO<رcя~Ğ={Xv-4 (.. * ZB3n ϔQe&cQc0GN&TTTz={vy,~s:~߅{w&|TF@w uuuTTT*ѣUUU\uU"_PIfD8ڱD8p[UJL*yFm' ٰafԩI 0)enhll^8a)xb,YByyyPXhL2B (--o߾`Ћhsf1jN sqxLD *Xf cرIcqĠwͱcXh˖-?AUUUx^ׅlܸݻpЋ@EEׯ'//|JJJ߿\/24F٪mhOLutt OT-DIQŋ7J#Z{ʕ;v#G0f̘ Xr YYY~y4w\nFFŵ^SZ$I!% tuu5v[g'N 52d|Ao{[nү_T0'dR̖6-Vx'aDuu5۶mc IsW]u?Oͥ-.x<<iݻw裏pB^{5:::’ O<G+Qػw/ 8|lܸjO0N sNtҠmv f:V U+ۗP_$R"cxvیdƴ͌Q)DGCd5rQ*v'fVZ9c+F!AG@%/^Ճ~ש[oQ&@ RS`b=zk!A%xNeaM2Gyv*4kjjbԩa̘4NN ΝKSSS(ٸc-[Ɲw}G0СC<# :4꾬>o<9ŋÚkv6??Ġu>'nڗU]dO4N@jUp>򨯯{EEEq!Z~o ,pUiT؍g? 63ft(u|$##{a~b](3X%{A:*@ 4dp!ckk+V[n԰rJ =h?v|*m]ivijg}vRij3x`@ =$UVVFϞ=mh`'I6Q(DP:tuqӣG_%v>iv Ng@{1^xᅤ ED`YYY۪iV]fuƅ,Qj6["̖`0Ȗ-[8pgv<>!$*=w\̙3ᦛnbܸq]=ܸ 9rׯ< ֭cʔ).#c'777 G3";pHHիWӳgOן)y,X_|ӟ4L 6)TJtttCz袋ϧ窇ke]8E2*͊QNGz֮]ĉO a4C:đ"Tz+Wdĉ\qώ?2*/.gF9sC#J8FU:::BJv&Eܵk3gLjd]< q*$hʊ>onnfTUUK~~>  5X$ʈJ8*h}VcɬY:4:i}tI 紴PQQƍOPSXş:jSvẊ~Hqq1uuu\tE 2$iLkANM[[۷\:::8~8SL"TOŅqL#$~|԰qF<O?tNgRLu:"mO#$E2oK[[!''P[*wX~=\~ŞRtC:q!/`0Ȕ)SBފ:ؼy Peee YA*b81؉NZZZXj#F`ȑa5StC@FHfNjd";;;d kٶm~i(F @l+Ԑh0xۄ8pJ⊸Z> T4B;^t52335jFĀܹUVK^(++@ ߿\RV۬UXGGG) 6lȑ#̚5U_NDs/g̙u])_LHǠO#*mٵkWOwfӦMx^9r$#GuzՋPp4 *=V[[Wf/iF\x饗ų͛<`ԩ',O`ɒ%~>}8>Tj~9!4U<{ԩqL>{wvp]A0 ;*--o߾(--+5k )))k2b h_8 s t]cee%O=T3<#= _uѽ{w:,JKK߿Į]ؾ};3fpܞˊߜyXr%|AXcGLs6it9b%j?M6͛ǙgC<()))~/ɓ]c.͏Oucit9b%}]FyRgx Tѽ{RS[ @j*=\ ꘢͚qr"AxgΜ9ۿ[ҥKٰa=PRYYM# #:.U±kYf yG(..ᦑF!mӰ?nstR׫܀Uұz@ @ff& .⑦Ft<=8o~Ln{8ڷh"=޽{(++cѢE<QO%>#R\\r_c_3flٲWUUzbO!^ObIDAT t3a^z%~_zHPU U&MbٲeybLTWW3u԰W^y%L8񴶶s+|>Z[[YxqJumOYx1}᭷(:4*p7i h})Mo)I#H4҈hU/"٬X"I#)HǠH# [ne\r%]94Nq tiDUwߥgQ^^ޕLE:đFQMVh?,XGƩN#48IqFiH4H#iFiq"mH#4NR\,/IENDB`mpmath-1.1.0/doc/source/plots/spherharm44.py000066400000000000000000000006141340375245600207320ustar00rootroot00000000000000from mpmath import fp # Real part of spherical harmonic Y_(4,4)(theta,phi) def Y(l,m): def g(theta,phi): R = abs(fp.re(fp.spherharm(l,m,theta,phi))) x = R*fp.cos(phi)*fp.sin(theta) y = R*fp.sin(phi)*fp.sin(theta) z = R*fp.cos(theta) return [x,y,z] return g fp.splot(Y(4,4), [0,fp.pi], [0,2*fp.pi], points=300, dpi=45, file="spherharm44.png") mpmath-1.1.0/doc/source/plotting.txt000066400000000000000000000012741340375245600174620ustar00rootroot00000000000000Plotting ======== If `matplotlib `_ is available, the functions ``plot`` and ``cplot`` in mpmath can be used to plot functions respectively as x-y graphs and in the complex plane. Also, ``splot`` can be used to produce 3D surface plots. Function curve plots ----------------------- .. image:: plot.png Output of ``plot([cos, sin], [-4, 4])`` .. autofunction:: mpmath.plot Complex function plots ------------------------- .. image:: cplot.png Output of ``fp.cplot(fp.gamma, points=100000)`` .. autofunction:: mpmath.cplot 3D surface plots ---------------- .. image:: splot.png Output of ``splot`` for the donut example. .. autofunction:: mpmath.splot mpmath-1.1.0/doc/source/references.txt000066400000000000000000000057001340375245600177410ustar00rootroot00000000000000References =================== The following is a non-comprehensive list of works used in the development of mpmath or cited for examples or mathematical definitions used in this documentation. References not listed here can be found in the source code. .. [AbramowitzStegun] M Abramowitz & I Stegun. *Handbook of Mathematical Functions, 9th Ed.*, Tenth Printing, December 1972, with corrections (electronic copy: http://people.math.sfu.ca/~cbm/aands/) .. [Bailey] D H Bailey. "Tanh-Sinh High-Precision Quadrature", http://crd.lbl.gov/~dhbailey/dhbpapers/dhb-tanh-sinh.pdf .. [BenderOrszag] C M Bender & S A Orszag. *Advanced Mathematical Methods for Scientists and Engineers*, Springer 1999 .. [BorweinBailey] J Borwein, D H Bailey & R Girgensohn. *Experimentation in Mathematics - Computational Paths to Discovery*, A K Peters, 2003 .. [BorweinBorwein] J Borwein & P B Borwein. *Pi and the AGM: A Study in Analytic Number Theory and Computational Complexity*, Wiley 1987 .. [BorweinZeta] P Borwein. "An Efficient Algorithm for the Riemann Zeta Function", http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf .. [CabralRosetti] L G Cabral-Rosetti & M A Sanchis-Lozano. "Appell Functions and the Scalar One-Loop Three-point Integrals in Feynman Diagrams". http://arxiv.org/abs/hep-ph/0206081 .. [Carlson] B C Carlson. "Numerical computation of real or complex elliptic integrals". http://arxiv.org/abs/math/9409227v1 .. [Corless] R M Corless et al. "On the Lambert W function", Adv. Comp. Math. 5 (1996) 329-359. http://www.apmaths.uwo.ca/~djeffrey/Offprints/W-adv-cm.pdf .. [DLMF] NIST Digital Library of Mathematical Functions. http://dlmf.nist.gov/ .. [GradshteynRyzhik] I S Gradshteyn & I M Ryzhik, A Jeffrey & D Zwillinger (eds.), *Table of Integrals, Series and Products*, Seventh edition (2007), Elsevier .. [GravesMorris] P R Graves-Morris, D E Roberts & A Salam. "The epsilon algorithm and related topics", *Journal of Computational and Applied Mathematics*, Volume 122, Issue 1-2 (October 2000) .. [MPFR] The MPFR team. "The MPFR Library: Algorithms and Proofs", http://www.mpfr.org/algorithms.pdf .. [Slater] L J Slater. *Generalized Hypergeometric Functions*. Cambridge University Press, 1966 .. [Spouge] J L Spouge. "Computation of the gamma, digamma, and trigamma functions", SIAM J. Numer. Anal. Vol. 31, No. 3, pp. 931-944, June 1994. .. [SrivastavaKarlsson] H M Srivastava & P W Karlsson. *Multiple Gaussian Hypergeometric Series*. Ellis Horwood, 1985. .. [Vidunas] R Vidunas. "Identities between Appell's and hypergeometric functions". http://arxiv.org/abs/0804.0655 .. [Weisstein] E W Weisstein. *MathWorld*. http://mathworld.wolfram.com/ .. [WhittakerWatson] E T Whittaker & G N Watson. *A Course of Modern Analysis*. 4th Ed. 1946 Cambridge University Press .. [Wikipedia] *Wikipedia, the free encyclopedia*. http://en.wikipedia.org/wiki/Main_Page .. [WolframFunctions] Wolfram Research, Inc. *The Wolfram Functions Site*. http://functions.wolfram.com/ mpmath-1.1.0/doc/source/setup.txt000066400000000000000000000137231340375245600167640ustar00rootroot00000000000000Setting up mpmath ================= Download and installation ------------------------- Installer ......... The mpmath setup files can be downloaded from the `Python Package Index `_. Download the source package (available as both .zip and .tar.gz), extract it, open the extracted directory, and run ``python setup.py install`` Using pip ......... Releases are registered on PyPI, so you can install latest release of the Mpmath with pip ``pip install mpmath`` or some specific version with ``pip install mpmath==0.19`` Using setuptools ................ If you have `setuptools `_ installed, you can download and install mpmath in one step by running: ``easy_install mpmath`` or ``python -m easy_install mpmath`` If you have an old version of mpmath installed already, you may have to pass ``easy_install`` the ``-U`` flag to force an upgrade. Debian/Ubuntu ............. Debian and Ubuntu users can install mpmath with ``sudo apt-get install python-mpmath`` See `debian `_ and `ubuntu `_ package information; please verify that you are getting the latest version. OpenSUSE ........ Mpmath is provided in the "Science" repository for all recent versions of `openSUSE `_. To add this repository to the YAST software management tool, see http://en.opensuse.org/SDB:Add_package_repositories Look up http://download.opensuse.org/repositories/science/ for a list of supported OpenSUSE versions and use http://download.opensuse.org/repositories/science/openSUSE_11.1/ (or accordingly for your OpenSUSE version) as the repository URL for YAST. Current development version ........................... The git repository is https://github.com/fredrik-johansson/mpmath Checking that it works ...................... After the setup has completed, you should be able to fire up the interactive Python interpreter and do the following:: >>> from mpmath import * >>> mp.dps = 50 >>> print(mpf(2) ** mpf('0.5')) 1.4142135623730950488016887242096980785696718753769 >>> print(2*pi) 6.2831853071795864769252867665590057683943387987502 *Note: if you have are upgrading mpmath from an earlier version, you may have to manually uninstall the old version or remove the old files.* Using gmpy (optional) --------------------- By default, mpmath uses Python integers internally. If `gmpy `_ version 1.03 or later is installed on your system, mpmath will automatically detect it and transparently use gmpy integers intead. This makes mpmath much faster, especially at high precision (approximately above 100 digits). To verify that mpmath uses gmpy, check the internal variable ``BACKEND`` is not equal to 'python': >>> import mpmath.libmp >>> mpmath.libmp.BACKEND # doctest:+SKIP 'gmpy' The gmpy mode can be disabled by setting the MPMATH_NOGMPY environment variable. Note that the mode cannot be switched during runtime; mpmath must be re-imported for this change to take effect. Running tests ------------- It is recommended that you run mpmath's full set of unit tests to make sure everything works. The `py.test `_ is a required dependence for testing. The tests are located in the ``tests`` subdirectory of the main mpmath directory. They can be run using:: ``py.test --pyargs mpmath`` If any test fails, please send a detailed bug report to the `mpmath issue tracker `_. To run the tests with support for gmpy disabled, set ``MPMATH_NOGMPY`` environment variable. To enable extra diagnostics, use, set ``MPMATH_STRICT`` environment variable. Compiling the documentation --------------------------- If you downloaded the source package, the text source for these documentation pages is included in the ``doc`` directory. The documentation can be compiled to pretty HTML using `Sphinx `_. Go to the ``doc`` directory and run ``python build.py`` You can also test that all the interactive examples in the documentation work by running ``python run_doctest.py`` and by running the individual ``.py`` files in the mpmath source. (The doctests may take several minutes.) Finally, some additional demo scripts are available in the ``demo`` directory included in the source package. Mpmath under Sage ------------------- Mpmath is a standard package in `Sage `_, in version 4.1 or later of Sage. Mpmath is preinstalled a regular Python module, and can be imported as usual within Sage:: ---------------------------------------------------------------------- | Sage Version 4.1, Release Date: 2009-07-09 | | Type notebook() for the GUI, and license() for information. | ---------------------------------------------------------------------- sage: import mpmath sage: mpmath.mp.dps = 50 sage: print mpmath.mpf(2) ** 0.5 1.4142135623730950488016887242096980785696718753769 The mpmath installation under Sage automatically use Sage integers for asymptotically fast arithmetic, so there is no need to install GMPY:: sage: mpmath.libmp.BACKEND 'sage' In Sage, mpmath can alternatively be imported via the interface library ``sage.libs.mpmath.all``. For example:: sage: import sage.libs.mpmath.all as mpmath This module provides a few extra conversion functions, including :func:`call` which permits calling any mpmath function with Sage numbers as input, and getting Sage ``RealNumber`` or ``ComplexNumber`` instances with the appropriate precision back:: sage: w = mpmath.call(mpmath.erf, 2+3*I, prec=100) sage: w -20.829461427614568389103088452 + 8.6873182714701631444280787545*I sage: type(w) sage: w.prec() 100 See the help for ``sage.libs.mpmath.all`` for further information. mpmath-1.1.0/doc/source/splot.png000066400000000000000000000563061340375245600167360ustar00rootroot00000000000000PNG  IHDRhPLTE             "$&(*,.02468:<>   % $) ### %""%$$$&&&!!)##,%%*$$-(((***,,,...&&0((2--3..5//800022233444455666611866:66=88899::::99=<<<>>?@BEHJMPRUY]`bdfhjlnprtvy|~<>E@@@@@BCCCAAEDDDDDGFFFEEJGGNHHHJJJJJNLLLMMONNNMMQPPPPPSRRRRRTTTTVVVXXXXX[ZZZ]]]]]^^^^^^`__d```aacbbbdddfffhhhjjjkkllllnnnppprrrtttvvvxxxyy{zzz|||~~~)CYIDATx^[ @EA~$QH>3Bѷϥ`,,,x ``\Έ1F-'(Gd-t̀8Ok/{_1GM=cc<8=&]qkΑRĨ륈ҤMn.EK ̋lux%$'KyG_ l3 Q\]jRdJ`bW.5b.{pcrI0o,.E F `ٳlj1:PNlN8n/51jޥs:kV +W ]0j4M: Y65NjcP:.\l2`t)d0SC[g U|_aP;[g{՟2`[j)co6dC]SsQaf.\rUD E+;A,DD $A$!\/`!V"ABkM! `J@vv6fVo';l6sTI\>N7Y@oeDWF`+kN'D[#_;_le-ttt(0rJt=& lP󘥜Ngm[FZ-`* r:ˋ>JU*Sgӭ4Xv:2Bꀑ Q#uʜs6pkN{GSt=0(%8V6D!~eYjyYUSj"o`%!KZ`%f ^ *JyN)V/2ϼ"#[,J,[y<`K#-vdaFoq *0Us]`(cS"!+ > oR ,D͇팩*SHƴz xo%B6`({XT+F8aBoe.-$$c( V[4xLR_MRqZ/Ux`ZK=L`r^]6tMqlm4~^AbCJrR\bO/֒Fox. uws& -M`(y&`$z+X g!׭ 0ȩ.qK eO.0a)0ojc7j]='g3?Vcnu'f#G*nwRqܺ .~lDYaF R` awt~\ignʆG7&Xm~>ȶL޵˗ο^Io%YX?ު7&ıMZi`ZaˬJΙ84 Eׇ¿ׯ|XR`"|fȕ,}ioGZ`k􀘂J ġ8#ih=FIM!epkCb866^뵉{>tK:]嫞VʿNP"djj K޴; q)=rǝj\ B7>[O\s}+үz}y+l\ע[ד*w1^ $rZU-/Na\IiA;x ~;]V?߱E]5O|yu&>b wj (=Ml2"%ZLaˊV?P;rAˇ==[` *gWk6_y+J]@+өO+w*ܸOn ԰Zn=DžJ<.ʁp+R.o)j06A*5R ^ -˗Z t]06߁89bߘz5`v&EP  ÿ+5ďl;-|J%߸!:Q_:-V&?MX0 m#:9Jc}S,?vc8p$Lg^u :v~`rK{*L] ?Z(/10)%LjAaA5>AϏ~ Uݬ KNq*Oqoؾsؗ-Iߵ!cl l]Fpl7|Q)I^ PͲ$EꎕMy<]sLMgWko&V:--cb kLdMϹ0ZX6"~ff'٩ʎlA߽ o_E?&+9SJ8̑Fupܑf U#MKY`FEMiK-=,ht|y+@co6˶ F&ԎQ5hԺK .(L%OfG4Bp'@~Ƞ4ďR)z5ӴMĀ}sy5)Ās=Ο@!쨥F43p/@KjcڇܻBztģ8*⇣<kW݋۷VӕϸoLq{H5bK-+Ľ TU?%PeIZe$BhO#HqOk;9^tK9̓@ +d:YRicW'+Vu:@!V?Z8$%/VkBB@ay vP~m&x}-wUb 6`8Yjq7\5 뮎)!iU8L+[Ȏ9v\>%U)F04}ӆ̀?-fp'5؉8G7xg<+;=uãl1$3 "\Q&&q~$s%o`"{-~x;x7% v`֝r&$ߴ wФ4aru-ZPzlf70./}ǷX4;_muJ2!`._)ͬ;QiI+&LUN3aދ:m%I 鞬HcO sP1`9[}XW?}O"_=|ǰyM=ďvg'X :>'*\}ܖ,ϻqCoI6'BOD܊aڍL~>G`%1gx!|tͶ}LJd?+{_VsbeȮxh$=IePG5eB\HS:c?x RB=bĢ [u81 ?/ܟ| o_pū>{/PW s6OݓGbKT-|KaBkɜcVF,ZPY"_ y Po3Ū+C욀R~ǿg/|y: 97?` bz^sŀO>sO"T ]ˌro$M+w=HjNSC}NT1-7r&,w7s+wV>nL s.|{Bu"fhA>6Ҽ/fo 4\ jr]=;'sB%FtbtAz3*_=,pLt1MkdLƲI.E%}]XanXm3S΄^ٲ1j?I D0u=eб+aV5coߜj;EZWa hr܌#_NW3bCa} Pe]h}`"?"d ’mbOMi*ysbnt'K!v U49wzh0ԑet,(KqϝDcw 0jDp#ɫF0B U#Q-X: 4 a}BxN=9a5杙UQN8 b[hzqs S̹{L#F08rZr$:US,#iYL|Dna@7f$]F |nUc|~ykܟvƀo)K ܑd vǸ )ɶCX<j|i$L#O>B*H[-+Pe{i_.\l\7gBkgL}L*`ؠ~p)c \8ct1|{#-ZYz\Ƭ sD uY% huF`GDj=<ޙ DݽDIh! eRNJ$82=4Ʒh1]{4l%{u-Zm>Y"` M0{0gؐfS:Sd$kZ'o\WKel9Nj!-`Jm%_>g[:$ȱX;mk_Hi],Bc טu603FN,8_B-^>Vv]~M.TEʝ-ߑaGI6,c5"~b+]Xݽ;|`ce IwTьvp2%I\dd7U8&BN/v#;\&?,TOt~ `R[?`ct}>?o0q&`u=إgv2:G!N0A{:4Wɢ+Ɍ{UYVQa8bylrLrȹsLhuRG. pO M =%aJۄY}^m'|\KuPdɻa! ;טt4- qym):߹SE.]1"4r4ʳ#6SIJ& %긥 #R}p<Y$eHrS(QKe,7M`6|_LKOx]#YF/&L mp~; Zr2YԨ(Vh(H%:ES41-7::R>)lď 7 ؏s>!bsYmkzUдO sb.=5/A7pj1hTvrƴNhC/cur$8pX-';߉={ OppԐO<WTG% {M:J'*zJZ["JldgIYbVR;x=(^| <撽;yht.Lײ]_XD"TA3[i` Vu+T5r,95rq2FXwz7Pj[r~1F'SaKRkb;b (UV#Ld"$UG=A%6rRt7%u i~=uJ*SO0_+TUD$Y(X4s{`®Br9b% rWRBP3 P$#h98@}X[mL֊S[GW`ZeM x& 3AdQ̮ol[$ W6PIy(ʘ} dNdG9!65Z htl1QEG܃Ʌn+J34Q ;R 3UMn9ߐ%ӥuT%k::\M˻/ܴ!|z-OS 3VD8U_Mbܟ[`)9RMKt$KLjYF`&UIKn#[Ptu&=)Xq&m#bjkL:=wO[ Wv3;9uWSpJ%ؠ9zXB}5:VMMٹ k'vLII fDpsu & ;\#rC}TPYPW+š5:v|&0 <]~Iu!I4V*RrVI"/3%=\wzy5+䳖v С<{iC':CKt<ǚ?%H8ً4ǡ 1$RL*o (1h_6midK])H-64igV>b|5ud\ןD9l n~t2BP$2x0pǥmY:f`!piUEHvʹaFɂ>d]0qa]( Iu+=3Z}b{o)Aia)|+NR#"l+@lFaI +wrWAPTV{IB=:Fm&G;CC-=@`|`}vnn"OQ6):R?Xhcd!R^dp6٤ۣA]0sB Sr!`kz) D Z!^ x-e†՛&mQEO~sӍ/< j`~}nqRWYsXmt A-^sM7*݌%";E|IehAkGؓjR l;=;\Pr~T;sQ^8)+ '6ڄ C Z$R@+Ir% YBf::|bCDAHS?  v5.~kͯ1,^|,#Vѽ|!-$;Xij>]wC|Պhw?Eu4oeL0-z~&6X$4sșC }l3x u.tR9Z!;]16{M{Y%?-{u +~~E>tbXbDyWE(n{q,h)G+6oG CdٌY7WgOLRbw l ;_ΧJ:hWldR~y)XNՑUOiPRZi]' {C)wXAc)&szk^B7> t(I&x݇9Pt.>e&Hg] 7DԈd~]q+c5 Oy-]AB#A;`k":KK6mQ%u'\#v͎SI#׀ٗo @{p0EX0,z5 {ĂwvBJҸqS2b.hR"pd]CGp44EvA#\p`]DE{[w:#>;u 0M$qU *f)F63NIlReT%dtb01=r+dT1C"=*BwMW,J{׶ up/̣S'ilZ!J&`^8`1w2+KP%U5@F&2IFfqn-P/O^$>v17nο8]*I#m BZqw35h/o,ήV?OF` 󉧛=DCSCKp_etR4Ζ ,Bg)V@Oo}&\9PzX9Fvg/@j^=/e< 7B2"`8UK((ڢ߼md0ρLbWC= yD),7Y0\)Jz/-o P[_3zE:pBFa&҅f0`G;9ebŀ_ LL庼3t`WF]77Y2qdMOhEO8 L@lCJ W,eDrB><&}<|.JPI7~{1CeNka"~,1\,]\.۩ ^x1a5DQkW-w uṣeě&mx |w$/m+54pFTI@4x+ 120v@ Ji2k{KTx5TY2k~w` 0}OEMN 5r1#/!;+ d.4息iAߦZE_*,*)OW?w!T8d)pXW4[٤? ?# ~.D sPk@٩G\.lѢ-`Nw!4ioza;7\̉]ޔfKAKTt\L\FRTHŁo(#&rJ[ ///w_Fs,4i[g%Ma ^;zgqmy nkU5sngF$<YRuTCQ2}*@n>-q//.kgN}*dcvyT*=k;Q#ʟWCGPF7#gIN{bK|LAIf)j98ʷ >ԓ4SL(Μ_ƽXKL ӧ8FУcK X[ZQhsȓي^ aH$ `ɵ0o=! ݁F7B'XoKy5= LPѕF ˄mJq/ⵡ)l(_8`+w0J gqdԂ'cFz$\xHec2F ╶E/%G{/c/yӤM9ig\0C)I,cu.tŦ\ 9w=h./o*})x;Dz?5</~HsYĹd9dZ3L\`orH|XB@qWͬ Æx06c4er,_ wJN!vC f%Gﱕ{JhEsMp-5#W 6ǟT//p6,"(<|!two'De}mq&#h{rAр0XYR\Ws]-hU3ձ󕊎3OB%pi=AV#OVA1`c1Uj?n{ܒy2IPW#^]=Gt^RK*^xWBPN4,ҨGL[p" ~@\aON3H&ML |RŌ4/9:V+o(/5rO Q$1G. x8{kq3T[.VxYe=7G7"1`qӈ8plKOs.ihCjӓv1@`Nʄbrx:ߕo_,^) Qd҆JF><&=Xa].U)TMⳡIK_ F -Vy*(E#^+i&(t\o@4fV)$u ŇvrUuu_&=^cAvW`n◗):!{|[L3gZ2 yv@[YY9Ǫ :k6:ulTt2F4 DZcՓ`11X<jz>BʀI;@R*b+lK.,%|ӤFTZpF\oh`u.65^hH>Yů% $V]*g aNb]V0,Ye[zT9#Z2XпiҶ˅XD\n|gΕ "51XқfC {Uh%z*qP M&m_7ppUE iC4xeRab^NiZLWǫ&wq1xP5|*`KjD;:m~KQ ˖U):PgҮ}xkKT+A5܍u>d ȭj(X\|/4iW&Y/Wh yDžH;NPfBNSmg'4<5@ )p)e)CUP5=M'j-Ra dwJ~m מ4vͮXk x/`$<@#Kވ z֙Xnlhmg@ȑrtFvN'*ltL+s9*CCψo~뀟 &Wk=)e3/R{ _(+^*jr]D'@T* AY[3T-XA]DQ_Da;v|k~v=+r̝+np>O_J$[@o cNLюHƫRZeRJS㡴ŲdkT `a{(=zp[97v%x>';RR;$n#!iiV{OGPAZr6wEQ0߳E6ϻ o#Q.19x2|{j_q{gL;{( U=<QSWi#MIPwݗdqlK7)-="CyCǩ> F~DOo dI`";Z(})8axu7]$Se]fVnJYRg|mGyz6~[uIHxʥܧm$.=K *)aJ(D Tu?+P[GЧ6{; /NdJF]I~}v;$mPq`sGfdTXe[H{/!Ctƈ!%&N@u+',M^"w^;E7D@aٔ ?6 c^ -+0CT#mwH#U؎4C^o%7nWw̹y /u!wZƿi Tq|g\-fk^V*ܣVjRV_tc/L ˁBN&JxZGJJyǎ+3!`!_knM^6=;J/9 X~O3t3TNV#PVFcʞֻ\ծhh|Y Qe%[1-8o^Fw0/L`2ra\?a`C)dǻOhOc"]R1^q~i¤`|QU5"d$/C!nҔB]on?ӻhMY^r~Q`yk؁kWf0`\e{,et9W}v1v 4,#6e˩-)/t 0JsO تnnFzM{yK~.6dIg1`&5ㅀ(m佨l">Bʱ?`iv,amy1cĀ=wdӤ̝+`R\>6B|Tԡ/)16dC``, ^弄Z|&m ނ0O 4c})-o[=S %v;-kjNsNlg@ Dh! ( ~ItTSl,dÎw֓ۉw/k7|z{t):f25XYbׅ(acP+μhJ2mjv g ]b6ّo]!x*_ `byD&-`'u9zxSe,CzGlPU_ 96 4_ l4juʉ qEtT8r:'#N|88agaRƵP=H~t%dRMQܬE7 T@ehJPu"a_b|D[v<5t#WĎ#QɉW#0+UۀVC^ 680P ېe%6^;km٤zAާMRѰ45=奛m1^&%ߢu&\#o8i1>F"'. zjKJ2RZ]n }5dzWȰo_L/R֖_v2UH=}k+8N3mpYN>`&~vFMuUIt2Hs3,">'1C@_2j#mf`c gK>ײ6z}hHpz Doj,?ZSr;e[ &3kuY'^3y~ᆳPO=1Y N2=ÏX9@+}|^մeTYJ7V5Xb v1Q'g7r=X޷XQ_F%;r:d O5˔͢[ ˄XX*F)SC߅xͷ G. 7%!;[fE_oIO om#uii2& 9N0lp65 :PUr2SKeQsg("ۂНC|!ۀ[N#'6 &cx`@, [G(C߉[a f dK1 isHVE'^ r H#Nb{HG#B ۱.`X 4,{n5 qիK|صRyʢλ{}}My>Sxd]1W gu*iHk. `JƈZkNjPnųfwwG3cOk78U])SM0j:ޞ#b .0il4f=ۆӄ9CVN6JfNst u>H(7/-9+[/BC}`W@`DLg8 Xs+߱ $b#HHae6Lbhj&+||G=Z%ID>5|)~6 Gq띷akGU8kBZ\JU݃y> cȻ9iqx3~=j0_24ai򎅗%W=`6 mCkSriu O2J9\Z!=Nho60ꇓ|\LXFNABVor5ԡp8Qk-Vv\ MpDz`vQ~ U#=#J a!4@hIi`]6;'Ɉg:լr+Vj+_XZ[F'oGybhw6y)T6 Ma\8c+1 $+ߚ FftPqK> K1,{]3T3wD2kIx. ;] m!5:⹻^~`W ÿs7?䊾"<'$ck~`_t YʂljbN1jsYH&v<_q&؏SSpxɜ O{ӄg|b܊?%.֧8w_ڱZKyVb`P^ -{o(᏾A3~r|&{é³7y~X l w] Yb<5CS%_N7YAq%F:EdK)rA×%TV r&8J ^& p@OQ?w؟W^V!_6m'P(" Hא:'ePN4>>&u5xLE&=ٳN`*`ҝр Տ[(QC\*\bQٮV O&k>Z3;.l7gOHnH%{*g|ow's-`ŗ Emcd$`VXJ7h]Ӝ"Fc99odM% {2f^zGo-.҆QN-|Rj,þT}XH_VR݈oVƆjNA|Չo@`V J77 `j,irUA`\)&p9v9XjxplT~Du?md JzGx:±(~̔6#kP^:-25E%2ZZK*3A/$C~lu ٔz#s?Y4{1X(y+jrI#:Hҫ6B6ULY۰MFJ}w`W f=޺xx?1c#FIPn]Lb^:i3N#D8ZAr0oR8h[8}i Jèë&ȭPaA|-w&iFV D@e}҅JU\ p(g8]ηt ( |8YH}ٍ0@rS4k:- !ʄəժޏ(SH4YЊ3=Q) 580y.xG*5* UI;o$xf)jjU$>TWtĬF-@R& 7؈-];J,4<[_-2Y3fjJhiiDP(6( qqbN?Pǐ`}r1QՊ6(888| ~8e[gȅP QUvD |( bpݍpƉY7֟“;'ip˺3LyCJp@/FS8ڑdr2eg{74?y:o`6'GS ُ< LU+^{g5_œ7pw5uB=ڳWiO&azw 3^+T 'Z$@H>r&X2nH#S+6˰Ġi') $b%|yb'] \6P{I_BZ,[o:̝k9_ƉS}abWWDƈ&`핲Aj8 Rg6bM аƚ-!%!7w@G FPUS+%/ ſGg-ȟ,x@4PBOw`16ټ*/`? &^F]b ͇Mgeui=Ic$`|z) ,\ f<H稆|%uT3xeeGL4DbV<&gzS%!@Ah*gk:`{Sȵ@wH r˫ˏkz9 {ѻ P4tj}z)рׯ&Χ0掚P"+yoWPRڿ 3Mdp A+г N@vPN26Q@F[-ƺBzn"w1D(  +y#f]9prh).$` 59I*)rW\,kSU LJ_\X/.,,1I+ԛ<_q0x JcP n%:^e B QQ@D#`;q8d8 a<34:b>H7眹r^Zr'N=IYYmN@ }mɁDD ʀ:ĠCdh<@ '0V0{ĕ2Z}2lǂſ]tzQ j.(Qh|-\jitբe^ ȥ#,[[~u_d`#C-\R:²y[n"Fvz0}0?[?9Þʦ0m&42jfڂ.w* Cq}_C_CŚP2, "*"TAAq6 v1mKr>]Ky^LO (0v9QfGK)0(z S@y2q (L=a+W(Ad& e;g0 Vo<z> eORbu;Sś]7+H92sTʓ{7K߬,Y ݁%Fp9r|l`m#;Xeo ,.+?".IENDB`mpmath-1.1.0/doc/source/technical.txt000066400000000000000000000357211340375245600175600ustar00rootroot00000000000000Precision and representation issues =================================== Most of the time, using mpmath is simply a matter of setting the desired precision and entering a formula. For verification purposes, a quite (but not always!) reliable technique is to calculate the same thing a second time at a higher precision and verifying that the results agree. To perform more advanced calculations, it is important to have some understanding of how mpmath works internally and what the possible sources of error are. This section gives an overview of arbitrary-precision binary floating-point arithmetic and some concepts from numerical analysis. The following concepts are important to understand: * The main sources of numerical errors are rounding and cancellation, which are due to the use of finite-precision arithmetic, and truncation or approximation errors, which are due to approximating infinite sequences or continuous functions by a finite number of samples. * Errors propagate between calculations. A small error in the input may result in a large error in the output. * Most numerical algorithms for complex problems (e.g. integrals, derivatives) give wrong answers for sufficiently ill-behaved input. Sometimes virtually the only way to get a wrong answer is to design some very contrived input, but at other times the chance of accidentally obtaining a wrong result even for reasonable-looking input is quite high. * Like any complex numerical software, mpmath has implementation bugs. You should be reasonably suspicious about any results computed by mpmath, even those it claims to be able to compute correctly! If possible, verify results analytically, try different algorithms, and cross-compare with other software. Precision, error and tolerance ------------------------------ The following terms are common in this documentation: - *Precision* (or *working precision*) is the precision at which floating-point arithmetic operations are performed. - *Error* is the difference between a computed approximation and the exact result. - *Accuracy* is the inverse of error. - *Tolerance* is the maximum error (or minimum accuracy) desired in a result. Error and accuracy can be measured either directly, or logarithmically in bits or digits. Specifically, if a `\hat y` is an approximation for `y`, then - (Direct) absolute error = `|\hat y - y|` - (Direct) relative error = `|\hat y - y| |y|^{-1}` - (Direct) absolute accuracy = `|\hat y - y|^{-1}` - (Direct) relative accuracy = `|\hat y - y|^{-1} |y|` - (Logarithmic) absolute error = `\log_b |\hat y - y|` - (Logarithmic) relative error = `\log_b |\hat y - y| - \log_b |y|` - (Logarithmic) absolute accuracy = `-\log_b |\hat y - y|` - (Logarithmic) relative accuracy = `-\log_b |\hat y - y| + \log_b |y|` where `b = 2` and `b = 10` for bits and digits respectively. Note that: - The logarithmic error roughly equals the position of the first incorrect bit or digit - The logarithmic accuracy roughly equals the number of correct bits or digits in the result These definitions also hold for complex numbers, using `|a+bi| = \sqrt{a^2+b^2}`. *Full accuracy* means that the accuracy of a result at least equals *prec*-1, i.e. it is correct except possibly for the last bit. Representation of numbers ------------------------- Mpmath uses binary arithmetic. A binary floating-point number is a number of the form `man \times 2^{exp}` where both *man* (the *mantissa*) and *exp* (the *exponent*) are integers. Some examples of floating-point numbers are given in the following table. +--------+----------+----------+ | Number | Mantissa | Exponent | +========+==========+==========+ | 3 | 3 | 0 | +--------+----------+----------+ | 10 | 5 | 1 | +--------+----------+----------+ | -16 | -1 | 4 | +--------+----------+----------+ | 1.25 | 5 | -2 | +--------+----------+----------+ The representation as defined so far is not unique; one can always multiply the mantissa by 2 and subtract 1 from the exponent with no change in the numerical value. In mpmath, numbers are always normalized so that *man* is an odd number, with the exception of zero which is always taken to have *man = exp = 0*. With these conventions, every representable number has a unique representation. (Mpmath does not currently distinguish between positive and negative zero.) Simple mathematical operations are now easy to define. Due to uniqueness, equality testing of two numbers simply amounts to separately checking equality of the mantissas and the exponents. Multiplication of nonzero numbers is straightforward: `(m 2^e) \times (n 2^f) = (m n) \times 2^{e+f}`. Addition is a bit more involved: we first need to multiply the mantissa of one of the operands by a suitable power of 2 to obtain equal exponents. More technically, mpmath represents a floating-point number as a 4-tuple *(sign, man, exp, bc)* where *sign* is 0 or 1 (indicating positive vs negative) and the mantissa is nonnegative; *bc* (*bitcount*) is the size of the absolute value of the mantissa as measured in bits. Though redundant, keeping a separate sign field and explicitly keeping track of the bitcount significantly speeds up arithmetic (the bitcount, especially, is frequently needed but slow to compute from scratch due to the lack of a Python built-in function for the purpose). Contrary to popular belief, floating-point *numbers* do not come with an inherent "small uncertainty", although floating-point *arithmetic* generally is inexact. Every binary floating-point number is an exact rational number. With arbitrary-precision integers used for the mantissa and exponent, floating-point numbers can be added, subtracted and multiplied *exactly*. In particular, integers and integer multiples of 1/2, 1/4, 1/8, 1/16, etc. can be represented, added and multiplied exactly in binary floating-point arithmetic. Floating-point arithmetic is generally approximate because the size of the mantissa must be limited for efficiency reasons. The maximum allowed width (bitcount) of the mantissa is called the precision or *prec* for short. Sums and products of floating-point numbers are exact as long as the absolute value of the mantissa is smaller than `2^{prec}`. As soon as the mantissa becomes larger than this, it is truncated to contain at most *prec* bits (the exponent is incremented accordingly to preserve the magnitude of the number), and this operation introduces a rounding error. Division is also generally inexact; although we can add and multiply exactly by setting the precision high enough, no precision is high enough to represent for example 1/3 exactly (the same obviously applies for roots, trigonometric functions, etc). The special numbers ``+inf``, ``-inf`` and ``nan`` are represented internally by a zero mantissa and a nonzero exponent. Mpmath uses arbitrary precision integers for both the mantissa and the exponent, so numbers can be as large in magnitude as permitted by the computer's memory. Some care may be necessary when working with extremely large numbers. Although standard arithmetic operators are safe, it is for example futile to attempt to compute the exponential function of of `10^{100000}`. Mpmath does not complain when asked to perform such a calculation, but instead chugs away on the problem to the best of its ability, assuming that computer resources are infinite. In the worst case, this will be slow and allocate a huge amount of memory; if entirely impossible Python will at some point raise ``OverflowError: long int too large to convert to int``. For further details on how the arithmetic is implemented, refer to the mpmath source code. The basic arithmetic operations are found in the ``libmp`` directory; many functions there are commented extensively. Decimal issues -------------- Mpmath uses binary arithmetic internally, while most interaction with the user is done via the decimal number system. Translating between binary and decimal numbers is a somewhat subtle matter; many Python novices run into the following "bug" (addressed in the `General Python FAQ `_):: >>> 1.2 - 1.0 0.19999999999999996 Decimal fractions fall into the category of numbers that generally cannot be represented exactly in binary floating-point form. For example, none of the numbers 0.1, 0.01, 0.001 has an exact representation as a binary floating-point number. Although mpmath can approximate decimal fractions with any accuracy, it does not solve this problem for all uses; users who need *exact* decimal fractions should look at the ``decimal`` module in Python's standard library (or perhaps use fractions, which are much faster). With *prec* bits of precision, an arbitrary number can be approximated relatively to within `2^{-prec}`, or within `10^{-dps}` for *dps* decimal digits. The equivalent values for *prec* and *dps* are therefore related proportionally via the factor `C = \log(10)/\log(2)`, or roughly 3.32. For example, the standard (binary) precision in mpmath is 53 bits, which corresponds to a decimal precision of 15.95 digits. More precisely, mpmath uses the following formulas to translate between *prec* and *dps*:: dps(prec) = max(1, int(round(int(prec) / C - 1))) prec(dps) = max(1, int(round((int(dps) + 1) * C))) Note that the dps is set 1 decimal digit lower than the corresponding binary precision. This is done to hide minor rounding errors and artifacts resulting from binary-decimal conversion. As a result, mpmath interprets 53 bits as giving 15 digits of decimal precision, not 16. The *dps* value controls the number of digits to display when printing numbers with :func:`str`, while the decimal precision used by :func:`repr` is set two or three digits higher. For example, with 15 dps we have:: >>> from mpmath import * >>> mp.dps = 15 >>> str(pi) '3.14159265358979' >>> repr(+pi) "mpf('3.1415926535897931')" The extra digits in the output from ``repr`` ensure that ``x == eval(repr(x))`` holds, i.e. that numbers can be converted to strings and back losslessly. It should be noted that precision and accuracy do not always correlate when translating between binary and decimal. As a simple example, the number 0.1 has a decimal precision of 1 digit but is an infinitely accurate representation of 1/10. Conversely, the number `2^{-50}` has a binary representation with 1 bit of precision that is infinitely accurate; the same number can actually be represented exactly as a decimal, but doing so requires 35 significant digits:: 0.00000000000000088817841970012523233890533447265625 All binary floating-point numbers can be represented exactly as decimals (possibly requiring many digits), but the converse is false. Correctness guarantees ---------------------- Basic arithmetic operations (with the ``mp`` context) are always performed with correct rounding. Results that can be represented exactly are guranteed to be exact, and results from single inexact operations are guaranteed to be the best possible rounded values. For higher-level operations, mpmath does not generally guarantee correct rounding. In general, mpmath only guarantees that it will use at least the user-set precision to perform a given calculation. *The user may have to manually set the working precision higher than the desired accuracy for the result, possibly much higher.* Functions for evaluation of transcendental functions, linear algebra operations, numerical integration, etc., usually automatically increase the working precision and use a stricter tolerance to give a correctly rounded result with high probability: for example, at 50 bits the temporary precision might be set to 70 bits and the tolerance might be set to 60 bits. It can often be assumed that such functions return values that have full accuracy, given inputs that are exact (or sufficiently precise approximations of exact values), but the user must exercise judgement about whether to trust mpmath. The level of rigor in mpmath covers the entire spectrum from "always correct by design" through "nearly always correct" and "handling the most common errors" to "just computing blindly and hoping for the best". Of course, a long-term development goal is to successively increase the rigor where possible. The following list might give an idea of the current state. Operations that are correctly rounded: * Addition, subtraction and multiplication of real and complex numbers. * Division and square roots of real numbers. * Powers of real numbers, assuming sufficiently small integer exponents (huge powers are rounded in the right direction, but possibly farther than necessary). * Conversion from decimal to binary, for reasonably sized numbers (roughly between `10^{-100}` and `10^{100}`). * Typically, transcendental functions for exact input-output pairs. Operations that should be fully accurate (however, the current implementation may be based on a heuristic error analysis): * Radix conversion (large or small numbers). * Mathematical constants like `\pi`. * Both real and imaginary parts of exp, cos, sin, cosh, sinh, log. * Other elementary functions (the largest of the real and imaginary part). * The gamma and log-gamma functions (the largest of the real and the imaginary part; both, when close to real axis). * Some functions based on hypergeometric series (the largest of the real and imaginary part). Correctness of root-finding, numerical integration, etc. largely depends on the well-behavedness of the input functions. Specific limitations are sometimes noted in the respective sections of the documentation. Double precision emulation -------------------------- On most systems, Python's ``float`` type represents an IEEE 754 *double precision* number, with a precision of 53 bits and rounding-to-nearest. With default precision (``mp.prec = 53``), the mpmath ``mpf`` type roughly emulates the behavior of the ``float`` type. Sources of incompatibility include the following: * In hardware floating-point arithmetic, the size of the exponent is restricted to a fixed range: regular Python floats have a range between roughly `10^{-300}` and `10^{300}`. Mpmath does not emulate overflow or underflow when exponents fall outside this range. * On some systems, Python uses 80-bit (extended double) registers for floating-point operations. Due to double rounding, this makes the ``float`` type less accurate. This problem is only known to occur with Python versions compiled with GCC on 32-bit systems. * Machine floats very close to the exponent limit round subnormally, meaning that they lose accuracy (Python may raise an exception instead of rounding a ``float`` subnormally). * Mpmath is able to produce more accurate results for transcendental functions. Further reading --------------- There are many excellent textbooks on numerical analysis and floating-point arithmetic. Some good web resources are: * `David Goldberg, What Every Computer Scientist Should Know About Floating-Point Arithmetic `_ * `The Wikipedia article about numerical analysis `_ mpmath-1.1.0/epydoc.conf000066400000000000000000000105721340375245600151470ustar00rootroot00000000000000[epydoc] # Epydoc section marker (required by ConfigParser) # The list of objects to document. Objects can be named using # dotted names, module filenames, or package directory names. # Alases for this option include "objects" and "values". modules: mpmath # The type of output that should be generated. Should be one # of: html, text, latex, dvi, ps, pdf. output: html # The path to the output directory. May be relative or absolute. target: doc_api # An integer indicating how verbose epydoc should be. The default # value is 0; negative values will supress warnings and errors; # positive values will give more verbose output. verbosity: 0 # A boolean value indicating that Epydoc should show a tracaback # in case of unexpected error. By default don't show tracebacks debug: 0 # If True, don't try to use colors or cursor control when doing # textual output. The default False assumes a rich text prompt simple-term: 0 ### Generation options # The default markup language for docstrings, for modules that do # not define __docformat__. Defaults to epytext. docformat: restructuredtext # Whether or not parsing should be used to examine objects. parse: yes # Whether or not introspection should be used to examine objects. introspect: yes # Don't examine in any way the modules whose dotted name match this # regular expression pattern. #exclude: # Don't perform introspection on the modules whose dotted name match this # regular expression pattern. #exclude-introspect # Don't perform parsing on the modules whose dotted name match this # regular expression pattern. #exclude-parse # The format for showing inheritance objects. # It should be one of: 'grouped', 'listed', 'included'. inheritance: listed # Whether or not to inclue private variables. (Even if included, # private variables will be hidden by default.) private: yes # Whether or not to list each module's imports. imports: no # Whether or not to include syntax highlighted source code in # the output (HTML only). sourcecode: yes # Whether or not to includea a page with Epydoc log, containing # effective option at the time of generation and the reported logs. include-log: no ### Output options # The documented project's name. name: Mpmath - Python library for arbitrary-precision floating-point arithmetic # The CSS stylesheet for HTML output. Can be the name of a builtin # stylesheet, or the name of a file. css: white # The documented project's URL. url: http://mpmath.googlecode.com/ # HTML code for the project link in the navigation bar. If left # unspecified, the project link will be generated based on the # project's name and URL. #link: My Cool Project # The "top" page for the documentation. Can be a URL, the name # of a module or class, or one of the special names "trees.html", # "indices.html", or "help.html" #top: os.path # An alternative help file. The named file should contain the # body of an HTML file; navigation bars will be added to it. #help: my_helpfile.html # Whether or not to include a frames-based table of contents. frames: yes # Whether each class should be listed in its own section when # generating LaTeX or PDF output. separate-classes: no ### API linking options # Define a new API document. A new interpreted text role # will be created #external-api: epydoc # Use the records in this file to resolve objects in the API named NAME. #external-api-file: epydoc:api-objects.txt # Use this URL prefix to configure the string returned for external API. #external-api-root: epydoc:http://epydoc.sourceforge.net/api ### Graph options # The list of graph types that should be automatically included # in the output. Graphs are generated using the Graphviz "dot" # executable. Graph types include: "classtree", "callgraph", # "umlclass". Use "all" to include all graph types graph: all # The path to the Graphviz "dot" executable, used to generate # graphs. dotpath: /usr/bin/dot # The name of one or more pstat files (generated by the profile # or hotshot module). These are used to generate call graphs. pstat: ./mpmath_profile.out # Specify the font used to generate Graphviz graphs. # (e.g., helvetica or times). graph-font: Courier # Specify the font size used to generate Graphviz graphs. graph-font-size: 10 ### Return value options # The condition upon which Epydoc should exit with a non-zero # exit status. Possible values are error, warning, docstring_warning #fail-on: error mpmath-1.1.0/mpmath/000077500000000000000000000000001340375245600142765ustar00rootroot00000000000000mpmath-1.1.0/mpmath/__init__.py000066400000000000000000000206301340375245600164100ustar00rootroot00000000000000__version__ = '1.1.0' from .usertools import monitor, timing from .ctx_fp import FPContext from .ctx_mp import MPContext from .ctx_iv import MPIntervalContext fp = FPContext() mp = MPContext() iv = MPIntervalContext() fp._mp = mp mp._mp = mp iv._mp = mp mp._fp = fp fp._fp = fp mp._iv = iv fp._iv = iv iv._iv = iv # XXX: extremely bad pickle hack from . import ctx_mp as _ctx_mp _ctx_mp._mpf_module.mpf = mp.mpf _ctx_mp._mpf_module.mpc = mp.mpc make_mpf = mp.make_mpf make_mpc = mp.make_mpc extraprec = mp.extraprec extradps = mp.extradps workprec = mp.workprec workdps = mp.workdps autoprec = mp.autoprec maxcalls = mp.maxcalls memoize = mp.memoize mag = mp.mag bernfrac = mp.bernfrac qfrom = mp.qfrom mfrom = mp.mfrom kfrom = mp.kfrom taufrom = mp.taufrom qbarfrom = mp.qbarfrom ellipfun = mp.ellipfun jtheta = mp.jtheta kleinj = mp.kleinj qp = mp.qp qhyper = mp.qhyper qgamma = mp.qgamma qfac = mp.qfac nint_distance = mp.nint_distance plot = mp.plot cplot = mp.cplot splot = mp.splot odefun = mp.odefun jacobian = mp.jacobian findroot = mp.findroot multiplicity = mp.multiplicity isinf = mp.isinf isnan = mp.isnan isnormal = mp.isnormal isint = mp.isint isfinite = mp.isfinite almosteq = mp.almosteq nan = mp.nan rand = mp.rand absmin = mp.absmin absmax = mp.absmax fraction = mp.fraction linspace = mp.linspace arange = mp.arange mpmathify = convert = mp.convert mpc = mp.mpc mpi = iv._mpi nstr = mp.nstr nprint = mp.nprint chop = mp.chop fneg = mp.fneg fadd = mp.fadd fsub = mp.fsub fmul = mp.fmul fdiv = mp.fdiv fprod = mp.fprod quad = mp.quad quadgl = mp.quadgl quadts = mp.quadts quadosc = mp.quadosc invertlaplace = mp.invertlaplace invlaptalbot = mp.invlaptalbot invlapstehfest = mp.invlapstehfest invlapdehoog = mp.invlapdehoog pslq = mp.pslq identify = mp.identify findpoly = mp.findpoly richardson = mp.richardson shanks = mp.shanks levin = mp.levin cohen_alt = mp.cohen_alt nsum = mp.nsum nprod = mp.nprod difference = mp.difference diff = mp.diff diffs = mp.diffs diffs_prod = mp.diffs_prod diffs_exp = mp.diffs_exp diffun = mp.diffun differint = mp.differint taylor = mp.taylor pade = mp.pade polyval = mp.polyval polyroots = mp.polyroots fourier = mp.fourier fourierval = mp.fourierval sumem = mp.sumem sumap = mp.sumap chebyfit = mp.chebyfit limit = mp.limit matrix = mp.matrix eye = mp.eye diag = mp.diag zeros = mp.zeros ones = mp.ones hilbert = mp.hilbert randmatrix = mp.randmatrix swap_row = mp.swap_row extend = mp.extend norm = mp.norm mnorm = mp.mnorm lu_solve = mp.lu_solve lu = mp.lu qr = mp.qr unitvector = mp.unitvector inverse = mp.inverse residual = mp.residual qr_solve = mp.qr_solve cholesky = mp.cholesky cholesky_solve = mp.cholesky_solve det = mp.det cond = mp.cond hessenberg = mp.hessenberg schur = mp.schur eig = mp.eig eig_sort = mp.eig_sort eigsy = mp.eigsy eighe = mp.eighe eigh = mp.eigh svd_r = mp.svd_r svd_c = mp.svd_c svd = mp.svd gauss_quadrature = mp.gauss_quadrature expm = mp.expm sqrtm = mp.sqrtm powm = mp.powm logm = mp.logm sinm = mp.sinm cosm = mp.cosm mpf = mp.mpf j = mp.j exp = mp.exp expj = mp.expj expjpi = mp.expjpi ln = mp.ln im = mp.im re = mp.re inf = mp.inf ninf = mp.ninf sign = mp.sign eps = mp.eps pi = mp.pi ln2 = mp.ln2 ln10 = mp.ln10 phi = mp.phi e = mp.e euler = mp.euler catalan = mp.catalan khinchin = mp.khinchin glaisher = mp.glaisher apery = mp.apery degree = mp.degree twinprime = mp.twinprime mertens = mp.mertens ldexp = mp.ldexp frexp = mp.frexp fsum = mp.fsum fdot = mp.fdot sqrt = mp.sqrt cbrt = mp.cbrt exp = mp.exp ln = mp.ln log = mp.log log10 = mp.log10 power = mp.power cos = mp.cos sin = mp.sin tan = mp.tan cosh = mp.cosh sinh = mp.sinh tanh = mp.tanh acos = mp.acos asin = mp.asin atan = mp.atan asinh = mp.asinh acosh = mp.acosh atanh = mp.atanh sec = mp.sec csc = mp.csc cot = mp.cot sech = mp.sech csch = mp.csch coth = mp.coth asec = mp.asec acsc = mp.acsc acot = mp.acot asech = mp.asech acsch = mp.acsch acoth = mp.acoth cospi = mp.cospi sinpi = mp.sinpi sinc = mp.sinc sincpi = mp.sincpi cos_sin = mp.cos_sin cospi_sinpi = mp.cospi_sinpi fabs = mp.fabs re = mp.re im = mp.im conj = mp.conj floor = mp.floor ceil = mp.ceil nint = mp.nint frac = mp.frac root = mp.root nthroot = mp.nthroot hypot = mp.hypot fmod = mp.fmod ldexp = mp.ldexp frexp = mp.frexp sign = mp.sign arg = mp.arg phase = mp.phase polar = mp.polar rect = mp.rect degrees = mp.degrees radians = mp.radians atan2 = mp.atan2 fib = mp.fib fibonacci = mp.fibonacci lambertw = mp.lambertw zeta = mp.zeta altzeta = mp.altzeta gamma = mp.gamma rgamma = mp.rgamma factorial = mp.factorial fac = mp.fac fac2 = mp.fac2 beta = mp.beta betainc = mp.betainc psi = mp.psi #psi0 = mp.psi0 #psi1 = mp.psi1 #psi2 = mp.psi2 #psi3 = mp.psi3 polygamma = mp.polygamma digamma = mp.digamma #trigamma = mp.trigamma #tetragamma = mp.tetragamma #pentagamma = mp.pentagamma harmonic = mp.harmonic bernoulli = mp.bernoulli bernfrac = mp.bernfrac stieltjes = mp.stieltjes hurwitz = mp.hurwitz dirichlet = mp.dirichlet bernpoly = mp.bernpoly eulerpoly = mp.eulerpoly eulernum = mp.eulernum polylog = mp.polylog clsin = mp.clsin clcos = mp.clcos gammainc = mp.gammainc gammaprod = mp.gammaprod binomial = mp.binomial rf = mp.rf ff = mp.ff hyper = mp.hyper hyp0f1 = mp.hyp0f1 hyp1f1 = mp.hyp1f1 hyp1f2 = mp.hyp1f2 hyp2f1 = mp.hyp2f1 hyp2f2 = mp.hyp2f2 hyp2f0 = mp.hyp2f0 hyp2f3 = mp.hyp2f3 hyp3f2 = mp.hyp3f2 hyperu = mp.hyperu hypercomb = mp.hypercomb meijerg = mp.meijerg appellf1 = mp.appellf1 appellf2 = mp.appellf2 appellf3 = mp.appellf3 appellf4 = mp.appellf4 hyper2d = mp.hyper2d bihyper = mp.bihyper erf = mp.erf erfc = mp.erfc erfi = mp.erfi erfinv = mp.erfinv npdf = mp.npdf ncdf = mp.ncdf expint = mp.expint e1 = mp.e1 ei = mp.ei li = mp.li ci = mp.ci si = mp.si chi = mp.chi shi = mp.shi fresnels = mp.fresnels fresnelc = mp.fresnelc airyai = mp.airyai airybi = mp.airybi airyaizero = mp.airyaizero airybizero = mp.airybizero scorergi = mp.scorergi scorerhi = mp.scorerhi ellipk = mp.ellipk ellipe = mp.ellipe ellipf = mp.ellipf ellippi = mp.ellippi elliprc = mp.elliprc elliprj = mp.elliprj elliprf = mp.elliprf elliprd = mp.elliprd elliprg = mp.elliprg agm = mp.agm jacobi = mp.jacobi chebyt = mp.chebyt chebyu = mp.chebyu legendre = mp.legendre legenp = mp.legenp legenq = mp.legenq hermite = mp.hermite pcfd = mp.pcfd pcfu = mp.pcfu pcfv = mp.pcfv pcfw = mp.pcfw gegenbauer = mp.gegenbauer laguerre = mp.laguerre spherharm = mp.spherharm besselj = mp.besselj j0 = mp.j0 j1 = mp.j1 besseli = mp.besseli bessely = mp.bessely besselk = mp.besselk besseljzero = mp.besseljzero besselyzero = mp.besselyzero hankel1 = mp.hankel1 hankel2 = mp.hankel2 struveh = mp.struveh struvel = mp.struvel angerj = mp.angerj webere = mp.webere lommels1 = mp.lommels1 lommels2 = mp.lommels2 whitm = mp.whitm whitw = mp.whitw ber = mp.ber bei = mp.bei ker = mp.ker kei = mp.kei coulombc = mp.coulombc coulombf = mp.coulombf coulombg = mp.coulombg barnesg = mp.barnesg superfac = mp.superfac hyperfac = mp.hyperfac loggamma = mp.loggamma siegeltheta = mp.siegeltheta siegelz = mp.siegelz grampoint = mp.grampoint zetazero = mp.zetazero riemannr = mp.riemannr primepi = mp.primepi primepi2 = mp.primepi2 primezeta = mp.primezeta bell = mp.bell polyexp = mp.polyexp expm1 = mp.expm1 log1p = mp.log1p powm1 = mp.powm1 unitroots = mp.unitroots cyclotomic = mp.cyclotomic mangoldt = mp.mangoldt secondzeta = mp.secondzeta nzeros = mp.nzeros backlunds = mp.backlunds lerchphi = mp.lerchphi stirling1 = mp.stirling1 stirling2 = mp.stirling2 # be careful when changing this name, don't use test*! def runtests(): """ Run all mpmath tests and print output. """ import os.path from inspect import getsourcefile from .tests import runtests as tests testdir = os.path.dirname(os.path.abspath(getsourcefile(tests))) importdir = os.path.abspath(testdir + '/../..') tests.testit(importdir, testdir) def doctests(filter=[]): import sys from timeit import default_timer as clock for i, arg in enumerate(sys.argv): if '__init__.py' in arg: filter = [sn for sn in sys.argv[i+1:] if not sn.startswith("-")] break import doctest globs = globals().copy() for obj in globs: #sorted(globs.keys()): if filter: if not sum([pat in obj for pat in filter]): continue sys.stdout.write(str(obj) + " ") sys.stdout.flush() t1 = clock() doctest.run_docstring_examples(globs[obj], {}, verbose=("-v" in sys.argv)) t2 = clock() print(round(t2-t1, 3)) if __name__ == '__main__': doctests() mpmath-1.1.0/mpmath/calculus/000077500000000000000000000000001340375245600161115ustar00rootroot00000000000000mpmath-1.1.0/mpmath/calculus/__init__.py000066400000000000000000000002421340375245600202200ustar00rootroot00000000000000from . import calculus # XXX: hack to set methods from . import approximation from . import differentiation from . import extrapolation from . import polynomials mpmath-1.1.0/mpmath/calculus/approximation.py000066400000000000000000000211611340375245600213560ustar00rootroot00000000000000from ..libmp.backend import xrange from .calculus import defun #----------------------------------------------------------------------------# # Approximation methods # #----------------------------------------------------------------------------# # The Chebyshev approximation formula is given at: # http://mathworld.wolfram.com/ChebyshevApproximationFormula.html # The only major changes in the following code is that we return the # expanded polynomial coefficients instead of Chebyshev coefficients, # and that we automatically transform [a,b] -> [-1,1] and back # for convenience. # Coefficient in Chebyshev approximation def chebcoeff(ctx,f,a,b,j,N): s = ctx.mpf(0) h = ctx.mpf(0.5) for k in range(1, N+1): t = ctx.cospi((k-h)/N) s += f(t*(b-a)*h + (b+a)*h) * ctx.cospi(j*(k-h)/N) return 2*s/N # Generate Chebyshev polynomials T_n(ax+b) in expanded form def chebT(ctx, a=1, b=0): Tb = [1] yield Tb Ta = [b, a] while 1: yield Ta # Recurrence: T[n+1](ax+b) = 2*(ax+b)*T[n](ax+b) - T[n-1](ax+b) Tmp = [0] + [2*a*t for t in Ta] for i, c in enumerate(Ta): Tmp[i] += 2*b*c for i, c in enumerate(Tb): Tmp[i] -= c Ta, Tb = Tmp, Ta @defun def chebyfit(ctx, f, interval, N, error=False): r""" Computes a polynomial of degree `N-1` that approximates the given function `f` on the interval `[a, b]`. With ``error=True``, :func:`~mpmath.chebyfit` also returns an accurate estimate of the maximum absolute error; that is, the maximum value of `|f(x) - P(x)|` for `x \in [a, b]`. :func:`~mpmath.chebyfit` uses the Chebyshev approximation formula, which gives a nearly optimal solution: that is, the maximum error of the approximating polynomial is very close to the smallest possible for any polynomial of the same degree. Chebyshev approximation is very useful if one needs repeated evaluation of an expensive function, such as function defined implicitly by an integral or a differential equation. (For example, it could be used to turn a slow mpmath function into a fast machine-precision version of the same.) **Examples** Here we use :func:`~mpmath.chebyfit` to generate a low-degree approximation of `f(x) = \cos(x)`, valid on the interval `[1, 2]`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> poly, err = chebyfit(cos, [1, 2], 5, error=True) >>> nprint(poly) [0.00291682, 0.146166, -0.732491, 0.174141, 0.949553] >>> nprint(err, 12) 1.61351758081e-5 The polynomial can be evaluated using ``polyval``:: >>> nprint(polyval(poly, 1.6), 12) -0.0291858904138 >>> nprint(cos(1.6), 12) -0.0291995223013 Sampling the true error at 1000 points shows that the error estimate generated by ``chebyfit`` is remarkably good:: >>> error = lambda x: abs(cos(x) - polyval(poly, x)) >>> nprint(max([error(1+n/1000.) for n in range(1000)]), 12) 1.61349954245e-5 **Choice of degree** The degree `N` can be set arbitrarily high, to obtain an arbitrarily good approximation. As a rule of thumb, an `N`-term Chebyshev approximation is good to `N/(b-a)` decimal places on a unit interval (although this depends on how well-behaved `f` is). The cost grows accordingly: ``chebyfit`` evaluates the function `(N^2)/2` times to compute the coefficients and an additional `N` times to estimate the error. **Possible issues** One should be careful to use a sufficiently high working precision both when calling ``chebyfit`` and when evaluating the resulting polynomial, as the polynomial is sometimes ill-conditioned. It is for example difficult to reach 15-digit accuracy when evaluating the polynomial using machine precision floats, no matter the theoretical accuracy of the polynomial. (The option to return the coefficients in Chebyshev form should be made available in the future.) It is important to note the Chebyshev approximation works poorly if `f` is not smooth. A function containing singularities, rapid oscillation, etc can be approximated more effectively by multiplying it by a weight function that cancels out the nonsmooth features, or by dividing the interval into several segments. """ a, b = ctx._as_points(interval) orig = ctx.prec try: ctx.prec = orig + int(N**0.5) + 20 c = [chebcoeff(ctx,f,a,b,k,N) for k in range(N)] d = [ctx.zero] * N d[0] = -c[0]/2 h = ctx.mpf(0.5) T = chebT(ctx, ctx.mpf(2)/(b-a), ctx.mpf(-1)*(b+a)/(b-a)) for (k, Tk) in zip(range(N), T): for i in range(len(Tk)): d[i] += c[k]*Tk[i] d = d[::-1] # Estimate maximum error err = ctx.zero for k in range(N): x = ctx.cos(ctx.pi*k/N) * (b-a)*h + (b+a)*h err = max(err, abs(f(x) - ctx.polyval(d, x))) finally: ctx.prec = orig if error: return d, +err else: return d @defun def fourier(ctx, f, interval, N): r""" Computes the Fourier series of degree `N` of the given function on the interval `[a, b]`. More precisely, :func:`~mpmath.fourier` returns two lists `(c, s)` of coefficients (the cosine series and sine series, respectively), such that .. math :: f(x) \sim \sum_{k=0}^N c_k \cos(k m x) + s_k \sin(k m x) where `m = 2 \pi / (b-a)`. Note that many texts define the first coefficient as `2 c_0` instead of `c_0`. The easiest way to evaluate the computed series correctly is to pass it to :func:`~mpmath.fourierval`. **Examples** The function `f(x) = x` has a simple Fourier series on the standard interval `[-\pi, \pi]`. The cosine coefficients are all zero (because the function has odd symmetry), and the sine coefficients are rational numbers:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> c, s = fourier(lambda x: x, [-pi, pi], 5) >>> nprint(c) [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] >>> nprint(s) [0.0, 2.0, -1.0, 0.666667, -0.5, 0.4] This computes a Fourier series of a nonsymmetric function on a nonstandard interval:: >>> I = [-1, 1.5] >>> f = lambda x: x**2 - 4*x + 1 >>> cs = fourier(f, I, 4) >>> nprint(cs[0]) [0.583333, 1.12479, -1.27552, 0.904708, -0.441296] >>> nprint(cs[1]) [0.0, -2.6255, 0.580905, 0.219974, -0.540057] It is instructive to plot a function along with its truncated Fourier series:: >>> plot([f, lambda x: fourierval(cs, I, x)], I) #doctest: +SKIP Fourier series generally converge slowly (and may not converge pointwise). For example, if `f(x) = \cosh(x)`, a 10-term Fourier series gives an `L^2` error corresponding to 2-digit accuracy:: >>> I = [-1, 1] >>> cs = fourier(cosh, I, 9) >>> g = lambda x: (cosh(x) - fourierval(cs, I, x))**2 >>> nprint(sqrt(quad(g, I))) 0.00467963 :func:`~mpmath.fourier` uses numerical quadrature. For nonsmooth functions, the accuracy (and speed) can be improved by including all singular points in the interval specification:: >>> nprint(fourier(abs, [-1, 1], 0), 10) ([0.5000441648], [0.0]) >>> nprint(fourier(abs, [-1, 0, 1], 0), 10) ([0.5], [0.0]) """ interval = ctx._as_points(interval) a = interval[0] b = interval[-1] L = b-a cos_series = [] sin_series = [] cutoff = ctx.eps*10 for n in xrange(N+1): m = 2*n*ctx.pi/L an = 2*ctx.quadgl(lambda t: f(t)*ctx.cos(m*t), interval)/L bn = 2*ctx.quadgl(lambda t: f(t)*ctx.sin(m*t), interval)/L if n == 0: an /= 2 if abs(an) < cutoff: an = ctx.zero if abs(bn) < cutoff: bn = ctx.zero cos_series.append(an) sin_series.append(bn) return cos_series, sin_series @defun def fourierval(ctx, series, interval, x): """ Evaluates a Fourier series (in the format computed by by :func:`~mpmath.fourier` for the given interval) at the point `x`. The series should be a pair `(c, s)` where `c` is the cosine series and `s` is the sine series. The two lists need not have the same length. """ cs, ss = series ab = ctx._as_points(interval) a = interval[0] b = interval[-1] m = 2*ctx.pi/(ab[-1]-ab[0]) s = ctx.zero s += ctx.fsum(cs[n]*ctx.cos(m*n*x) for n in xrange(len(cs)) if cs[n]) s += ctx.fsum(ss[n]*ctx.sin(m*n*x) for n in xrange(len(ss)) if ss[n]) return s mpmath-1.1.0/mpmath/calculus/calculus.py000066400000000000000000000001431340375245600202740ustar00rootroot00000000000000class CalculusMethods(object): pass def defun(f): setattr(CalculusMethods, f.__name__, f) mpmath-1.1.0/mpmath/calculus/differentiation.py000066400000000000000000000474021340375245600216440ustar00rootroot00000000000000from ..libmp.backend import xrange from .calculus import defun try: iteritems = dict.iteritems except AttributeError: iteritems = dict.items #----------------------------------------------------------------------------# # Differentiation # #----------------------------------------------------------------------------# @defun def difference(ctx, s, n): r""" Given a sequence `(s_k)` containing at least `n+1` items, returns the `n`-th forward difference, .. math :: \Delta^n = \sum_{k=0}^{\infty} (-1)^{k+n} {n \choose k} s_k. """ n = int(n) d = ctx.zero b = (-1) ** (n & 1) for k in xrange(n+1): d += b * s[k] b = (b * (k-n)) // (k+1) return d def hsteps(ctx, f, x, n, prec, **options): singular = options.get('singular') addprec = options.get('addprec', 10) direction = options.get('direction', 0) workprec = (prec+2*addprec) * (n+1) orig = ctx.prec try: ctx.prec = workprec h = options.get('h') if h is None: if options.get('relative'): hextramag = int(ctx.mag(x)) else: hextramag = 0 h = ctx.ldexp(1, -prec-addprec-hextramag) else: h = ctx.convert(h) # Directed: steps x, x+h, ... x+n*h direction = options.get('direction', 0) if direction: h *= ctx.sign(direction) steps = xrange(n+1) norm = h # Central: steps x-n*h, x-(n-2)*h ..., x, ..., x+(n-2)*h, x+n*h else: steps = xrange(-n, n+1, 2) norm = (2*h) # Perturb if singular: x += 0.5*h values = [f(x+k*h) for k in steps] return values, norm, workprec finally: ctx.prec = orig @defun def diff(ctx, f, x, n=1, **options): r""" Numerically computes the derivative of `f`, `f'(x)`, or generally for an integer `n \ge 0`, the `n`-th derivative `f^{(n)}(x)`. A few basic examples are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> diff(lambda x: x**2 + x, 1.0) 3.0 >>> diff(lambda x: x**2 + x, 1.0, 2) 2.0 >>> diff(lambda x: x**2 + x, 1.0, 3) 0.0 >>> nprint([diff(exp, 3, n) for n in range(5)]) # exp'(x) = exp(x) [20.0855, 20.0855, 20.0855, 20.0855, 20.0855] Even more generally, given a tuple of arguments `(x_1, \ldots, x_k)` and order `(n_1, \ldots, n_k)`, the partial derivative `f^{(n_1,\ldots,n_k)}(x_1,\ldots,x_k)` is evaluated. For example:: >>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (0,1)) 2.75 >>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (1,1)) 3.0 **Options** The following optional keyword arguments are recognized: ``method`` Supported methods are ``'step'`` or ``'quad'``: derivatives may be computed using either a finite difference with a small step size `h` (default), or numerical quadrature. ``direction`` Direction of finite difference: can be -1 for a left difference, 0 for a central difference (default), or +1 for a right difference; more generally can be any complex number. ``addprec`` Extra precision for `h` used to account for the function's sensitivity to perturbations (default = 10). ``relative`` Choose `h` relative to the magnitude of `x`, rather than an absolute value; useful for large or tiny `x` (default = False). ``h`` As an alternative to ``addprec`` and ``relative``, manually select the step size `h`. ``singular`` If True, evaluation exactly at the point `x` is avoided; this is useful for differentiating functions with removable singularities. Default = False. ``radius`` Radius of integration contour (with ``method = 'quad'``). Default = 0.25. A larger radius typically is faster and more accurate, but it must be chosen so that `f` has no singularities within the radius from the evaluation point. A finite difference requires `n+1` function evaluations and must be performed at `(n+1)` times the target precision. Accordingly, `f` must support fast evaluation at high precision. With integration, a larger number of function evaluations is required, but not much extra precision is required. For high order derivatives, this method may thus be faster if f is very expensive to evaluate at high precision. **Further examples** The direction option is useful for computing left- or right-sided derivatives of nonsmooth functions:: >>> diff(abs, 0, direction=0) 0.0 >>> diff(abs, 0, direction=1) 1.0 >>> diff(abs, 0, direction=-1) -1.0 More generally, if the direction is nonzero, a right difference is computed where the step size is multiplied by sign(direction). For example, with direction=+j, the derivative from the positive imaginary direction will be computed:: >>> diff(abs, 0, direction=j) (0.0 - 1.0j) With integration, the result may have a small imaginary part even even if the result is purely real:: >>> diff(sqrt, 1, method='quad') # doctest:+ELLIPSIS (0.5 - 4.59...e-26j) >>> chop(_) 0.5 Adding precision to obtain an accurate value:: >>> diff(cos, 1e-30) 0.0 >>> diff(cos, 1e-30, h=0.0001) -9.99999998328279e-31 >>> diff(cos, 1e-30, addprec=100) -1.0e-30 """ partial = False try: orders = list(n) x = list(x) partial = True except TypeError: pass if partial: x = [ctx.convert(_) for _ in x] return _partial_diff(ctx, f, x, orders, options) method = options.get('method', 'step') if n == 0 and method != 'quad' and not options.get('singular'): return f(ctx.convert(x)) prec = ctx.prec try: if method == 'step': values, norm, workprec = hsteps(ctx, f, x, n, prec, **options) ctx.prec = workprec v = ctx.difference(values, n) / norm**n elif method == 'quad': ctx.prec += 10 radius = ctx.convert(options.get('radius', 0.25)) def g(t): rei = radius*ctx.expj(t) z = x + rei return f(z) / rei**n d = ctx.quadts(g, [0, 2*ctx.pi]) v = d * ctx.factorial(n) / (2*ctx.pi) else: raise ValueError("unknown method: %r" % method) finally: ctx.prec = prec return +v def _partial_diff(ctx, f, xs, orders, options): if not orders: return f() if not sum(orders): return f(*xs) i = 0 for i in range(len(orders)): if orders[i]: break order = orders[i] def fdiff_inner(*f_args): def inner(t): return f(*(f_args[:i] + (t,) + f_args[i+1:])) return ctx.diff(inner, f_args[i], order, **options) orders[i] = 0 return _partial_diff(ctx, fdiff_inner, xs, orders, options) @defun def diffs(ctx, f, x, n=None, **options): r""" Returns a generator that yields the sequence of derivatives .. math :: f(x), f'(x), f''(x), \ldots, f^{(k)}(x), \ldots With ``method='step'``, :func:`~mpmath.diffs` uses only `O(k)` function evaluations to generate the first `k` derivatives, rather than the roughly `O(k^2)` evaluations required if one calls :func:`~mpmath.diff` `k` separate times. With `n < \infty`, the generator stops as soon as the `n`-th derivative has been generated. If the exact number of needed derivatives is known in advance, this is further slightly more efficient. Options are the same as for :func:`~mpmath.diff`. **Examples** >>> from mpmath import * >>> mp.dps = 15 >>> nprint(list(diffs(cos, 1, 5))) [0.540302, -0.841471, -0.540302, 0.841471, 0.540302, -0.841471] >>> for i, d in zip(range(6), diffs(cos, 1)): ... print("%s %s" % (i, d)) ... 0 0.54030230586814 1 -0.841470984807897 2 -0.54030230586814 3 0.841470984807897 4 0.54030230586814 5 -0.841470984807897 """ if n is None: n = ctx.inf else: n = int(n) if options.get('method', 'step') != 'step': k = 0 while k < n + 1: yield ctx.diff(f, x, k, **options) k += 1 return singular = options.get('singular') if singular: yield ctx.diff(f, x, 0, singular=True) else: yield f(ctx.convert(x)) if n < 1: return if n == ctx.inf: A, B = 1, 2 else: A, B = 1, n+1 while 1: callprec = ctx.prec y, norm, workprec = hsteps(ctx, f, x, B, callprec, **options) for k in xrange(A, B): try: ctx.prec = workprec d = ctx.difference(y, k) / norm**k finally: ctx.prec = callprec yield +d if k >= n: return A, B = B, int(A*1.4+1) B = min(B, n) def iterable_to_function(gen): gen = iter(gen) data = [] def f(k): for i in xrange(len(data), k+1): data.append(next(gen)) return data[k] return f @defun def diffs_prod(ctx, factors): r""" Given a list of `N` iterables or generators yielding `f_k(x), f'_k(x), f''_k(x), \ldots` for `k = 1, \ldots, N`, generate `g(x), g'(x), g''(x), \ldots` where `g(x) = f_1(x) f_2(x) \cdots f_N(x)`. At high precision and for large orders, this is typically more efficient than numerical differentiation if the derivatives of each `f_k(x)` admit direct computation. Note: This function does not increase the working precision internally, so guard digits may have to be added externally for full accuracy. **Examples** >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> f = lambda x: exp(x)*cos(x)*sin(x) >>> u = diffs(f, 1) >>> v = mp.diffs_prod([diffs(exp,1), diffs(cos,1), diffs(sin,1)]) >>> next(u); next(v) 1.23586333600241 1.23586333600241 >>> next(u); next(v) 0.104658952245596 0.104658952245596 >>> next(u); next(v) -5.96999877552086 -5.96999877552086 >>> next(u); next(v) -12.4632923122697 -12.4632923122697 """ N = len(factors) if N == 1: for c in factors[0]: yield c else: u = iterable_to_function(ctx.diffs_prod(factors[:N//2])) v = iterable_to_function(ctx.diffs_prod(factors[N//2:])) n = 0 while 1: #yield sum(binomial(n,k)*u(n-k)*v(k) for k in xrange(n+1)) s = u(n) * v(0) a = 1 for k in xrange(1,n+1): a = a * (n-k+1) // k s += a * u(n-k) * v(k) yield s n += 1 def dpoly(n, _cache={}): """ nth differentiation polynomial for exp (Faa di Bruno's formula). TODO: most exponents are zero, so maybe a sparse representation would be better. """ if n in _cache: return _cache[n] if not _cache: _cache[0] = {(0,):1} R = dpoly(n-1) R = dict((c+(0,),v) for (c,v) in iteritems(R)) Ra = {} for powers, count in iteritems(R): powers1 = (powers[0]+1,) + powers[1:] if powers1 in Ra: Ra[powers1] += count else: Ra[powers1] = count for powers, count in iteritems(R): if not sum(powers): continue for k,p in enumerate(powers): if p: powers2 = powers[:k] + (p-1,powers[k+1]+1) + powers[k+2:] if powers2 in Ra: Ra[powers2] += p*count else: Ra[powers2] = p*count _cache[n] = Ra return _cache[n] @defun def diffs_exp(ctx, fdiffs): r""" Given an iterable or generator yielding `f(x), f'(x), f''(x), \ldots` generate `g(x), g'(x), g''(x), \ldots` where `g(x) = \exp(f(x))`. At high precision and for large orders, this is typically more efficient than numerical differentiation if the derivatives of `f(x)` admit direct computation. Note: This function does not increase the working precision internally, so guard digits may have to be added externally for full accuracy. **Examples** The derivatives of the gamma function can be computed using logarithmic differentiation:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> >>> def diffs_loggamma(x): ... yield loggamma(x) ... i = 0 ... while 1: ... yield psi(i,x) ... i += 1 ... >>> u = diffs_exp(diffs_loggamma(3)) >>> v = diffs(gamma, 3) >>> next(u); next(v) 2.0 2.0 >>> next(u); next(v) 1.84556867019693 1.84556867019693 >>> next(u); next(v) 2.49292999190269 2.49292999190269 >>> next(u); next(v) 3.44996501352367 3.44996501352367 """ fn = iterable_to_function(fdiffs) f0 = ctx.exp(fn(0)) yield f0 i = 1 while 1: s = ctx.mpf(0) for powers, c in iteritems(dpoly(i)): s += c*ctx.fprod(fn(k+1)**p for (k,p) in enumerate(powers) if p) yield s * f0 i += 1 @defun def differint(ctx, f, x, n=1, x0=0): r""" Calculates the Riemann-Liouville differintegral, or fractional derivative, defined by .. math :: \,_{x_0}{\mathbb{D}}^n_xf(x) = \frac{1}{\Gamma(m-n)} \frac{d^m}{dx^m} \int_{x_0}^{x}(x-t)^{m-n-1}f(t)dt where `f` is a given (presumably well-behaved) function, `x` is the evaluation point, `n` is the order, and `x_0` is the reference point of integration (`m` is an arbitrary parameter selected automatically). With `n = 1`, this is just the standard derivative `f'(x)`; with `n = 2`, the second derivative `f''(x)`, etc. With `n = -1`, it gives `\int_{x_0}^x f(t) dt`, with `n = -2` it gives `\int_{x_0}^x \left( \int_{x_0}^t f(u) du \right) dt`, etc. As `n` is permitted to be any number, this operator generalizes iterated differentiation and iterated integration to a single operator with a continuous order parameter. **Examples** There is an exact formula for the fractional derivative of a monomial `x^p`, which may be used as a reference. For example, the following gives a half-derivative (order 0.5):: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> x = mpf(3); p = 2; n = 0.5 >>> differint(lambda t: t**p, x, n) 7.81764019044672 >>> gamma(p+1)/gamma(p-n+1) * x**(p-n) 7.81764019044672 Another useful test function is the exponential function, whose integration / differentiation formula easy generalizes to arbitrary order. Here we first compute a third derivative, and then a triply nested integral. (The reference point `x_0` is set to `-\infty` to avoid nonzero endpoint terms.):: >>> differint(lambda x: exp(pi*x), -1.5, 3) 0.278538406900792 >>> exp(pi*-1.5) * pi**3 0.278538406900792 >>> differint(lambda x: exp(pi*x), 3.5, -3, -inf) 1922.50563031149 >>> exp(pi*3.5) / pi**3 1922.50563031149 However, for noninteger `n`, the differentiation formula for the exponential function must be modified to give the same result as the Riemann-Liouville differintegral:: >>> x = mpf(3.5) >>> c = pi >>> n = 1+2*j >>> differint(lambda x: exp(c*x), x, n) (-123295.005390743 + 140955.117867654j) >>> x**(-n) * exp(c)**x * (x*c)**n * gammainc(-n, 0, x*c) / gamma(-n) (-123295.005390743 + 140955.117867654j) """ m = max(int(ctx.ceil(ctx.re(n)))+1, 1) r = m-n-1 g = lambda x: ctx.quad(lambda t: (x-t)**r * f(t), [x0, x]) return ctx.diff(g, x, m) / ctx.gamma(m-n) @defun def diffun(ctx, f, n=1, **options): r""" Given a function `f`, returns a function `g(x)` that evaluates the nth derivative `f^{(n)}(x)`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> cos2 = diffun(sin) >>> sin2 = diffun(sin, 4) >>> cos(1.3), cos2(1.3) (0.267498828624587, 0.267498828624587) >>> sin(1.3), sin2(1.3) (0.963558185417193, 0.963558185417193) The function `f` must support arbitrary precision evaluation. See :func:`~mpmath.diff` for additional details and supported keyword options. """ if n == 0: return f def g(x): return ctx.diff(f, x, n, **options) return g @defun def taylor(ctx, f, x, n, **options): r""" Produces a degree-`n` Taylor polynomial around the point `x` of the given function `f`. The coefficients are returned as a list. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nprint(chop(taylor(sin, 0, 5))) [0.0, 1.0, 0.0, -0.166667, 0.0, 0.00833333] The coefficients are computed using high-order numerical differentiation. The function must be possible to evaluate to arbitrary precision. See :func:`~mpmath.diff` for additional details and supported keyword options. Note that to evaluate the Taylor polynomial as an approximation of `f`, e.g. with :func:`~mpmath.polyval`, the coefficients must be reversed, and the point of the Taylor expansion must be subtracted from the argument: >>> p = taylor(exp, 2.0, 10) >>> polyval(p[::-1], 2.5 - 2.0) 12.1824939606092 >>> exp(2.5) 12.1824939607035 """ gen = enumerate(ctx.diffs(f, x, n, **options)) if options.get("chop", True): return [ctx.chop(d)/ctx.factorial(i) for i, d in gen] else: return [d/ctx.factorial(i) for i, d in gen] @defun def pade(ctx, a, L, M): r""" Computes a Pade approximation of degree `(L, M)` to a function. Given at least `L+M+1` Taylor coefficients `a` approximating a function `A(x)`, :func:`~mpmath.pade` returns coefficients of polynomials `P, Q` satisfying .. math :: P = \sum_{k=0}^L p_k x^k Q = \sum_{k=0}^M q_k x^k Q_0 = 1 A(x) Q(x) = P(x) + O(x^{L+M+1}) `P(x)/Q(x)` can provide a good approximation to an analytic function beyond the radius of convergence of its Taylor series (example from G.A. Baker 'Essentials of Pade Approximants' Academic Press, Ch.1A):: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> one = mpf(1) >>> def f(x): ... return sqrt((one + 2*x)/(one + x)) ... >>> a = taylor(f, 0, 6) >>> p, q = pade(a, 3, 3) >>> x = 10 >>> polyval(p[::-1], x)/polyval(q[::-1], x) 1.38169105566806 >>> f(x) 1.38169855941551 """ # To determine L+1 coefficients of P and M coefficients of Q # L+M+1 coefficients of A must be provided if len(a) < L+M+1: raise ValueError("L+M+1 Coefficients should be provided") if M == 0: if L == 0: return [ctx.one], [ctx.one] else: return a[:L+1], [ctx.one] # Solve first # a[L]*q[1] + ... + a[L-M+1]*q[M] = -a[L+1] # ... # a[L+M-1]*q[1] + ... + a[L]*q[M] = -a[L+M] A = ctx.matrix(M) for j in range(M): for i in range(min(M, L+j+1)): A[j, i] = a[L+j-i] v = -ctx.matrix(a[(L+1):(L+M+1)]) x = ctx.lu_solve(A, v) q = [ctx.one] + list(x) # compute p p = [0]*(L+1) for i in range(L+1): s = a[i] for j in range(1, min(M,i) + 1): s += q[j]*a[i-j] p[i] = s return p, q mpmath-1.1.0/mpmath/calculus/extrapolation.py000066400000000000000000002171111340375245600213570ustar00rootroot00000000000000try: from itertools import izip except ImportError: izip = zip from ..libmp.backend import xrange from .calculus import defun try: next = next except NameError: next = lambda _: _.next() @defun def richardson(ctx, seq): r""" Given a list ``seq`` of the first `N` elements of a slowly convergent infinite sequence, :func:`~mpmath.richardson` computes the `N`-term Richardson extrapolate for the limit. :func:`~mpmath.richardson` returns `(v, c)` where `v` is the estimated limit and `c` is the magnitude of the largest weight used during the computation. The weight provides an estimate of the precision lost to cancellation. Due to cancellation effects, the sequence must be typically be computed at a much higher precision than the target accuracy of the extrapolation. **Applicability and issues** The `N`-step Richardson extrapolation algorithm used by :func:`~mpmath.richardson` is described in [1]. Richardson extrapolation only works for a specific type of sequence, namely one converging like partial sums of `P(1)/Q(1) + P(2)/Q(2) + \ldots` where `P` and `Q` are polynomials. When the sequence does not convergence at such a rate :func:`~mpmath.richardson` generally produces garbage. Richardson extrapolation has the advantage of being fast: the `N`-term extrapolate requires only `O(N)` arithmetic operations, and usually produces an estimate that is accurate to `O(N)` digits. Contrast with the Shanks transformation (see :func:`~mpmath.shanks`), which requires `O(N^2)` operations. :func:`~mpmath.richardson` is unable to produce an estimate for the approximation error. One way to estimate the error is to perform two extrapolations with slightly different `N` and comparing the results. Richardson extrapolation does not work for oscillating sequences. As a simple workaround, :func:`~mpmath.richardson` detects if the last three elements do not differ monotonically, and in that case applies extrapolation only to the even-index elements. **Example** Applying Richardson extrapolation to the Leibniz series for `\pi`:: >>> from mpmath import * >>> mp.dps = 30; mp.pretty = True >>> S = [4*sum(mpf(-1)**n/(2*n+1) for n in range(m)) ... for m in range(1,30)] >>> v, c = richardson(S[:10]) >>> v 3.2126984126984126984126984127 >>> nprint([v-pi, c]) [0.0711058, 2.0] >>> v, c = richardson(S[:30]) >>> v 3.14159265468624052829954206226 >>> nprint([v-pi, c]) [1.09645e-9, 20833.3] **References** 1. [BenderOrszag]_ pp. 375-376 """ if len(seq) < 3: raise ValueError("seq should be of minimum length 3") if ctx.sign(seq[-1]-seq[-2]) != ctx.sign(seq[-2]-seq[-3]): seq = seq[::2] N = len(seq)//2-1 s = ctx.zero # The general weight is c[k] = (N+k)**N * (-1)**(k+N) / k! / (N-k)! # To avoid repeated factorials, we simplify the quotient # of successive weights to obtain a recurrence relation c = (-1)**N * N**N / ctx.mpf(ctx._ifac(N)) maxc = 1 for k in xrange(N+1): s += c * seq[N+k] maxc = max(abs(c), maxc) c *= (k-N)*ctx.mpf(k+N+1)**N c /= ((1+k)*ctx.mpf(k+N)**N) return s, maxc @defun def shanks(ctx, seq, table=None, randomized=False): r""" Given a list ``seq`` of the first `N` elements of a slowly convergent infinite sequence `(A_k)`, :func:`~mpmath.shanks` computes the iterated Shanks transformation `S(A), S(S(A)), \ldots, S^{N/2}(A)`. The Shanks transformation often provides strong convergence acceleration, especially if the sequence is oscillating. The iterated Shanks transformation is computed using the Wynn epsilon algorithm (see [1]). :func:`~mpmath.shanks` returns the full epsilon table generated by Wynn's algorithm, which can be read off as follows: * The table is a list of lists forming a lower triangular matrix, where higher row and column indices correspond to more accurate values. * The columns with even index hold dummy entries (required for the computation) and the columns with odd index hold the actual extrapolates. * The last element in the last row is typically the most accurate estimate of the limit. * The difference to the third last element in the last row provides an estimate of the approximation error. * The magnitude of the second last element provides an estimate of the numerical accuracy lost to cancellation. For convenience, so the extrapolation is stopped at an odd index so that ``shanks(seq)[-1][-1]`` always gives an estimate of the limit. Optionally, an existing table can be passed to :func:`~mpmath.shanks`. This can be used to efficiently extend a previous computation after new elements have been appended to the sequence. The table will then be updated in-place. **The Shanks transformation** The Shanks transformation is defined as follows (see [2]): given the input sequence `(A_0, A_1, \ldots)`, the transformed sequence is given by .. math :: S(A_k) = \frac{A_{k+1}A_{k-1}-A_k^2}{A_{k+1}+A_{k-1}-2 A_k} The Shanks transformation gives the exact limit `A_{\infty}` in a single step if `A_k = A + a q^k`. Note in particular that it extrapolates the exact sum of a geometric series in a single step. Applying the Shanks transformation once often improves convergence substantially for an arbitrary sequence, but the optimal effect is obtained by applying it iteratively: `S(S(A_k)), S(S(S(A_k))), \ldots`. Wynn's epsilon algorithm provides an efficient way to generate the table of iterated Shanks transformations. It reduces the computation of each element to essentially a single division, at the cost of requiring dummy elements in the table. See [1] for details. **Precision issues** Due to cancellation effects, the sequence must be typically be computed at a much higher precision than the target accuracy of the extrapolation. If the Shanks transformation converges to the exact limit (such as if the sequence is a geometric series), then a division by zero occurs. By default, :func:`~mpmath.shanks` handles this case by terminating the iteration and returning the table it has generated so far. With *randomized=True*, it will instead replace the zero by a pseudorandom number close to zero. (TODO: find a better solution to this problem.) **Examples** We illustrate by applying Shanks transformation to the Leibniz series for `\pi`:: >>> from mpmath import * >>> mp.dps = 50 >>> S = [4*sum(mpf(-1)**n/(2*n+1) for n in range(m)) ... for m in range(1,30)] >>> >>> T = shanks(S[:7]) >>> for row in T: ... nprint(row) ... [-0.75] [1.25, 3.16667] [-1.75, 3.13333, -28.75] [2.25, 3.14524, 82.25, 3.14234] [-2.75, 3.13968, -177.75, 3.14139, -969.937] [3.25, 3.14271, 327.25, 3.14166, 3515.06, 3.14161] The extrapolated accuracy is about 4 digits, and about 4 digits may have been lost due to cancellation:: >>> L = T[-1] >>> nprint([abs(L[-1] - pi), abs(L[-1] - L[-3]), abs(L[-2])]) [2.22532e-5, 4.78309e-5, 3515.06] Now we extend the computation:: >>> T = shanks(S[:25], T) >>> L = T[-1] >>> nprint([abs(L[-1] - pi), abs(L[-1] - L[-3]), abs(L[-2])]) [3.75527e-19, 1.48478e-19, 2.96014e+17] The value for pi is now accurate to 18 digits. About 18 digits may also have been lost to cancellation. Here is an example with a geometric series, where the convergence is immediate (the sum is exactly 1):: >>> mp.dps = 15 >>> for row in shanks([0.5, 0.75, 0.875, 0.9375, 0.96875]): ... nprint(row) [4.0] [8.0, 1.0] **References** 1. [GravesMorris]_ 2. [BenderOrszag]_ pp. 368-375 """ if len(seq) < 2: raise ValueError("seq should be of minimum length 2") if table: START = len(table) else: START = 0 table = [] STOP = len(seq) - 1 if STOP & 1: STOP -= 1 one = ctx.one eps = +ctx.eps if randomized: from random import Random rnd = Random() rnd.seed(START) for i in xrange(START, STOP): row = [] for j in xrange(i+1): if j == 0: a, b = 0, seq[i+1]-seq[i] else: if j == 1: a = seq[i] else: a = table[i-1][j-2] b = row[j-1] - table[i-1][j-1] if not b: if randomized: b = rnd.getrandbits(10)*eps elif i & 1: return table[:-1] else: return table row.append(a + one/b) table.append(row) return table class levin_class: # levin: Copyright 2013 Timo Hartmann (thartmann15 at gmail.com) r""" This interface implements Levin's (nonlinear) sequence transformation for convergence acceleration and summation of divergent series. It performs better than the Shanks/Wynn-epsilon algorithm for logarithmic convergent or alternating divergent series. Let *A* be the series we want to sum: .. math :: A = \sum_{k=0}^{\infty} a_k Attention: all `a_k` must be non-zero! Let `s_n` be the partial sums of this series: .. math :: s_n = \sum_{k=0}^n a_k. **Methods** Calling ``levin`` returns an object with the following methods. ``update(...)`` works with the list of individual terms `a_k` of *A*, and ``update_step(...)`` works with the list of partial sums `s_k` of *A*: .. code :: v, e = ...update([a_0, a_1,..., a_k]) v, e = ...update_psum([s_0, s_1,..., s_k]) ``step(...)`` works with the individual terms `a_k` and ``step_psum(...)`` works with the partial sums `s_k`: .. code :: v, e = ...step(a_k) v, e = ...step_psum(s_k) *v* is the current estimate for *A*, and *e* is an error estimate which is simply the difference between the current estimate and the last estimate. One should not mix ``update``, ``update_psum``, ``step`` and ``step_psum``. **A word of caution** One can only hope for good results (i.e. convergence acceleration or resummation) if the `s_n` have some well defind asymptotic behavior for large `n` and are not erratic or random. Furthermore one usually needs very high working precision because of the numerical cancellation. If the working precision is insufficient, levin may produce silently numerical garbage. Furthermore even if the Levin-transformation converges, in the general case there is no proof that the result is mathematically sound. Only for very special classes of problems one can prove that the Levin-transformation converges to the expected result (for example Stieltjes-type integrals). Furthermore the Levin-transform is quite expensive (i.e. slow) in comparison to Shanks/Wynn-epsilon, Richardson & co. In summary one can say that the Levin-transformation is powerful but unreliable and that it may need a copious amount of working precision. The Levin transform has several variants differing in the choice of weights. Some variants are better suited for the possible flavours of convergence behaviour of *A* than other variants: .. code :: convergence behaviour levin-u levin-t levin-v shanks/wynn-epsilon logarithmic + - + - linear + + + + alternating divergent + + + + "+" means the variant is suitable,"-" means the variant is not suitable; for comparison the Shanks/Wynn-epsilon transform is listed, too. The variant is controlled though the variant keyword (i.e. ``variant="u"``, ``variant="t"`` or ``variant="v"``). Overall "u" is probably the best choice. Finally it is possible to use the Sidi-S transform instead of the Levin transform by using the keyword ``method='sidi'``. The Sidi-S transform works better than the Levin transformation for some divergent series (see the examples). Parameters: .. code :: method "levin" or "sidi" chooses either the Levin or the Sidi-S transformation variant "u","t" or "v" chooses the weight variant. The Levin transform is also accessible through the nsum interface. ``method="l"`` or ``method="levin"`` select the normal Levin transform while ``method="sidi"`` selects the Sidi-S transform. The variant is in both cases selected through the levin_variant keyword. The stepsize in :func:`~mpmath.nsum` must not be chosen too large, otherwise it will miss the point where the Levin transform converges resulting in numerical overflow/garbage. For highly divergent series a copious amount of working precision must be chosen. **Examples** First we sum the zeta function:: >>> from mpmath import mp >>> mp.prec = 53 >>> eps = mp.mpf(mp.eps) >>> with mp.extraprec(2 * mp.prec): # levin needs a high working precision ... L = mp.levin(method = "levin", variant = "u") ... S, s, n = [], 0, 1 ... while 1: ... s += mp.one / (n * n) ... n += 1 ... S.append(s) ... v, e = L.update_psum(S) ... if e < eps: ... break ... if n > 1000: raise RuntimeError("iteration limit exceeded") >>> print(mp.chop(v - mp.pi ** 2 / 6)) 0.0 >>> w = mp.nsum(lambda n: 1 / (n*n), [1, mp.inf], method = "levin", levin_variant = "u") >>> print(mp.chop(v - w)) 0.0 Now we sum the zeta function outside its range of convergence (attention: This does not work at the negative integers!):: >>> eps = mp.mpf(mp.eps) >>> with mp.extraprec(2 * mp.prec): # levin needs a high working precision ... L = mp.levin(method = "levin", variant = "v") ... A, n = [], 1 ... while 1: ... s = mp.mpf(n) ** (2 + 3j) ... n += 1 ... A.append(s) ... v, e = L.update(A) ... if e < eps: ... break ... if n > 1000: raise RuntimeError("iteration limit exceeded") >>> print(mp.chop(v - mp.zeta(-2-3j))) 0.0 >>> w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = "levin", levin_variant = "v") >>> print(mp.chop(v - w)) 0.0 Now we sum the divergent asymptotic expansion of an integral related to the exponential integral (see also [2] p.373). The Sidi-S transform works best here:: >>> z = mp.mpf(10) >>> exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf]) >>> # exact = z * mp.exp(z) * mp.expint(1,z) # this is the symbolic expression for the integral >>> eps = mp.mpf(mp.eps) >>> with mp.extraprec(2 * mp.prec): # high working precisions are mandatory for divergent resummation ... L = mp.levin(method = "sidi", variant = "t") ... n = 0 ... while 1: ... s = (-1)**n * mp.fac(n) * z ** (-n) ... v, e = L.step(s) ... n += 1 ... if e < eps: ... break ... if n > 1000: raise RuntimeError("iteration limit exceeded") >>> print(mp.chop(v - exact)) 0.0 >>> w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = "sidi", levin_variant = "t") >>> print(mp.chop(v - w)) 0.0 Another highly divergent integral is also summable:: >>> z = mp.mpf(2) >>> eps = mp.mpf(mp.eps) >>> exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 * mp.pi) >>> # exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt(z * mp.pi)) # this is the symbolic expression for the integral >>> with mp.extraprec(7 * mp.prec): # we need copious amount of precision to sum this highly divergent series ... L = mp.levin(method = "levin", variant = "t") ... n, s = 0, 0 ... while 1: ... s += (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)) ... n += 1 ... v, e = L.step_psum(s) ... if e < eps: ... break ... if n > 1000: raise RuntimeError("iteration limit exceeded") >>> print(mp.chop(v - exact)) 0.0 >>> w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)), ... [0, mp.inf], method = "levin", levin_variant = "t", workprec = 8*mp.prec, steps = [2] + [1 for x in xrange(1000)]) >>> print(mp.chop(v - w)) 0.0 These examples run with 15-20 decimal digits precision. For higher precision the working precision must be raised. **Examples for nsum** Here we calculate Euler's constant as the constant term in the Laurent expansion of `\zeta(s)` at `s=1`. This sum converges extremly slowly because of the logarithmic convergence behaviour of the Dirichlet series for zeta:: >>> mp.dps = 30 >>> z = mp.mpf(10) ** (-10) >>> a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = "l") - 1 / z >>> print(mp.chop(a - mp.euler, tol = 1e-10)) 0.0 The Sidi-S transform performs excellently for the alternating series of `\log(2)`:: >>> a = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "sidi") >>> print(mp.chop(a - mp.log(2))) 0.0 Hypergeometric series can also be summed outside their range of convergence. The stepsize in :func:`~mpmath.nsum` must not be chosen too large, otherwise it will miss the point where the Levin transform converges resulting in numerical overflow/garbage:: >>> z = 2 + 1j >>> exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z) >>> f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3), n) * mp.fac(n)) >>> v = mp.nsum(f, [0, mp.inf], method = "levin", steps = [10 for x in xrange(1000)]) >>> print(mp.chop(exact-v)) 0.0 References: [1] E.J. Weniger - "Nonlinear Sequence Transformations for the Acceleration of Convergence and the Summation of Divergent Series" arXiv:math/0306302 [2] A. Sidi - "Pratical Extrapolation Methods" [3] H.H.H. Homeier - "Scalar Levin-Type Sequence Transformations" arXiv:math/0005209 """ def __init__(self, method = "levin", variant = "u"): self.variant = variant self.n = 0 self.a0 = 0 self.theta = 1 self.A = [] self.B = [] self.last = 0 self.last_s = False if method == "levin": self.factor = self.factor_levin elif method == "sidi": self.factor = self.factor_sidi else: raise ValueError("levin: unknown method \"%s\"" % method) def factor_levin(self, i): # original levin # [1] p.50,e.7.5-7 (with n-j replaced by i) return (self.theta + i) * (self.theta + self.n - 1) ** (self.n - i - 2) / self.ctx.mpf(self.theta + self.n) ** (self.n - i - 1) def factor_sidi(self, i): # sidi analogon to levin (factorial series) # [1] p.59,e.8.3-16 (with n-j replaced by i) return (self.theta + self.n - 1) * (self.theta + self.n - 2) / self.ctx.mpf((self.theta + 2 * self.n - i - 2) * (self.theta + 2 * self.n - i - 3)) def run(self, s, a0, a1 = 0): if self.variant=="t": # levin t w=a0 elif self.variant=="u": # levin u w=a0*(self.theta+self.n) elif self.variant=="v": # levin v w=a0*a1/(a0-a1) else: assert False, "unknown variant" if w==0: raise ValueError("levin: zero weight") self.A.append(s/w) self.B.append(1/w) for i in range(self.n-1,-1,-1): if i==self.n-1: f=1 else: f=self.factor(i) self.A[i]=self.A[i+1]-f*self.A[i] self.B[i]=self.B[i+1]-f*self.B[i] self.n+=1 ########################################################################### def update_psum(self,S): """ This routine applies the convergence acceleration to the list of partial sums. A = sum(a_k, k = 0..infinity) s_n = sum(a_k, k = 0..n) v, e = ...update_psum([s_0, s_1,..., s_k]) output: v current estimate of the series A e an error estimate which is simply the difference between the current estimate and the last estimate. """ if self.variant!="v": if self.n==0: self.run(S[0],S[0]) while self.n>> from mpmath import mp >>> AC = mp.cohen_alt() >>> S, s, n = [], 0, 1 >>> while 1: ... s += -((-1) ** n) * mp.one / (n * n) ... n += 1 ... S.append(s) ... v, e = AC.update_psum(S) ... if e < mp.eps: ... break ... if n > 1000: raise RuntimeError("iteration limit exceeded") >>> print(mp.chop(v - mp.pi ** 2 / 12)) 0.0 Here we compute the product `\prod_{n=1}^{\infty} \Gamma(1+1/(2n-1)) / \Gamma(1+1/(2n))`:: >>> A = [] >>> AC = mp.cohen_alt() >>> n = 1 >>> while 1: ... A.append( mp.loggamma(1 + mp.one / (2 * n - 1))) ... A.append(-mp.loggamma(1 + mp.one / (2 * n))) ... n += 1 ... v, e = AC.update(A) ... if e < mp.eps: ... break ... if n > 1000: raise RuntimeError("iteration limit exceeded") >>> v = mp.exp(v) >>> print(mp.chop(v - 1.06215090557106, tol = 1e-12)) 0.0 ``cohen_alt`` is also accessible through the :func:`~mpmath.nsum` interface:: >>> v = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "a") >>> print(mp.chop(v - mp.log(2))) 0.0 >>> v = mp.nsum(lambda n: (-1)**n / (2 * n + 1), [0, mp.inf], method = "a") >>> print(mp.chop(v - mp.pi / 4)) 0.0 >>> v = mp.nsum(lambda n: (-1)**n * mp.log(n) * n, [1, mp.inf], method = "a") >>> print(mp.chop(v - mp.diff(lambda s: mp.altzeta(s), -1))) 0.0 """ def __init__(self): self.last=0 def update(self, A): """ This routine applies the convergence acceleration to the list of individual terms. A = sum(a_k, k = 0..infinity) v, e = ...update([a_0, a_1,..., a_k]) output: v current estimate of the series A e an error estimate which is simply the difference between the current estimate and the last estimate. """ n = len(A) d = (3 + self.ctx.sqrt(8)) ** n d = (d + 1 / d) / 2 b = -self.ctx.one c = -d s = 0 for k in xrange(n): c = b - c if k % 2 == 0: s = s + c * A[k] else: s = s - c * A[k] b = 2 * (k + n) * (k - n) * b / ((2 * k + 1) * (k + self.ctx.one)) value = s / d err = abs(value - self.last) self.last = value return value, err def update_psum(self, S): """ This routine applies the convergence acceleration to the list of partial sums. A = sum(a_k, k = 0..infinity) s_n = sum(a_k ,k = 0..n) v, e = ...update_psum([s_0, s_1,..., s_k]) output: v current estimate of the series A e an error estimate which is simply the difference between the current estimate and the last estimate. """ n = len(S) d = (3 + self.ctx.sqrt(8)) ** n d = (d + 1 / d) / 2 b = self.ctx.one s = 0 for k in xrange(n): b = 2 * (n + k) * (n - k) * b / ((2 * k + 1) * (k + self.ctx.one)) s += b * S[k] value = s / d err = abs(value - self.last) self.last = value return value, err def cohen_alt(ctx): L = cohen_alt_class() L.ctx = ctx return L cohen_alt.__doc__ = cohen_alt_class.__doc__ defun(cohen_alt) @defun def sumap(ctx, f, interval, integral=None, error=False): r""" Evaluates an infinite series of an analytic summand *f* using the Abel-Plana formula .. math :: \sum_{k=0}^{\infty} f(k) = \int_0^{\infty} f(t) dt + \frac{1}{2} f(0) + i \int_0^{\infty} \frac{f(it)-f(-it)}{e^{2\pi t}-1} dt. Unlike the Euler-Maclaurin formula (see :func:`~mpmath.sumem`), the Abel-Plana formula does not require derivatives. However, it only works when `|f(it)-f(-it)|` does not increase too rapidly with `t`. **Examples** The Abel-Plana formula is particularly useful when the summand decreases like a power of `k`; for example when the sum is a pure zeta function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> sumap(lambda k: 1/k**2.5, [1,inf]) 1.34148725725091717975677 >>> zeta(2.5) 1.34148725725091717975677 >>> sumap(lambda k: 1/(k+1j)**(2.5+2.5j), [1,inf]) (-3.385361068546473342286084 - 0.7432082105196321803869551j) >>> zeta(2.5+2.5j, 1+1j) (-3.385361068546473342286084 - 0.7432082105196321803869551j) If the series is alternating, numerical quadrature along the real line is likely to give poor results, so it is better to evaluate the first term symbolically whenever possible: >>> n=3; z=-0.75 >>> I = expint(n,-log(z)) >>> chop(sumap(lambda k: z**k / k**n, [1,inf], integral=I)) -0.6917036036904594510141448 >>> polylog(n,z) -0.6917036036904594510141448 """ prec = ctx.prec try: ctx.prec += 10 a, b = interval if b != ctx.inf: raise ValueError("b should be equal to ctx.inf") g = lambda x: f(x+a) if integral is None: i1, err1 = ctx.quad(g, [0,ctx.inf], error=True) else: i1, err1 = integral, 0 j = ctx.j p = ctx.pi * 2 if ctx._is_real_type(i1): h = lambda t: -2 * ctx.im(g(j*t)) / ctx.expm1(p*t) else: h = lambda t: j*(g(j*t)-g(-j*t)) / ctx.expm1(p*t) i2, err2 = ctx.quad(h, [0,ctx.inf], error=True) err = err1+err2 v = i1+i2+0.5*g(ctx.mpf(0)) finally: ctx.prec = prec if error: return +v, err return +v @defun def sumem(ctx, f, interval, tol=None, reject=10, integral=None, adiffs=None, bdiffs=None, verbose=False, error=False, _fast_abort=False): r""" Uses the Euler-Maclaurin formula to compute an approximation accurate to within ``tol`` (which defaults to the present epsilon) of the sum .. math :: S = \sum_{k=a}^b f(k) where `(a,b)` are given by ``interval`` and `a` or `b` may be infinite. The approximation is .. math :: S \sim \int_a^b f(x) \,dx + \frac{f(a)+f(b)}{2} + \sum_{k=1}^{\infty} \frac{B_{2k}}{(2k)!} \left(f^{(2k-1)}(b)-f^{(2k-1)}(a)\right). The last sum in the Euler-Maclaurin formula is not generally convergent (a notable exception is if `f` is a polynomial, in which case Euler-Maclaurin actually gives an exact result). The summation is stopped as soon as the quotient between two consecutive terms falls below *reject*. That is, by default (*reject* = 10), the summation is continued as long as each term adds at least one decimal. Although not convergent, convergence to a given tolerance can often be "forced" if `b = \infty` by summing up to `a+N` and then applying the Euler-Maclaurin formula to the sum over the range `(a+N+1, \ldots, \infty)`. This procedure is implemented by :func:`~mpmath.nsum`. By default numerical quadrature and differentiation is used. If the symbolic values of the integral and endpoint derivatives are known, it is more efficient to pass the value of the integral explicitly as ``integral`` and the derivatives explicitly as ``adiffs`` and ``bdiffs``. The derivatives should be given as iterables that yield `f(a), f'(a), f''(a), \ldots` (and the equivalent for `b`). **Examples** Summation of an infinite series, with automatic and symbolic integral and derivative values (the second should be much faster):: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> sumem(lambda n: 1/n**2, [32, inf]) 0.03174336652030209012658168043874142714132886413417 >>> I = mpf(1)/32 >>> D = adiffs=((-1)**n*fac(n+1)*32**(-2-n) for n in range(999)) >>> sumem(lambda n: 1/n**2, [32, inf], integral=I, adiffs=D) 0.03174336652030209012658168043874142714132886413417 An exact evaluation of a finite polynomial sum:: >>> sumem(lambda n: n**5-12*n**2+3*n, [-100000, 200000]) 10500155000624963999742499550000.0 >>> print(sum(n**5-12*n**2+3*n for n in range(-100000, 200001))) 10500155000624963999742499550000 """ tol = tol or +ctx.eps interval = ctx._as_points(interval) a = ctx.convert(interval[0]) b = ctx.convert(interval[-1]) err = ctx.zero prev = 0 M = 10000 if a == ctx.ninf: adiffs = (0 for n in xrange(M)) else: adiffs = adiffs or ctx.diffs(f, a) if b == ctx.inf: bdiffs = (0 for n in xrange(M)) else: bdiffs = bdiffs or ctx.diffs(f, b) orig = ctx.prec #verbose = 1 try: ctx.prec += 10 s = ctx.zero for k, (da, db) in enumerate(izip(adiffs, bdiffs)): if k & 1: term = (db-da) * ctx.bernoulli(k+1) / ctx.factorial(k+1) mag = abs(term) if verbose: print("term", k, "magnitude =", ctx.nstr(mag)) if k > 4 and mag < tol: s += term break elif k > 4 and abs(prev) / mag < reject: err += mag if _fast_abort: return [s, (s, err)][error] if verbose: print("Failed to converge") break else: s += term prev = term # Endpoint correction if a != ctx.ninf: s += f(a)/2 if b != ctx.inf: s += f(b)/2 # Tail integral if verbose: print("Integrating f(x) from x = %s to %s" % (ctx.nstr(a), ctx.nstr(b))) if integral: s += integral else: integral, ierr = ctx.quad(f, interval, error=True) if verbose: print("Integration error:", ierr) s += integral err += ierr finally: ctx.prec = orig if error: return s, err else: return s @defun def adaptive_extrapolation(ctx, update, emfun, kwargs): option = kwargs.get if ctx._fixed_precision: tol = option('tol', ctx.eps*2**10) else: tol = option('tol', ctx.eps/2**10) verbose = option('verbose', False) maxterms = option('maxterms', ctx.dps*10) method = set(option('method', 'r+s').split('+')) skip = option('skip', 0) steps = iter(option('steps', xrange(10, 10**9, 10))) strict = option('strict') #steps = (10 for i in xrange(1000)) summer=[] if 'd' in method or 'direct' in method: TRY_RICHARDSON = TRY_SHANKS = TRY_EULER_MACLAURIN = False else: TRY_RICHARDSON = ('r' in method) or ('richardson' in method) TRY_SHANKS = ('s' in method) or ('shanks' in method) TRY_EULER_MACLAURIN = ('e' in method) or \ ('euler-maclaurin' in method) def init_levin(m): variant = kwargs.get("levin_variant", "u") if isinstance(variant, str): if variant == "all": variant = ["u", "v", "t"] else: variant = [variant] for s in variant: L = levin_class(method = m, variant = s) L.ctx = ctx L.name = m + "(" + s + ")" summer.append(L) if ('l' in method) or ('levin' in method): init_levin("levin") if ('sidi' in method): init_levin("sidi") if ('a' in method) or ('alternating' in method): L = cohen_alt_class() L.ctx = ctx L.name = "alternating" summer.append(L) last_richardson_value = 0 shanks_table = [] index = 0 step = 10 partial = [] best = ctx.zero orig = ctx.prec try: if 'workprec' in kwargs: ctx.prec = kwargs['workprec'] elif TRY_RICHARDSON or TRY_SHANKS or len(summer)!=0: ctx.prec = (ctx.prec+10) * 4 else: ctx.prec += 30 while 1: if index >= maxterms: break # Get new batch of terms try: step = next(steps) except StopIteration: pass if verbose: print("-"*70) print("Adding terms #%i-#%i" % (index, index+step)) update(partial, xrange(index, index+step)) index += step # Check direct error best = partial[-1] error = abs(best - partial[-2]) if verbose: print("Direct error: %s" % ctx.nstr(error)) if error <= tol: return best # Check each extrapolation method if TRY_RICHARDSON: value, maxc = ctx.richardson(partial) # Convergence richardson_error = abs(value - last_richardson_value) if verbose: print("Richardson error: %s" % ctx.nstr(richardson_error)) # Convergence if richardson_error <= tol: return value last_richardson_value = value # Unreliable due to cancellation if ctx.eps*maxc > tol: if verbose: print("Ran out of precision for Richardson") TRY_RICHARDSON = False if richardson_error < error: error = richardson_error best = value if TRY_SHANKS: shanks_table = ctx.shanks(partial, shanks_table, randomized=True) row = shanks_table[-1] if len(row) == 2: est1 = row[-1] shanks_error = 0 else: est1, maxc, est2 = row[-1], abs(row[-2]), row[-3] shanks_error = abs(est1-est2) if verbose: print("Shanks error: %s" % ctx.nstr(shanks_error)) if shanks_error <= tol: return est1 if ctx.eps*maxc > tol: if verbose: print("Ran out of precision for Shanks") TRY_SHANKS = False if shanks_error < error: error = shanks_error best = est1 for L in summer: est, lerror = L.update_psum(partial) if verbose: print("%s error: %s" % (L.name, ctx.nstr(lerror))) if lerror <= tol: return est if lerror < error: error = lerror best = est if TRY_EULER_MACLAURIN: if ctx.mpc(ctx.sign(partial[-1]) / ctx.sign(partial[-2])).ae(-1): if verbose: print ("NOT using Euler-Maclaurin: the series appears" " to be alternating, so numerical\n quadrature" " will most likely fail") TRY_EULER_MACLAURIN = False else: value, em_error = emfun(index, tol) value += partial[-1] if verbose: print("Euler-Maclaurin error: %s" % ctx.nstr(em_error)) if em_error <= tol: return value if em_error < error: best = value finally: ctx.prec = orig if strict: raise ctx.NoConvergence if verbose: print("Warning: failed to converge to target accuracy") return best @defun def nsum(ctx, f, *intervals, **options): r""" Computes the sum .. math :: S = \sum_{k=a}^b f(k) where `(a, b)` = *interval*, and where `a = -\infty` and/or `b = \infty` are allowed, or more generally .. math :: S = \sum_{k_1=a_1}^{b_1} \cdots \sum_{k_n=a_n}^{b_n} f(k_1,\ldots,k_n) if multiple intervals are given. Two examples of infinite series that can be summed by :func:`~mpmath.nsum`, where the first converges rapidly and the second converges slowly, are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nsum(lambda n: 1/fac(n), [0, inf]) 2.71828182845905 >>> nsum(lambda n: 1/n**2, [1, inf]) 1.64493406684823 When appropriate, :func:`~mpmath.nsum` applies convergence acceleration to accurately estimate the sums of slowly convergent series. If the series is finite, :func:`~mpmath.nsum` currently does not attempt to perform any extrapolation, and simply calls :func:`~mpmath.fsum`. Multidimensional infinite series are reduced to a single-dimensional series over expanding hypercubes; if both infinite and finite dimensions are present, the finite ranges are moved innermost. For more advanced control over the summation order, use nested calls to :func:`~mpmath.nsum`, or manually rewrite the sum as a single-dimensional series. **Options** *tol* Desired maximum final error. Defaults roughly to the epsilon of the working precision. *method* Which summation algorithm to use (described below). Default: ``'richardson+shanks'``. *maxterms* Cancel after at most this many terms. Default: 10*dps. *steps* An iterable giving the number of terms to add between each extrapolation attempt. The default sequence is [10, 20, 30, 40, ...]. For example, if you know that approximately 100 terms will be required, efficiency might be improved by setting this to [100, 10]. Then the first extrapolation will be performed after 100 terms, the second after 110, etc. *verbose* Print details about progress. *ignore* If enabled, any term that raises ``ArithmeticError`` or ``ValueError`` (e.g. through division by zero) is replaced by a zero. This is convenient for lattice sums with a singular term near the origin. **Methods** Unfortunately, an algorithm that can efficiently sum any infinite series does not exist. :func:`~mpmath.nsum` implements several different algorithms that each work well in different cases. The *method* keyword argument selects a method. The default method is ``'r+s'``, i.e. both Richardson extrapolation and Shanks transformation is attempted. A slower method that handles more cases is ``'r+s+e'``. For very high precision summation, or if the summation needs to be fast (for example if multiple sums need to be evaluated), it is a good idea to investigate which one method works best and only use that. ``'richardson'`` / ``'r'``: Uses Richardson extrapolation. Provides useful extrapolation when `f(k) \sim P(k)/Q(k)` or when `f(k) \sim (-1)^k P(k)/Q(k)` for polynomials `P` and `Q`. See :func:`~mpmath.richardson` for additional information. ``'shanks'`` / ``'s'``: Uses Shanks transformation. Typically provides useful extrapolation when `f(k) \sim c^k` or when successive terms alternate signs. Is able to sum some divergent series. See :func:`~mpmath.shanks` for additional information. ``'levin'`` / ``'l'``: Uses the Levin transformation. It performs better than the Shanks transformation for logarithmic convergent or alternating divergent series. The ``'levin_variant'``-keyword selects the variant. Valid choices are "u", "t", "v" and "all" whereby "all" uses all three u,t and v simultanously (This is good for performance comparison in conjunction with "verbose=True"). Instead of the Levin transform one can also use the Sidi-S transform by selecting the method ``'sidi'``. See :func:`~mpmath.levin` for additional details. ``'alternating'`` / ``'a'``: This is the convergence acceleration of alternating series developped by Cohen, Villegras and Zagier. See :func:`~mpmath.cohen_alt` for additional details. ``'euler-maclaurin'`` / ``'e'``: Uses the Euler-Maclaurin summation formula to approximate the remainder sum by an integral. This requires high-order numerical derivatives and numerical integration. The advantage of this algorithm is that it works regardless of the decay rate of `f`, as long as `f` is sufficiently smooth. See :func:`~mpmath.sumem` for additional information. ``'direct'`` / ``'d'``: Does not perform any extrapolation. This can be used (and should only be used for) rapidly convergent series. The summation automatically stops when the terms decrease below the target tolerance. **Basic examples** A finite sum:: >>> nsum(lambda k: 1/k, [1, 6]) 2.45 Summation of a series going to negative infinity and a doubly infinite series:: >>> nsum(lambda k: 1/k**2, [-inf, -1]) 1.64493406684823 >>> nsum(lambda k: 1/(1+k**2), [-inf, inf]) 3.15334809493716 :func:`~mpmath.nsum` handles sums of complex numbers:: >>> nsum(lambda k: (0.5+0.25j)**k, [0, inf]) (1.6 + 0.8j) The following sum converges very rapidly, so it is most efficient to sum it by disabling convergence acceleration:: >>> mp.dps = 1000 >>> a = nsum(lambda k: -(-1)**k * k**2 / fac(2*k), [1, inf], ... method='direct') >>> b = (cos(1)+sin(1))/4 >>> abs(a-b) < mpf('1e-998') True **Examples with Richardson extrapolation** Richardson extrapolation works well for sums over rational functions, as well as their alternating counterparts:: >>> mp.dps = 50 >>> nsum(lambda k: 1 / k**3, [1, inf], ... method='richardson') 1.2020569031595942853997381615114499907649862923405 >>> zeta(3) 1.2020569031595942853997381615114499907649862923405 >>> nsum(lambda n: (n + 3)/(n**3 + n**2), [1, inf], ... method='richardson') 2.9348022005446793094172454999380755676568497036204 >>> pi**2/2-2 2.9348022005446793094172454999380755676568497036204 >>> nsum(lambda k: (-1)**k / k**3, [1, inf], ... method='richardson') -0.90154267736969571404980362113358749307373971925537 >>> -3*zeta(3)/4 -0.90154267736969571404980362113358749307373971925538 **Examples with Shanks transformation** The Shanks transformation works well for geometric series and typically provides excellent acceleration for Taylor series near the border of their disk of convergence. Here we apply it to a series for `\log(2)`, which can be seen as the Taylor series for `\log(1+x)` with `x = 1`:: >>> nsum(lambda k: -(-1)**k/k, [1, inf], ... method='shanks') 0.69314718055994530941723212145817656807550013436025 >>> log(2) 0.69314718055994530941723212145817656807550013436025 Here we apply it to a slowly convergent geometric series:: >>> nsum(lambda k: mpf('0.995')**k, [0, inf], ... method='shanks') 200.0 Finally, Shanks' method works very well for alternating series where `f(k) = (-1)^k g(k)`, and often does so regardless of the exact decay rate of `g(k)`:: >>> mp.dps = 15 >>> nsum(lambda k: (-1)**(k+1) / k**1.5, [1, inf], ... method='shanks') 0.765147024625408 >>> (2-sqrt(2))*zeta(1.5)/2 0.765147024625408 The following slowly convergent alternating series has no known closed-form value. Evaluating the sum a second time at higher precision indicates that the value is probably correct:: >>> nsum(lambda k: (-1)**k / log(k), [2, inf], ... method='shanks') 0.924299897222939 >>> mp.dps = 30 >>> nsum(lambda k: (-1)**k / log(k), [2, inf], ... method='shanks') 0.92429989722293885595957018136 **Examples with Levin transformation** The following example calculates Euler's constant as the constant term in the Laurent expansion of zeta(s) at s=1. This sum converges extremly slow because of the logarithmic convergence behaviour of the Dirichlet series for zeta. >>> mp.dps = 30 >>> z = mp.mpf(10) ** (-10) >>> a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = "levin") - 1 / z >>> print(mp.chop(a - mp.euler, tol = 1e-10)) 0.0 Now we sum the zeta function outside its range of convergence (attention: This does not work at the negative integers!): >>> mp.dps = 15 >>> w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = "levin", levin_variant = "v") >>> print(mp.chop(w - mp.zeta(-2-3j))) 0.0 The next example resummates an asymptotic series expansion of an integral related to the exponential integral. >>> mp.dps = 15 >>> z = mp.mpf(10) >>> # exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf]) >>> exact = z * mp.exp(z) * mp.expint(1,z) # this is the symbolic expression for the integral >>> w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = "sidi", levin_variant = "t") >>> print(mp.chop(w - exact)) 0.0 Following highly divergent asymptotic expansion needs some care. Firstly we need copious amount of working precision. Secondly the stepsize must not be chosen to large, otherwise nsum may miss the point where the Levin transform converges and reach the point where only numerical garbage is produced due to numerical cancellation. >>> mp.dps = 15 >>> z = mp.mpf(2) >>> # exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 * mp.pi) >>> exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt(z * mp.pi)) # this is the symbolic expression for the integral >>> w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)), ... [0, mp.inf], method = "levin", levin_variant = "t", workprec = 8*mp.prec, steps = [2] + [1 for x in xrange(1000)]) >>> print(mp.chop(w - exact)) 0.0 The hypergeoemtric function can also be summed outside its range of convergence: >>> mp.dps = 15 >>> z = 2 + 1j >>> exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z) >>> f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3), n) * mp.fac(n)) >>> v = mp.nsum(f, [0, mp.inf], method = "levin", steps = [10 for x in xrange(1000)]) >>> print(mp.chop(exact-v)) 0.0 **Examples with Cohen's alternating series resummation** The next example sums the alternating zeta function: >>> v = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "a") >>> print(mp.chop(v - mp.log(2))) 0.0 The derivate of the alternating zeta function outside its range of convergence: >>> v = mp.nsum(lambda n: (-1)**n * mp.log(n) * n, [1, mp.inf], method = "a") >>> print(mp.chop(v - mp.diff(lambda s: mp.altzeta(s), -1))) 0.0 **Examples with Euler-Maclaurin summation** The sum in the following example has the wrong rate of convergence for either Richardson or Shanks to be effective. >>> f = lambda k: log(k)/k**2.5 >>> mp.dps = 15 >>> nsum(f, [1, inf], method='euler-maclaurin') 0.38734195032621 >>> -diff(zeta, 2.5) 0.38734195032621 Increasing ``steps`` improves speed at higher precision:: >>> mp.dps = 50 >>> nsum(f, [1, inf], method='euler-maclaurin', steps=[250]) 0.38734195032620997271199237593105101319948228874688 >>> -diff(zeta, 2.5) 0.38734195032620997271199237593105101319948228874688 **Divergent series** The Shanks transformation is able to sum some *divergent* series. In particular, it is often able to sum Taylor series beyond their radius of convergence (this is due to a relation between the Shanks transformation and Pade approximations; see :func:`~mpmath.pade` for an alternative way to evaluate divergent Taylor series). Furthermore the Levin-transform examples above contain some divergent series resummation. Here we apply it to `\log(1+x)` far outside the region of convergence:: >>> mp.dps = 50 >>> nsum(lambda k: -(-9)**k/k, [1, inf], ... method='shanks') 2.3025850929940456840179914546843642076011014886288 >>> log(10) 2.3025850929940456840179914546843642076011014886288 A particular type of divergent series that can be summed using the Shanks transformation is geometric series. The result is the same as using the closed-form formula for an infinite geometric series:: >>> mp.dps = 15 >>> for n in range(-8, 8): ... if n == 1: ... continue ... print("%s %s %s" % (mpf(n), mpf(1)/(1-n), ... nsum(lambda k: n**k, [0, inf], method='shanks'))) ... -8.0 0.111111111111111 0.111111111111111 -7.0 0.125 0.125 -6.0 0.142857142857143 0.142857142857143 -5.0 0.166666666666667 0.166666666666667 -4.0 0.2 0.2 -3.0 0.25 0.25 -2.0 0.333333333333333 0.333333333333333 -1.0 0.5 0.5 0.0 1.0 1.0 2.0 -1.0 -1.0 3.0 -0.5 -0.5 4.0 -0.333333333333333 -0.333333333333333 5.0 -0.25 -0.25 6.0 -0.2 -0.2 7.0 -0.166666666666667 -0.166666666666667 **Multidimensional sums** Any combination of finite and infinite ranges is allowed for the summation indices:: >>> mp.dps = 15 >>> nsum(lambda x,y: x+y, [2,3], [4,5]) 28.0 >>> nsum(lambda x,y: x/2**y, [1,3], [1,inf]) 6.0 >>> nsum(lambda x,y: y/2**x, [1,inf], [1,3]) 6.0 >>> nsum(lambda x,y,z: z/(2**x*2**y), [1,inf], [1,inf], [3,4]) 7.0 >>> nsum(lambda x,y,z: y/(2**x*2**z), [1,inf], [3,4], [1,inf]) 7.0 >>> nsum(lambda x,y,z: x/(2**z*2**y), [3,4], [1,inf], [1,inf]) 7.0 Some nice examples of double series with analytic solutions or reductions to single-dimensional series (see [1]):: >>> nsum(lambda m, n: 1/2**(m*n), [1,inf], [1,inf]) 1.60669515241529 >>> nsum(lambda n: 1/(2**n-1), [1,inf]) 1.60669515241529 >>> nsum(lambda i,j: (-1)**(i+j)/(i**2+j**2), [1,inf], [1,inf]) 0.278070510848213 >>> pi*(pi-3*ln2)/12 0.278070510848213 >>> nsum(lambda i,j: (-1)**(i+j)/(i+j)**2, [1,inf], [1,inf]) 0.129319852864168 >>> altzeta(2) - altzeta(1) 0.129319852864168 >>> nsum(lambda i,j: (-1)**(i+j)/(i+j)**3, [1,inf], [1,inf]) 0.0790756439455825 >>> altzeta(3) - altzeta(2) 0.0790756439455825 >>> nsum(lambda m,n: m**2*n/(3**m*(n*3**m+m*3**n)), ... [1,inf], [1,inf]) 0.28125 >>> mpf(9)/32 0.28125 >>> nsum(lambda i,j: fac(i-1)*fac(j-1)/fac(i+j), ... [1,inf], [1,inf], workprec=400) 1.64493406684823 >>> zeta(2) 1.64493406684823 A hard example of a multidimensional sum is the Madelung constant in three dimensions (see [2]). The defining sum converges very slowly and only conditionally, so :func:`~mpmath.nsum` is lucky to obtain an accurate value through convergence acceleration. The second evaluation below uses a much more efficient, rapidly convergent 2D sum:: >>> nsum(lambda x,y,z: (-1)**(x+y+z)/(x*x+y*y+z*z)**0.5, ... [-inf,inf], [-inf,inf], [-inf,inf], ignore=True) -1.74756459463318 >>> nsum(lambda x,y: -12*pi*sech(0.5*pi * \ ... sqrt((2*x+1)**2+(2*y+1)**2))**2, [0,inf], [0,inf]) -1.74756459463318 Another example of a lattice sum in 2D:: >>> nsum(lambda x,y: (-1)**(x+y) / (x**2+y**2), [-inf,inf], ... [-inf,inf], ignore=True) -2.1775860903036 >>> -pi*ln2 -2.1775860903036 An example of an Eisenstein series:: >>> nsum(lambda m,n: (m+n*1j)**(-4), [-inf,inf], [-inf,inf], ... ignore=True) (3.1512120021539 + 0.0j) **References** 1. [Weisstein]_ http://mathworld.wolfram.com/DoubleSeries.html, 2. [Weisstein]_ http://mathworld.wolfram.com/MadelungConstants.html """ infinite, g = standardize(ctx, f, intervals, options) if not infinite: return +g() def update(partial_sums, indices): if partial_sums: psum = partial_sums[-1] else: psum = ctx.zero for k in indices: psum = psum + g(ctx.mpf(k)) partial_sums.append(psum) prec = ctx.prec def emfun(point, tol): workprec = ctx.prec ctx.prec = prec + 10 v = ctx.sumem(g, [point, ctx.inf], tol, error=1) ctx.prec = workprec return v return +ctx.adaptive_extrapolation(update, emfun, options) def wrapsafe(f): def g(*args): try: return f(*args) except (ArithmeticError, ValueError): return 0 return g def standardize(ctx, f, intervals, options): if options.get("ignore"): f = wrapsafe(f) finite = [] infinite = [] for k, points in enumerate(intervals): a, b = ctx._as_points(points) if b < a: return False, (lambda: ctx.zero) if a == ctx.ninf or b == ctx.inf: infinite.append((k, (a,b))) else: finite.append((k, (int(a), int(b)))) if finite: f = fold_finite(ctx, f, finite) if not infinite: return False, lambda: f(*([0]*len(intervals))) if infinite: f = standardize_infinite(ctx, f, infinite) f = fold_infinite(ctx, f, infinite) args = [0] * len(intervals) d = infinite[0][0] def g(k): args[d] = k return f(*args) return True, g # backwards compatible itertools.product def cartesian_product(args): pools = map(tuple, args) result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod) def fold_finite(ctx, f, intervals): if not intervals: return f indices = [v[0] for v in intervals] points = [v[1] for v in intervals] ranges = [xrange(a, b+1) for (a,b) in points] def g(*args): args = list(args) s = ctx.zero for xs in cartesian_product(ranges): for dim, x in zip(indices, xs): args[dim] = ctx.mpf(x) s += f(*args) return s #print "Folded finite", indices return g # Standardize each interval to [0,inf] def standardize_infinite(ctx, f, intervals): if not intervals: return f dim, [a,b] = intervals[-1] if a == ctx.ninf: if b == ctx.inf: def g(*args): args = list(args) k = args[dim] if k: s = f(*args) args[dim] = -k s += f(*args) return s else: return f(*args) else: def g(*args): args = list(args) args[dim] = b - args[dim] return f(*args) else: def g(*args): args = list(args) args[dim] += a return f(*args) #print "Standardized infinity along dimension", dim, a, b return standardize_infinite(ctx, g, intervals[:-1]) def fold_infinite(ctx, f, intervals): if len(intervals) < 2: return f dim1 = intervals[-2][0] dim2 = intervals[-1][0] # Assume intervals are [0,inf] x [0,inf] x ... def g(*args): args = list(args) #args.insert(dim2, None) n = int(args[dim1]) s = ctx.zero #y = ctx.mpf(n) args[dim2] = ctx.mpf(n) #y for x in xrange(n+1): args[dim1] = ctx.mpf(x) s += f(*args) args[dim1] = ctx.mpf(n) #ctx.mpf(n) for y in xrange(n): args[dim2] = ctx.mpf(y) s += f(*args) return s #print "Folded infinite from", len(intervals), "to", (len(intervals)-1) return fold_infinite(ctx, g, intervals[:-1]) @defun def nprod(ctx, f, interval, nsum=False, **kwargs): r""" Computes the product .. math :: P = \prod_{k=a}^b f(k) where `(a, b)` = *interval*, and where `a = -\infty` and/or `b = \infty` are allowed. By default, :func:`~mpmath.nprod` uses the same extrapolation methods as :func:`~mpmath.nsum`, except applied to the partial products rather than partial sums, and the same keyword options as for :func:`~mpmath.nsum` are supported. If ``nsum=True``, the product is instead computed via :func:`~mpmath.nsum` as .. math :: P = \exp\left( \sum_{k=a}^b \log(f(k)) \right). This is slower, but can sometimes yield better results. It is also required (and used automatically) when Euler-Maclaurin summation is requested. **Examples** A simple finite product:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> nprod(lambda k: k, [1, 4]) 24.0 A large number of infinite products have known exact values, and can therefore be used as a reference. Most of the following examples are taken from MathWorld [1]. A few infinite products with simple values are:: >>> 2*nprod(lambda k: (4*k**2)/(4*k**2-1), [1, inf]) 3.141592653589793238462643 >>> nprod(lambda k: (1+1/k)**2/(1+2/k), [1, inf]) 2.0 >>> nprod(lambda k: (k**3-1)/(k**3+1), [2, inf]) 0.6666666666666666666666667 >>> nprod(lambda k: (1-1/k**2), [2, inf]) 0.5 Next, several more infinite products with more complicated values:: >>> nprod(lambda k: exp(1/k**2), [1, inf]); exp(pi**2/6) 5.180668317897115748416626 5.180668317897115748416626 >>> nprod(lambda k: (k**2-1)/(k**2+1), [2, inf]); pi*csch(pi) 0.2720290549821331629502366 0.2720290549821331629502366 >>> nprod(lambda k: (k**4-1)/(k**4+1), [2, inf]) 0.8480540493529003921296502 >>> pi*sinh(pi)/(cosh(sqrt(2)*pi)-cos(sqrt(2)*pi)) 0.8480540493529003921296502 >>> nprod(lambda k: (1+1/k+1/k**2)**2/(1+2/k+3/k**2), [1, inf]) 1.848936182858244485224927 >>> 3*sqrt(2)*cosh(pi*sqrt(3)/2)**2*csch(pi*sqrt(2))/pi 1.848936182858244485224927 >>> nprod(lambda k: (1-1/k**4), [2, inf]); sinh(pi)/(4*pi) 0.9190194775937444301739244 0.9190194775937444301739244 >>> nprod(lambda k: (1-1/k**6), [2, inf]) 0.9826842777421925183244759 >>> (1+cosh(pi*sqrt(3)))/(12*pi**2) 0.9826842777421925183244759 >>> nprod(lambda k: (1+1/k**2), [2, inf]); sinh(pi)/(2*pi) 1.838038955187488860347849 1.838038955187488860347849 >>> nprod(lambda n: (1+1/n)**n * exp(1/(2*n)-1), [1, inf]) 1.447255926890365298959138 >>> exp(1+euler/2)/sqrt(2*pi) 1.447255926890365298959138 The following two products are equivalent and can be evaluated in terms of a Jacobi theta function. Pi can be replaced by any value (as long as convergence is preserved):: >>> nprod(lambda k: (1-pi**-k)/(1+pi**-k), [1, inf]) 0.3838451207481672404778686 >>> nprod(lambda k: tanh(k*log(pi)/2), [1, inf]) 0.3838451207481672404778686 >>> jtheta(4,0,1/pi) 0.3838451207481672404778686 This product does not have a known closed form value:: >>> nprod(lambda k: (1-1/2**k), [1, inf]) 0.2887880950866024212788997 A product taken from `-\infty`:: >>> nprod(lambda k: 1-k**(-3), [-inf,-2]) 0.8093965973662901095786805 >>> cosh(pi*sqrt(3)/2)/(3*pi) 0.8093965973662901095786805 A doubly infinite product:: >>> nprod(lambda k: exp(1/(1+k**2)), [-inf, inf]) 23.41432688231864337420035 >>> exp(pi/tanh(pi)) 23.41432688231864337420035 A product requiring the use of Euler-Maclaurin summation to compute an accurate value:: >>> nprod(lambda k: (1-1/k**2.5), [2, inf], method='e') 0.696155111336231052898125 **References** 1. [Weisstein]_ http://mathworld.wolfram.com/InfiniteProduct.html """ if nsum or ('e' in kwargs.get('method', '')): orig = ctx.prec try: # TODO: we are evaluating log(1+eps) -> eps, which is # inaccurate. This currently works because nsum greatly # increases the working precision. But we should be # more intelligent and handle the precision here. ctx.prec += 10 v = ctx.nsum(lambda n: ctx.ln(f(n)), interval, **kwargs) finally: ctx.prec = orig return +ctx.exp(v) a, b = ctx._as_points(interval) if a == ctx.ninf: if b == ctx.inf: return f(0) * ctx.nprod(lambda k: f(-k) * f(k), [1, ctx.inf], **kwargs) return ctx.nprod(f, [-b, ctx.inf], **kwargs) elif b != ctx.inf: return ctx.fprod(f(ctx.mpf(k)) for k in xrange(int(a), int(b)+1)) a = int(a) def update(partial_products, indices): if partial_products: pprod = partial_products[-1] else: pprod = ctx.one for k in indices: pprod = pprod * f(a + ctx.mpf(k)) partial_products.append(pprod) return +ctx.adaptive_extrapolation(update, None, kwargs) @defun def limit(ctx, f, x, direction=1, exp=False, **kwargs): r""" Computes an estimate of the limit .. math :: \lim_{t \to x} f(t) where `x` may be finite or infinite. For finite `x`, :func:`~mpmath.limit` evaluates `f(x + d/n)` for consecutive integer values of `n`, where the approach direction `d` may be specified using the *direction* keyword argument. For infinite `x`, :func:`~mpmath.limit` evaluates values of `f(\mathrm{sign}(x) \cdot n)`. If the approach to the limit is not sufficiently fast to give an accurate estimate directly, :func:`~mpmath.limit` attempts to find the limit using Richardson extrapolation or the Shanks transformation. You can select between these methods using the *method* keyword (see documentation of :func:`~mpmath.nsum` for more information). **Options** The following options are available with essentially the same meaning as for :func:`~mpmath.nsum`: *tol*, *method*, *maxterms*, *steps*, *verbose*. If the option *exp=True* is set, `f` will be sampled at exponentially spaced points `n = 2^1, 2^2, 2^3, \ldots` instead of the linearly spaced points `n = 1, 2, 3, \ldots`. This can sometimes improve the rate of convergence so that :func:`~mpmath.limit` may return a more accurate answer (and faster). However, do note that this can only be used if `f` supports fast and accurate evaluation for arguments that are extremely close to the limit point (or if infinite, very large arguments). **Examples** A basic evaluation of a removable singularity:: >>> from mpmath import * >>> mp.dps = 30; mp.pretty = True >>> limit(lambda x: (x-sin(x))/x**3, 0) 0.166666666666666666666666666667 Computing the exponential function using its limit definition:: >>> limit(lambda n: (1+3/n)**n, inf) 20.0855369231876677409285296546 >>> exp(3) 20.0855369231876677409285296546 A limit for `\pi`:: >>> f = lambda n: 2**(4*n+1)*fac(n)**4/(2*n+1)/fac(2*n)**2 >>> limit(f, inf) 3.14159265358979323846264338328 Calculating the coefficient in Stirling's formula:: >>> limit(lambda n: fac(n) / (sqrt(n)*(n/e)**n), inf) 2.50662827463100050241576528481 >>> sqrt(2*pi) 2.50662827463100050241576528481 Evaluating Euler's constant `\gamma` using the limit representation .. math :: \gamma = \lim_{n \rightarrow \infty } \left[ \left( \sum_{k=1}^n \frac{1}{k} \right) - \log(n) \right] (which converges notoriously slowly):: >>> f = lambda n: sum([mpf(1)/k for k in range(1,int(n)+1)]) - log(n) >>> limit(f, inf) 0.577215664901532860606512090082 >>> +euler 0.577215664901532860606512090082 With default settings, the following limit converges too slowly to be evaluated accurately. Changing to exponential sampling however gives a perfect result:: >>> f = lambda x: sqrt(x**3+x**2)/(sqrt(x**3)+x) >>> limit(f, inf) 0.992831158558330281129249686491 >>> limit(f, inf, exp=True) 1.0 """ if ctx.isinf(x): direction = ctx.sign(x) g = lambda k: f(ctx.mpf(k+1)*direction) else: direction *= ctx.one g = lambda k: f(x + direction/(k+1)) if exp: h = g g = lambda k: h(2**k) def update(values, indices): for k in indices: values.append(g(k+1)) # XXX: steps used by nsum don't work well if not 'steps' in kwargs: kwargs['steps'] = [10] return +ctx.adaptive_extrapolation(update, None, kwargs) mpmath-1.1.0/mpmath/calculus/inverselaplace.py000066400000000000000000000746371340375245600215010ustar00rootroot00000000000000# contributed to mpmath by Kristopher L. Kuhlman, February 2017 class InverseLaplaceTransform(object): r""" Inverse Laplace transform methods are implemented using this class, in order to simplify the code and provide a common infrastructure. Implement a custom inverse Laplace transform algorithm by subclassing :class:`InverseLaplaceTransform` and implementing the appropriate methods. The subclass can then be used by :func:`~mpmath.invertlaplace` by passing it as the *method* argument. """ def __init__(self,ctx): self.ctx = ctx def calc_laplace_parameter(self,t,**kwargs): r""" Determine the vector of Laplace parameter values needed for an algorithm, this will depend on the choice of algorithm (de Hoog is default), the algorithm-specific parameters passed (or default ones), and desired time. """ raise NotImplementedError def calc_time_domain_solution(self,fp): r""" Compute the time domain solution, after computing the Laplace-space function evaluations at the abscissa required for the algorithm. Abscissa computed for one algorithm are typically not useful for another algorithm. """ raise NotImplementedError class FixedTalbot(InverseLaplaceTransform): def calc_laplace_parameter(self,t,**kwargs): r"""The "fixed" Talbot method deforms the Bromwich contour towards `-\infty` in the shape of a parabola. Traditionally the Talbot algorithm has adjustable parameters, but the "fixed" version does not. The `r` parameter could be passed in as a parameter, if you want to override the default given by (Abate & Valko, 2004). The Laplace parameter is sampled along a parabola opening along the negative imaginary axis, with the base of the parabola along the real axis at `p=\frac{r}{t_\mathrm{max}}`. As the number of terms used in the approximation (degree) grows, the abscissa required for function evaluation tend towards `-\infty`, requiring high precision to prevent overflow. If any poles, branch cuts or other singularities exist such that the deformed Bromwich contour lies to the left of the singularity, the method will fail. **Optional arguments** :class:`~mpmath.calculus.inverselaplace.FixedTalbot.calc_laplace_parameter` recognizes the following keywords *tmax* maximum time associated with vector of times (typically just the time requested) *degree* integer order of approximation (M = number of terms) *r* abscissa for `p_0` (otherwise computed using rule of thumb `2M/5`) The working precision will be increased according to a rule of thumb. If 'degree' is not specified, the working precision and degree are chosen to hopefully achieve the dps of the calling context. If 'degree' is specified, the working precision is chosen to achieve maximum resulting precision for the specified degree. .. math :: p_0=\frac{r}{t} .. math :: p_i=\frac{i r \pi}{Mt_\mathrm{max}}\left[\cot\left( \frac{i\pi}{M}\right) + j \right] \qquad 1\le i 0: self.degree += 1 M = self.degree # this is adjusting the dps of the calling context # hopefully the caller doesn't monkey around with it # between calling this routine and calc_time_domain_solution() self.dps_orig = self.ctx.dps self.ctx.dps = self.dps_goal self.V = self._coeff() self.p = self.ctx.matrix(self.ctx.arange(1,M+1))*self.ctx.ln2/self.t # NB: p is real (mpf) def _coeff(self): r"""Salzer summation weights (aka, "Stehfest coefficients") only depend on the approximation order (M) and the precision""" M = self.degree M2 = int(M/2) # checked earlier that M is even V = self.ctx.matrix(M,1) # Salzer summation weights # get very large in magnitude and oscillate in sign, # if the precision is not high enough, there will be # catastrophic cancellation for k in range(1,M+1): z = self.ctx.matrix(min(k,M2)+1,1) for j in range(int((k+1)/2),min(k,M2)+1): z[j] = (self.ctx.power(j,M2)*self.ctx.fac(2*j)/ (self.ctx.fac(M2-j)*self.ctx.fac(j)* self.ctx.fac(j-1)*self.ctx.fac(k-j)* self.ctx.fac(2*j-k))) V[k-1] = self.ctx.power(-1,k+M2)*self.ctx.fsum(z) return V def calc_time_domain_solution(self,fp,t,manual_prec=False): r"""Compute time-domain Stehfest algorithm solution. .. math :: f(t,M) = \frac{\log 2}{t} \sum_{k=1}^{M} V_k \bar{f}\left( p_k \right) where .. math :: V_k = (-1)^{k + N/2} \sum^{\min(k,N/2)}_{i=\lfloor(k+1)/2 \rfloor} \frac{i^{\frac{N}{2}}(2i)!}{\left(\frac{N}{2}-i \right)! \, i! \, \left(i-1 \right)! \, \left(k-i\right)! \, \left(2i-k \right)!} As the degree increases, the abscissa (`p_k`) only increase linearly towards `\infty`, but the Stehfest coefficients (`V_k`) alternate in sign and increase rapidly in sign, requiring high precision to prevent overflow or loss of significance when evaluating the sum. **References** 1. Widder, D. (1941). *The Laplace Transform*. Princeton. 2. Stehfest, H. (1970). Algorithm 368: numerical inversion of Laplace transforms. *Communications of the ACM* 13(1):47-49, http://dx.doi.org/10.1145/361953.361969 """ # required self.t = self.ctx.convert(t) # assume fp was computed from p matrix returned from # calc_laplace_parameter(), so is already # a list or matrix of mpmath 'mpf' types result = self.ctx.fdot(self.V,fp)*self.ctx.ln2/self.t # setting dps back to value when calc_laplace_parameter was called if not manual_prec: self.ctx.dps = self.dps_orig # ignore any small imaginary part return result.real # **************************************** class deHoog(InverseLaplaceTransform): def calc_laplace_parameter(self,t,**kwargs): r"""the de Hoog, Knight & Stokes algorithm is an accelerated form of the Fourier series numerical inverse Laplace transform algorithms. .. math :: p_k = \gamma + \frac{jk}{T} \qquad 0 \le k < 2M+1 where .. math :: \gamma = \alpha - \frac{\log \mathrm{tol}}{2T}, `j=\sqrt{-1}`, `T = 2t_\mathrm{max}` is a scaled time, `\alpha=10^{-\mathrm{dps\_goal}}` is the real part of the rightmost pole or singularity, which is chosen based on the desired accuracy (assuming the rightmost singularity is 0), and `\mathrm{tol}=10\alpha` is the desired tolerance, which is chosen in relation to `\alpha`.` When increasing the degree, the abscissa increase towards `j\infty`, but more slowly than the fixed Talbot algorithm. The de Hoog et al. algorithm typically does better with oscillatory functions of time, and less well-behaved functions. The method tends to be slower than the Talbot and Stehfest algorithsm, especially so at very high precision (e.g., `>500` digits precision). """ # required # ------------------------------ self.t = self.ctx.convert(t) # optional # ------------------------------ self.tmax = kwargs.get('tmax',self.t) # empirical relationships used here based on a linear fit of # requested and delivered dps for exponentially decaying time # functions for requested dps up to 512. if 'degree' in kwargs: self.degree = kwargs['degree'] self.dps_goal = int(1.38*self.degree) else: self.dps_goal = int(self.ctx.dps*1.36) self.degree = max(10,self.dps_goal) # 2*M+1 terms in approximation M = self.degree # adjust alpha component of abscissa of convergence for higher # precision tmp = self.ctx.power(10.0,-self.dps_goal) self.alpha = self.ctx.convert(kwargs.get('alpha',tmp)) # desired tolerance (here simply related to alpha) self.tol = self.ctx.convert(kwargs.get('tol',self.alpha*10.0)) self.np = 2*self.degree+1 # number of terms in approximation # this is adjusting the dps of the calling context # hopefully the caller doesn't monkey around with it # between calling this routine and calc_time_domain_solution() self.dps_orig = self.ctx.dps self.ctx.dps = self.dps_goal # scaling factor (likely tun-able, but 2 is typical) self.scale = kwargs.get('scale',2) self.T = self.ctx.convert(kwargs.get('T',self.scale*self.tmax)) self.p = self.ctx.matrix(2*M+1,1) self.gamma = self.alpha - self.ctx.log(self.tol)/(self.scale*self.T) self.p = (self.gamma + self.ctx.pi* self.ctx.matrix(self.ctx.arange(self.np))/self.T*1j) # NB: p is complex (mpc) def calc_time_domain_solution(self,fp,t,manual_prec=False): r"""Calculate time-domain solution for de Hoog, Knight & Stokes algorithm. The un-accelerated Fourier series approach is: .. math :: f(t,2M+1) = \frac{e^{\gamma t}}{T} \sum_{k=0}^{2M}{}^{'} \Re\left[\bar{f}\left( p_k \right) e^{i\pi t/T} \right], where the prime on the summation indicates the first term is halved. This simplistic approach requires so many function evaluations that it is not practical. Non-linear acceleration is accomplished via Pade-approximation and an analytic expression for the remainder of the continued fraction. See the original paper (reference 2 below) a detailed description of the numerical approach. **References** 1. Davies, B. (2005). *Integral Transforms and their Applications*, Third Edition. Springer. 2. de Hoog, F., J. Knight, A. Stokes (1982). An improved method for numerical inversion of Laplace transforms. *SIAM Journal of Scientific and Statistical Computing* 3:357-366, http://dx.doi.org/10.1137/0903022 """ M = self.degree np = self.np T = self.T self.t = self.ctx.convert(t) # would it be useful to try re-using # space between e&q and A&B? e = self.ctx.zeros(np,M+1) q = self.ctx.matrix(np,M) d = self.ctx.matrix(np,1) A = self.ctx.zeros(np+2,1) B = self.ctx.ones(np+2,1) # initialize Q-D table # e[0:2*M,0] = 0.0 + 0.0j q[0,0] = fp[1]/(fp[0]/2) for i in range(1,2*M): q[i,0] = fp[i+1]/fp[i] # rhombus rule for filling triangular Q-D table (e & q) for r in range(1,M+1): # start with e, column 1, 0:2*M-2 mr = 2*(M-r) e[0:mr,r] = q[1:mr+1,r-1] - q[0:mr,r-1] + e[1:mr+1,r-1] if not r == M: rq = r+1 mr = 2*(M-rq)+1 for i in range(mr): q[i,rq-1] = q[i+1,rq-2]*e[i+1,rq-1]/e[i,rq-1] # build up continued fraction coefficients (d) d[0] = fp[0]/2 for r in range(1,M+1): d[2*r-1] = -q[0,r-1] # even terms d[2*r] = -e[0,r] # odd terms # seed A and B for recurrence #A[0] = 0.0 + 0.0j A[1] = d[0] #B[0:2] = 1.0 + 0.0j # base of the power series z = self.ctx.expjpi(self.t/T) # i*pi is already in fcn # coefficients of Pade approximation (A & B) # using recurrence for all but last term for i in range(1,2*M): A[i+1] = A[i] + d[i]*A[i-1]*z B[i+1] = B[i] + d[i]*B[i-1]*z # "improved remainder" to continued fraction brem = (1 + (d[2*M-1] - d[2*M])*z)/2 # powm1(x,y) computes x^y - 1 more accurately near zero rem = brem*self.ctx.powm1(1 + d[2*M]*z/brem, self.ctx.fraction(1,2)) # last term of recurrence using new remainder A[np] = A[2*M] + rem*A[2*M-1] B[np] = B[2*M] + rem*B[2*M-1] # diagonal Pade approximation # F=A/B represents accelerated trapezoid rule result = self.ctx.exp(self.gamma*self.t)/T*(A[np]/B[np]).real # setting dps back to value when calc_laplace_parameter was called if not manual_prec: self.ctx.dps = self.dps_orig return result # **************************************** class LaplaceTransformInversionMethods(object): def __init__(ctx, *args, **kwargs): ctx._fixed_talbot = FixedTalbot(ctx) ctx._stehfest = Stehfest(ctx) ctx._de_hoog = deHoog(ctx) def invertlaplace(ctx, f, t, **kwargs): r"""Computes the numerical inverse Laplace transform for a Laplace-space function at a given time. The function being evaluated is assumed to be a real-valued function of time. The user must supply a Laplace-space function `\bar{f}(p)`, and a desired time at which to estimate the time-domain solution `f(t)`. A few basic examples of Laplace-space functions with known inverses (see references [1,2]) : .. math :: \mathcal{L}\left\lbrace f(t) \right\rbrace=\bar{f}(p) .. math :: \mathcal{L}^{-1}\left\lbrace \bar{f}(p) \right\rbrace = f(t) .. math :: \bar{f}(p) = \frac{1}{(p+1)^2} .. math :: f(t) = t e^{-t} >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> tt = [0.001, 0.01, 0.1, 1, 10] >>> fp = lambda p: 1/(p+1)**2 >>> ft = lambda t: t*exp(-t) >>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='talbot') (0.000999000499833375, 8.57923043561212e-20) >>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='talbot') (0.00990049833749168, 3.27007646698047e-19) >>> ft(tt[2]),ft(tt[2])-invertlaplace(fp,tt[2],method='talbot') (0.090483741803596, -1.75215800052168e-18) >>> ft(tt[3]),ft(tt[3])-invertlaplace(fp,tt[3],method='talbot') (0.367879441171442, 1.2428864009344e-17) >>> ft(tt[4]),ft(tt[4])-invertlaplace(fp,tt[4],method='talbot') (0.000453999297624849, 4.04513489306658e-20) The methods also work for higher precision: >>> mp.dps = 100; mp.pretty = True >>> nstr(ft(tt[0]),15),nstr(ft(tt[0])-invertlaplace(fp,tt[0],method='talbot'),15) ('0.000999000499833375', '-4.96868310693356e-105') >>> nstr(ft(tt[1]),15),nstr(ft(tt[1])-invertlaplace(fp,tt[1],method='talbot'),15) ('0.00990049833749168', '1.23032291513122e-104') .. math :: \bar{f}(p) = \frac{1}{p^2+1} .. math :: f(t) = \mathrm{J}_0(t) >>> mp.dps = 15; mp.pretty = True >>> fp = lambda p: 1/sqrt(p*p + 1) >>> ft = lambda t: besselj(0,t) >>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0]) (0.999999750000016, -8.2477943034014e-18) >>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1]) (0.99997500015625, -3.69810144898872e-17) .. math :: \bar{f}(p) = \frac{\log p}{p} .. math :: f(t) = -\gamma -\log t >>> mp.dps = 15; mp.pretty = True >>> fp = lambda p: log(p)/p >>> ft = lambda t: -euler-log(t) >>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='stehfest') (6.3305396140806, -1.92126634837863e-16) >>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='stehfest') (4.02795452108656, -4.81486093200704e-16) **Options** :func:`~mpmath.invertlaplace` recognizes the following optional keywords valid for all methods: *method* Chooses numerical inverse Laplace transform algorithm (described below). *degree* Number of terms used in the approximation **Algorithms** Mpmath implements three numerical inverse Laplace transform algorithms, attributed to: Talbot, Stehfest, and de Hoog, Knight and Stokes. These can be selected by using *method='talbot'*, *method='stehfest'*, or *method='dehoog'* or by passing the classes *method=FixedTalbot*, *method=Stehfest*, or *method=deHoog*. The functions :func:`~mpmath.invlaptalbot`, :func:`~mpmath.invlapstehfest`, and :func:`~mpmath.invlapdehoog` are also available as shortcuts. All three algorithms implement a heuristic balance between the requested precision and the precision used internally for the calculations. This has been tuned for a typical exponentially decaying function and precision up to few hundred decimal digits. The Laplace transform converts the variable time (i.e., along a line) into a parameter given by the right half of the complex `p`-plane. Singularities, poles, and branch cuts in the complex `p`-plane contain all the information regarding the time behavior of the corresponding function. Any numerical method must therefore sample `p`-plane "close enough" to the singularities to accurately characterize them, while not getting too close to have catastrophic cancellation, overflow, or underflow issues. Most significantly, if one or more of the singularities in the `p`-plane is not on the left side of the Bromwich contour, its effects will be left out of the computed solution, and the answer will be completely wrong. *Talbot* The fixed Talbot method is high accuracy and fast, but the method can catastrophically fail for certain classes of time-domain behavior, including a Heaviside step function for positive time (e.g., `H(t-2)`), or some oscillatory behaviors. The Talbot method usually has adjustable parameters, but the "fixed" variety implemented here does not. This method deforms the Bromwich integral contour in the shape of a parabola towards `-\infty`, which leads to problems when the solution has a decaying exponential in it (e.g., a Heaviside step function is equivalent to multiplying by a decaying exponential in Laplace space). *Stehfest* The Stehfest algorithm only uses abscissa along the real axis of the complex `p`-plane to estimate the time-domain function. Oscillatory time-domain functions have poles away from the real axis, so this method does not work well with oscillatory functions, especially high-frequency ones. This method also depends on summation of terms in a series that grows very large, and will have catastrophic cancellation during summation if the working precision is too low. *de Hoog et al.* The de Hoog, Knight, and Stokes method is essentially a Fourier-series quadrature-type approximation to the Bromwich contour integral, with non-linear series acceleration and an analytical expression for the remainder term. This method is typically the most robust and is therefore the default method. This method also involves the greatest amount of overhead, so it is typically the slowest of the three methods at high precision. **Singularities** All numerical inverse Laplace transform methods have problems at large time when the Laplace-space function has poles, singularities, or branch cuts to the right of the origin in the complex plane. For simple poles in `\bar{f}(p)` at the `p`-plane origin, the time function is constant in time (e.g., `\mathcal{L}\left\lbrace 1 \right\rbrace=1/p` has a pole at `p=0`). A pole in `\bar{f}(p)` to the left of the origin is a decreasing function of time (e.g., `\mathcal{L}\left\lbrace e^{-t/2} \right\rbrace=1/(p+1/2)` has a pole at `p=-1/2`), and a pole to the right of the origin leads to an increasing function in time (e.g., `\mathcal{L}\left\lbrace t e^{t/4} \right\rbrace = 1/(p-1/4)^2` has a pole at `p=1/4`). When singularities occur off the real `p` axis, the time-domain function is oscillatory. For example `\mathcal{L}\left\lbrace \mathrm{J}_0(t) \right\rbrace=1/\sqrt{p^2+1}` has a branch cut starting at `p=j=\sqrt{-1}` and is a decaying oscillatory function, This range of behaviors is illustrated in Duffy [3] Figure 4.10.4, p. 228. In general as `p \rightarrow \infty` `t \rightarrow 0` and vice-versa. All numerical inverse Laplace transform methods require their abscissa to shift closer to the origin for larger times. If the abscissa shift left of the rightmost singularity in the Laplace domain, the answer will be completely wrong (the effect of singularities to the right of the Bromwich contour are not included in the results). For example, the following exponentially growing function has a pole at `p=3`: .. math :: \bar{f}(p)=\frac{1}{p^2-9} .. math :: f(t)=\frac{1}{3}\sinh 3t >>> mp.dps = 15; mp.pretty = True >>> fp = lambda p: 1/(p*p-9) >>> ft = lambda t: sinh(3*t)/3 >>> tt = [0.01,0.1,1.0,10.0] >>> ft(tt[0]),invertlaplace(fp,tt[0],method='talbot') (0.0100015000675014, 0.0100015000675014) >>> ft(tt[1]),invertlaplace(fp,tt[1],method='talbot') (0.101506764482381, 0.101506764482381) >>> ft(tt[2]),invertlaplace(fp,tt[2],method='talbot') (3.33929164246997, 3.33929164246997) >>> ft(tt[3]),invertlaplace(fp,tt[3],method='talbot') (1781079096920.74, -1.61331069624091e-14) **References** 1. [DLMF]_ section 1.14 (http://dlmf.nist.gov/1.14T4) 2. Cohen, A.M. (2007). Numerical Methods for Laplace Transform Inversion, Springer. 3. Duffy, D.G. (1998). Advanced Engineering Mathematics, CRC Press. **Numerical Inverse Laplace Transform Reviews** 1. Bellman, R., R.E. Kalaba, J.A. Lockett (1966). *Numerical inversion of the Laplace transform: Applications to Biology, Economics, Engineering, and Physics*. Elsevier. 2. Davies, B., B. Martin (1979). Numerical inversion of the Laplace transform: a survey and comparison of methods. *Journal of Computational Physics* 33:1-32, http://dx.doi.org/10.1016/0021-9991(79)90025-1 3. Duffy, D.G. (1993). On the numerical inversion of Laplace transforms: Comparison of three new methods on characteristic problems from applications. *ACM Transactions on Mathematical Software* 19(3):333-359, http://dx.doi.org/10.1145/155743.155788 4. Kuhlman, K.L., (2013). Review of Inverse Laplace Transform Algorithms for Laplace-Space Numerical Approaches, *Numerical Algorithms*, 63(2):339-355. http://dx.doi.org/10.1007/s11075-012-9625-3 """ rule = kwargs.get('method','dehoog') if type(rule) is str: lrule = rule.lower() if lrule == 'talbot': rule = ctx._fixed_talbot elif lrule == 'stehfest': rule = ctx._stehfest elif lrule == 'dehoog': rule = ctx._de_hoog else: raise ValueError("unknown invlap algorithm: %s" % rule) else: rule = rule(ctx) # determine the vector of Laplace-space parameter # needed for the requested method and desired time rule.calc_laplace_parameter(t,**kwargs) # compute the Laplace-space function evalutations # at the required abscissa. fp = [f(p) for p in rule.p] # compute the time-domain solution from the # Laplace-space function evaluations return rule.calc_time_domain_solution(fp,t) # shortcuts for the above function for specific methods def invlaptalbot(ctx, *args, **kwargs): kwargs['method'] = 'talbot' return ctx.invertlaplace(*args, **kwargs) def invlapstehfest(ctx, *args, **kwargs): kwargs['method'] = 'stehfest' return ctx.invertlaplace(*args, **kwargs) def invlapdehoog(ctx, *args, **kwargs): kwargs['method'] = 'dehoog' return ctx.invertlaplace(*args, **kwargs) # **************************************** if __name__ == '__main__': import doctest doctest.testmod() mpmath-1.1.0/mpmath/calculus/odes.py000066400000000000000000000232641340375245600174240ustar00rootroot00000000000000from bisect import bisect from ..libmp.backend import xrange class ODEMethods(object): pass def ode_taylor(ctx, derivs, x0, y0, tol_prec, n): h = tol = ctx.ldexp(1, -tol_prec) dim = len(y0) xs = [x0] ys = [y0] x = x0 y = y0 orig = ctx.prec try: ctx.prec = orig*(1+n) # Use n steps with Euler's method to get # evaluation points for derivatives for i in range(n): fxy = derivs(x, y) y = [y[i]+h*fxy[i] for i in xrange(len(y))] x += h xs.append(x) ys.append(y) # Compute derivatives ser = [[] for d in range(dim)] for j in range(n+1): s = [0]*dim b = (-1) ** (j & 1) k = 1 for i in range(j+1): for d in range(dim): s[d] += b * ys[i][d] b = (b * (j-k+1)) // (-k) k += 1 scale = h**(-j) / ctx.fac(j) for d in range(dim): s[d] = s[d] * scale ser[d].append(s[d]) finally: ctx.prec = orig # Estimate radius for which we can get full accuracy. # XXX: do this right for zeros radius = ctx.one for ts in ser: if ts[-1]: radius = min(radius, ctx.nthroot(tol/abs(ts[-1]), n)) radius /= 2 # XXX return ser, x0+radius def odefun(ctx, F, x0, y0, tol=None, degree=None, method='taylor', verbose=False): r""" Returns a function `y(x) = [y_0(x), y_1(x), \ldots, y_n(x)]` that is a numerical solution of the `n+1`-dimensional first-order ordinary differential equation (ODE) system .. math :: y_0'(x) = F_0(x, [y_0(x), y_1(x), \ldots, y_n(x)]) y_1'(x) = F_1(x, [y_0(x), y_1(x), \ldots, y_n(x)]) \vdots y_n'(x) = F_n(x, [y_0(x), y_1(x), \ldots, y_n(x)]) The derivatives are specified by the vector-valued function *F* that evaluates `[y_0', \ldots, y_n'] = F(x, [y_0, \ldots, y_n])`. The initial point `x_0` is specified by the scalar argument *x0*, and the initial value `y(x_0) = [y_0(x_0), \ldots, y_n(x_0)]` is specified by the vector argument *y0*. For convenience, if the system is one-dimensional, you may optionally provide just a scalar value for *y0*. In this case, *F* should accept a scalar *y* argument and return a scalar. The solution function *y* will return scalar values instead of length-1 vectors. Evaluation of the solution function `y(x)` is permitted for any `x \ge x_0`. A high-order ODE can be solved by transforming it into first-order vector form. This transformation is described in standard texts on ODEs. Examples will also be given below. **Options, speed and accuracy** By default, :func:`~mpmath.odefun` uses a high-order Taylor series method. For reasonably well-behaved problems, the solution will be fully accurate to within the working precision. Note that *F* must be possible to evaluate to very high precision for the generation of Taylor series to work. To get a faster but less accurate solution, you can set a large value for *tol* (which defaults roughly to *eps*). If you just want to plot the solution or perform a basic simulation, *tol = 0.01* is likely sufficient. The *degree* argument controls the degree of the solver (with *method='taylor'*, this is the degree of the Taylor series expansion). A higher degree means that a longer step can be taken before a new local solution must be generated from *F*, meaning that fewer steps are required to get from `x_0` to a given `x_1`. On the other hand, a higher degree also means that each local solution becomes more expensive (i.e., more evaluations of *F* are required per step, and at higher precision). The optimal setting therefore involves a tradeoff. Generally, decreasing the *degree* for Taylor series is likely to give faster solution at low precision, while increasing is likely to be better at higher precision. The function object returned by :func:`~mpmath.odefun` caches the solutions at all step points and uses polynomial interpolation between step points. Therefore, once `y(x_1)` has been evaluated for some `x_1`, `y(x)` can be evaluated very quickly for any `x_0 \le x \le x_1`. and continuing the evaluation up to `x_2 > x_1` is also fast. **Examples of first-order ODEs** We will solve the standard test problem `y'(x) = y(x), y(0) = 1` which has explicit solution `y(x) = \exp(x)`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> f = odefun(lambda x, y: y, 0, 1) >>> for x in [0, 1, 2.5]: ... print((f(x), exp(x))) ... (1.0, 1.0) (2.71828182845905, 2.71828182845905) (12.1824939607035, 12.1824939607035) The solution with high precision:: >>> mp.dps = 50 >>> f = odefun(lambda x, y: y, 0, 1) >>> f(1) 2.7182818284590452353602874713526624977572470937 >>> exp(1) 2.7182818284590452353602874713526624977572470937 Using the more general vectorized form, the test problem can be input as (note that *f* returns a 1-element vector):: >>> mp.dps = 15 >>> f = odefun(lambda x, y: [y[0]], 0, [1]) >>> f(1) [2.71828182845905] :func:`~mpmath.odefun` can solve nonlinear ODEs, which are generally impossible (and at best difficult) to solve analytically. As an example of a nonlinear ODE, we will solve `y'(x) = x \sin(y(x))` for `y(0) = \pi/2`. An exact solution happens to be known for this problem, and is given by `y(x) = 2 \tan^{-1}\left(\exp\left(x^2/2\right)\right)`:: >>> f = odefun(lambda x, y: x*sin(y), 0, pi/2) >>> for x in [2, 5, 10]: ... print((f(x), 2*atan(exp(mpf(x)**2/2)))) ... (2.87255666284091, 2.87255666284091) (3.14158520028345, 3.14158520028345) (3.14159265358979, 3.14159265358979) If `F` is independent of `y`, an ODE can be solved using direct integration. We can therefore obtain a reference solution with :func:`~mpmath.quad`:: >>> f = lambda x: (1+x**2)/(1+x**3) >>> g = odefun(lambda x, y: f(x), pi, 0) >>> g(2*pi) 0.72128263801696 >>> quad(f, [pi, 2*pi]) 0.72128263801696 **Examples of second-order ODEs** We will solve the harmonic oscillator equation `y''(x) + y(x) = 0`. To do this, we introduce the helper functions `y_0 = y, y_1 = y_0'` whereby the original equation can be written as `y_1' + y_0' = 0`. Put together, we get the first-order, two-dimensional vector ODE .. math :: \begin{cases} y_0' = y_1 \\ y_1' = -y_0 \end{cases} To get a well-defined IVP, we need two initial values. With `y(0) = y_0(0) = 1` and `-y'(0) = y_1(0) = 0`, the problem will of course be solved by `y(x) = y_0(x) = \cos(x)` and `-y'(x) = y_1(x) = \sin(x)`. We check this:: >>> f = odefun(lambda x, y: [-y[1], y[0]], 0, [1, 0]) >>> for x in [0, 1, 2.5, 10]: ... nprint(f(x), 15) ... nprint([cos(x), sin(x)], 15) ... print("---") ... [1.0, 0.0] [1.0, 0.0] --- [0.54030230586814, 0.841470984807897] [0.54030230586814, 0.841470984807897] --- [-0.801143615546934, 0.598472144103957] [-0.801143615546934, 0.598472144103957] --- [-0.839071529076452, -0.54402111088937] [-0.839071529076452, -0.54402111088937] --- Note that we get both the sine and the cosine solutions simultaneously. **TODO** * Better automatic choice of degree and step size * Make determination of Taylor series convergence radius more robust * Allow solution for `x < x_0` * Allow solution for complex `x` * Test for difficult (ill-conditioned) problems * Implement Runge-Kutta and other algorithms """ if tol: tol_prec = int(-ctx.log(tol, 2))+10 else: tol_prec = ctx.prec+10 degree = degree or (3 + int(3*ctx.dps/2.)) workprec = ctx.prec + 40 try: len(y0) return_vector = True except TypeError: F_ = F F = lambda x, y: [F_(x, y[0])] y0 = [y0] return_vector = False ser, xb = ode_taylor(ctx, F, x0, y0, tol_prec, degree) series_boundaries = [x0, xb] series_data = [(ser, x0, xb)] # We will be working with vectors of Taylor series def mpolyval(ser, a): return [ctx.polyval(s[::-1], a) for s in ser] # Find nearest expansion point; compute if necessary def get_series(x): if x < x0: raise ValueError n = bisect(series_boundaries, x) if n < len(series_boundaries): return series_data[n-1] while 1: ser, xa, xb = series_data[-1] if verbose: print("Computing Taylor series for [%f, %f]" % (xa, xb)) y = mpolyval(ser, xb-xa) xa = xb ser, xb = ode_taylor(ctx, F, xb, y, tol_prec, degree) series_boundaries.append(xb) series_data.append((ser, xa, xb)) if x <= xb: return series_data[-1] # Evaluation function def interpolant(x): x = ctx.convert(x) orig = ctx.prec try: ctx.prec = workprec ser, xa, xb = get_series(x) y = mpolyval(ser, x-xa) finally: ctx.prec = orig if return_vector: return [+yk for yk in y] else: return +y[0] return interpolant ODEMethods.odefun = odefun if __name__ == "__main__": import doctest doctest.testmod() mpmath-1.1.0/mpmath/calculus/optimization.py000066400000000000000000000772431340375245600212260ustar00rootroot00000000000000from copy import copy from ..libmp.backend import xrange, print_ class OptimizationMethods(object): def __init__(ctx): pass ############## # 1D-SOLVERS # ############## class Newton: """ 1d-solver generating pairs of approximative root and error. Needs starting points x0 close to the root. Pro: * converges fast * sometimes more robust than secant with bad second starting point Contra: * converges slowly for multiple roots * needs first derivative * 2 function evaluations per iteration """ maxsteps = 20 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if len(x0) == 1: self.x0 = x0[0] else: raise ValueError('expected 1 starting point, got %i' % len(x0)) self.f = f if not 'df' in kwargs: def df(x): return self.ctx.diff(f, x) else: df = kwargs['df'] self.df = df def __iter__(self): f = self.f df = self.df x0 = self.x0 while True: x1 = x0 - f(x0) / df(x0) error = abs(x1 - x0) x0 = x1 yield (x1, error) class Secant: """ 1d-solver generating pairs of approximative root and error. Needs starting points x0 and x1 close to the root. x1 defaults to x0 + 0.25. Pro: * converges fast Contra: * converges slowly for multiple roots """ maxsteps = 30 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if len(x0) == 1: self.x0 = x0[0] self.x1 = self.x0 + 0.25 elif len(x0) == 2: self.x0 = x0[0] self.x1 = x0[1] else: raise ValueError('expected 1 or 2 starting points, got %i' % len(x0)) self.f = f def __iter__(self): f = self.f x0 = self.x0 x1 = self.x1 f0 = f(x0) while True: f1 = f(x1) l = x1 - x0 if not l: break s = (f1 - f0) / l if not s: break x0, x1 = x1, x1 - f1/s f0 = f1 yield x1, abs(l) class MNewton: """ 1d-solver generating pairs of approximative root and error. Needs starting point x0 close to the root. Uses modified Newton's method that converges fast regardless of the multiplicity of the root. Pro: * converges fast for multiple roots Contra: * needs first and second derivative of f * 3 function evaluations per iteration """ maxsteps = 20 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if not len(x0) == 1: raise ValueError('expected 1 starting point, got %i' % len(x0)) self.x0 = x0[0] self.f = f if not 'df' in kwargs: def df(x): return self.ctx.diff(f, x) else: df = kwargs['df'] self.df = df if not 'd2f' in kwargs: def d2f(x): return self.ctx.diff(df, x) else: d2f = kwargs['df'] self.d2f = d2f def __iter__(self): x = self.x0 f = self.f df = self.df d2f = self.d2f while True: prevx = x fx = f(x) if fx == 0: break dfx = df(x) d2fx = d2f(x) # x = x - F(x)/F'(x) with F(x) = f(x)/f'(x) x -= fx / (dfx - fx * d2fx / dfx) error = abs(x - prevx) yield x, error class Halley: """ 1d-solver generating pairs of approximative root and error. Needs a starting point x0 close to the root. Uses Halley's method with cubic convergence rate. Pro: * converges even faster the Newton's method * useful when computing with *many* digits Contra: * needs first and second derivative of f * 3 function evaluations per iteration * converges slowly for multiple roots """ maxsteps = 20 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if not len(x0) == 1: raise ValueError('expected 1 starting point, got %i' % len(x0)) self.x0 = x0[0] self.f = f if not 'df' in kwargs: def df(x): return self.ctx.diff(f, x) else: df = kwargs['df'] self.df = df if not 'd2f' in kwargs: def d2f(x): return self.ctx.diff(df, x) else: d2f = kwargs['df'] self.d2f = d2f def __iter__(self): x = self.x0 f = self.f df = self.df d2f = self.d2f while True: prevx = x fx = f(x) dfx = df(x) d2fx = d2f(x) x -= 2*fx*dfx / (2*dfx**2 - fx*d2fx) error = abs(x - prevx) yield x, error class Muller: """ 1d-solver generating pairs of approximative root and error. Needs starting points x0, x1 and x2 close to the root. x1 defaults to x0 + 0.25; x2 to x1 + 0.25. Uses Muller's method that converges towards complex roots. Pro: * converges fast (somewhat faster than secant) * can find complex roots Contra: * converges slowly for multiple roots * may have complex values for real starting points and real roots http://en.wikipedia.org/wiki/Muller's_method """ maxsteps = 30 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if len(x0) == 1: self.x0 = x0[0] self.x1 = self.x0 + 0.25 self.x2 = self.x1 + 0.25 elif len(x0) == 2: self.x0 = x0[0] self.x1 = x0[1] self.x2 = self.x1 + 0.25 elif len(x0) == 3: self.x0 = x0[0] self.x1 = x0[1] self.x2 = x0[2] else: raise ValueError('expected 1, 2 or 3 starting points, got %i' % len(x0)) self.f = f self.verbose = kwargs['verbose'] def __iter__(self): f = self.f x0 = self.x0 x1 = self.x1 x2 = self.x2 fx0 = f(x0) fx1 = f(x1) fx2 = f(x2) while True: # TODO: maybe refactoring with function for divided differences # calculate divided differences fx2x1 = (fx1 - fx2) / (x1 - x2) fx2x0 = (fx0 - fx2) / (x0 - x2) fx1x0 = (fx0 - fx1) / (x0 - x1) w = fx2x1 + fx2x0 - fx1x0 fx2x1x0 = (fx1x0 - fx2x1) / (x0 - x2) if w == 0 and fx2x1x0 == 0: if self.verbose: print_('canceled with') print_('x0 =', x0, ', x1 =', x1, 'and x2 =', x2) break x0 = x1 fx0 = fx1 x1 = x2 fx1 = fx2 # denominator should be as large as possible => choose sign r = self.ctx.sqrt(w**2 - 4*fx2*fx2x1x0) if abs(w - r) > abs(w + r): r = -r x2 -= 2*fx2 / (w + r) fx2 = f(x2) error = abs(x2 - x1) yield x2, error # TODO: consider raising a ValueError when there's no sign change in a and b class Bisection: """ 1d-solver generating pairs of approximative root and error. Uses bisection method to find a root of f in [a, b]. Might fail for multiple roots (needs sign change). Pro: * robust and reliable Contra: * converges slowly * needs sign change """ maxsteps = 100 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if len(x0) != 2: raise ValueError('expected interval of 2 points, got %i' % len(x0)) self.f = f self.a = x0[0] self.b = x0[1] def __iter__(self): f = self.f a = self.a b = self.b l = b - a fb = f(b) while True: m = self.ctx.ldexp(a + b, -1) fm = f(m) sign = fm * fb if sign < 0: a = m elif sign > 0: b = m fb = fm else: yield m, self.ctx.zero l /= 2 yield (a + b)/2, abs(l) def _getm(method): """ Return a function to calculate m for Illinois-like methods. """ if method == 'illinois': def getm(fz, fb): return 0.5 elif method == 'pegasus': def getm(fz, fb): return fb/(fb + fz) elif method == 'anderson': def getm(fz, fb): m = 1 - fz/fb if m > 0: return m else: return 0.5 else: raise ValueError("method '%s' not recognized" % method) return getm class Illinois: """ 1d-solver generating pairs of approximative root and error. Uses Illinois method or similar to find a root of f in [a, b]. Might fail for multiple roots (needs sign change). Combines bisect with secant (improved regula falsi). The only difference between the methods is the scaling factor m, which is used to ensure convergence (you can choose one using the 'method' keyword): Illinois method ('illinois'): m = 0.5 Pegasus method ('pegasus'): m = fb/(fb + fz) Anderson-Bjoerk method ('anderson'): m = 1 - fz/fb if positive else 0.5 Pro: * converges very fast Contra: * has problems with multiple roots * needs sign change """ maxsteps = 30 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if len(x0) != 2: raise ValueError('expected interval of 2 points, got %i' % len(x0)) self.a = x0[0] self.b = x0[1] self.f = f self.tol = kwargs['tol'] self.verbose = kwargs['verbose'] self.method = kwargs.get('method', 'illinois') self.getm = _getm(self.method) if self.verbose: print_('using %s method' % self.method) def __iter__(self): method = self.method f = self.f a = self.a b = self.b fa = f(a) fb = f(b) m = None while True: l = b - a if l == 0: break s = (fb - fa) / l z = a - fa/s fz = f(z) if abs(fz) < self.tol: # TODO: better condition (when f is very flat) if self.verbose: print_('canceled with z =', z) yield z, l break if fz * fb < 0: # root in [z, b] a = b fa = fb b = z fb = fz else: # root in [a, z] m = self.getm(fz, fb) b = z fb = fz fa = m*fa # scale down to ensure convergence if self.verbose and m and not method == 'illinois': print_('m:', m) yield (a + b)/2, abs(l) def Pegasus(*args, **kwargs): """ 1d-solver generating pairs of approximative root and error. Uses Pegasus method to find a root of f in [a, b]. Wrapper for illinois to use method='pegasus'. """ kwargs['method'] = 'pegasus' return Illinois(*args, **kwargs) def Anderson(*args, **kwargs): """ 1d-solver generating pairs of approximative root and error. Uses Anderson-Bjoerk method to find a root of f in [a, b]. Wrapper for illinois to use method='pegasus'. """ kwargs['method'] = 'anderson' return Illinois(*args, **kwargs) # TODO: check whether it's possible to combine it with Illinois stuff class Ridder: """ 1d-solver generating pairs of approximative root and error. Ridders' method to find a root of f in [a, b]. Is told to perform as well as Brent's method while being simpler. Pro: * very fast * simpler than Brent's method Contra: * two function evaluations per step * has problems with multiple roots * needs sign change http://en.wikipedia.org/wiki/Ridders'_method """ maxsteps = 30 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx self.f = f if len(x0) != 2: raise ValueError('expected interval of 2 points, got %i' % len(x0)) self.x1 = x0[0] self.x2 = x0[1] self.verbose = kwargs['verbose'] self.tol = kwargs['tol'] def __iter__(self): ctx = self.ctx f = self.f x1 = self.x1 fx1 = f(x1) x2 = self.x2 fx2 = f(x2) while True: x3 = 0.5*(x1 + x2) fx3 = f(x3) x4 = x3 + (x3 - x1) * ctx.sign(fx1 - fx2) * fx3 / ctx.sqrt(fx3**2 - fx1*fx2) fx4 = f(x4) if abs(fx4) < self.tol: # TODO: better condition (when f is very flat) if self.verbose: print_('canceled with f(x4) =', fx4) yield x4, abs(x1 - x2) break if fx4 * fx2 < 0: # root in [x4, x2] x1 = x4 fx1 = fx4 else: # root in [x1, x4] x2 = x4 fx2 = fx4 error = abs(x1 - x2) yield (x1 + x2)/2, error class ANewton: """ EXPERIMENTAL 1d-solver generating pairs of approximative root and error. Uses Newton's method modified to use Steffensens method when convergence is slow. (I.e. for multiple roots.) """ maxsteps = 20 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx if not len(x0) == 1: raise ValueError('expected 1 starting point, got %i' % len(x0)) self.x0 = x0[0] self.f = f if not 'df' in kwargs: def df(x): return self.ctx.diff(f, x) else: df = kwargs['df'] self.df = df def phi(x): return x - f(x) / df(x) self.phi = phi self.verbose = kwargs['verbose'] def __iter__(self): x0 = self.x0 f = self.f df = self.df phi = self.phi error = 0 counter = 0 while True: prevx = x0 try: x0 = phi(x0) except ZeroDivisionError: if self.verbose: print_('ZeroDivisionError: canceled with x =', x0) break preverror = error error = abs(prevx - x0) # TODO: decide not to use convergence acceleration if error and abs(error - preverror) / error < 1: if self.verbose: print_('converging slowly') counter += 1 if counter >= 3: # accelerate convergence phi = steffensen(phi) counter = 0 if self.verbose: print_('accelerating convergence') yield x0, error # TODO: add Brent ############################ # MULTIDIMENSIONAL SOLVERS # ############################ def jacobian(ctx, f, x): """ Calculate the Jacobian matrix of a function at the point x0. This is the first derivative of a vectorial function: f : R^m -> R^n with m >= n """ x = ctx.matrix(x) h = ctx.sqrt(ctx.eps) fx = ctx.matrix(f(*x)) m = len(fx) n = len(x) J = ctx.matrix(m, n) for j in xrange(n): xj = x.copy() xj[j] += h Jj = (ctx.matrix(f(*xj)) - fx) / h for i in xrange(m): J[i,j] = Jj[i] return J # TODO: test with user-specified jacobian matrix, support force_type class MDNewton: """ Find the root of a vector function numerically using Newton's method. f is a vector function representing a nonlinear equation system. x0 is the starting point close to the root. J is a function returning the Jacobian matrix for a point. Supports overdetermined systems. Use the 'norm' keyword to specify which norm to use. Defaults to max-norm. The function to calculate the Jacobian matrix can be given using the keyword 'J'. Otherwise it will be calculated numerically. Please note that this method converges only locally. Especially for high- dimensional systems it is not trivial to find a good starting point being close enough to the root. It is recommended to use a faster, low-precision solver from SciPy [1] or OpenOpt [2] to get an initial guess. Afterwards you can use this method for root-polishing to any precision. [1] http://scipy.org [2] http://openopt.org/Welcome """ maxsteps = 10 def __init__(self, ctx, f, x0, **kwargs): self.ctx = ctx self.f = f if isinstance(x0, (tuple, list)): x0 = ctx.matrix(x0) assert x0.cols == 1, 'need a vector' self.x0 = x0 if 'J' in kwargs: self.J = kwargs['J'] else: def J(*x): return ctx.jacobian(f, x) self.J = J self.norm = kwargs['norm'] self.verbose = kwargs['verbose'] def __iter__(self): f = self.f x0 = self.x0 norm = self.norm J = self.J fx = self.ctx.matrix(f(*x0)) fxnorm = norm(fx) cancel = False while not cancel: # get direction of descent fxn = -fx Jx = J(*x0) s = self.ctx.lu_solve(Jx, fxn) if self.verbose: print_('Jx:') print_(Jx) print_('s:', s) # damping step size TODO: better strategy (hard task) l = self.ctx.one x1 = x0 + s while True: if x1 == x0: if self.verbose: print_("canceled, won't get more excact") cancel = True break fx = self.ctx.matrix(f(*x1)) newnorm = norm(fx) if newnorm < fxnorm: # new x accepted fxnorm = newnorm x0 = x1 break l /= 2 x1 = x0 + l*s yield (x0, fxnorm) ############# # UTILITIES # ############# str2solver = {'newton':Newton, 'secant':Secant, 'mnewton':MNewton, 'halley':Halley, 'muller':Muller, 'bisect':Bisection, 'illinois':Illinois, 'pegasus':Pegasus, 'anderson':Anderson, 'ridder':Ridder, 'anewton':ANewton, 'mdnewton':MDNewton} def findroot(ctx, f, x0, solver='secant', tol=None, verbose=False, verify=True, **kwargs): r""" Find a solution to `f(x) = 0`, using *x0* as starting point or interval for *x*. Multidimensional overdetermined systems are supported. You can specify them using a function or a list of functions. If the found root does not satisfy `|f(x)|^2 \leq \mathrm{tol}`, an exception is raised (this can be disabled with *verify=False*). **Arguments** *f* one dimensional function *x0* starting point, several starting points or interval (depends on solver) *tol* the returned solution has an error smaller than this *verbose* print additional information for each iteration if true *verify* verify the solution and raise a ValueError if `|f(x)|^2 > \mathrm{tol}` *solver* a generator for *f* and *x0* returning approximative solution and error *maxsteps* after how many steps the solver will cancel *df* first derivative of *f* (used by some solvers) *d2f* second derivative of *f* (used by some solvers) *multidimensional* force multidimensional solving *J* Jacobian matrix of *f* (used by multidimensional solvers) *norm* used vector norm (used by multidimensional solvers) solver has to be callable with ``(f, x0, **kwargs)`` and return an generator yielding pairs of approximative solution and estimated error (which is expected to be positive). You can use the following string aliases: 'secant', 'mnewton', 'halley', 'muller', 'illinois', 'pegasus', 'anderson', 'ridder', 'anewton', 'bisect' See mpmath.calculus.optimization for their documentation. **Examples** The function :func:`~mpmath.findroot` locates a root of a given function using the secant method by default. A simple example use of the secant method is to compute `\pi` as the root of `\sin x` closest to `x_0 = 3`:: >>> from mpmath import * >>> mp.dps = 30; mp.pretty = True >>> findroot(sin, 3) 3.14159265358979323846264338328 The secant method can be used to find complex roots of analytic functions, although it must in that case generally be given a nonreal starting value (or else it will never leave the real line):: >>> mp.dps = 15 >>> findroot(lambda x: x**3 + 2*x + 1, j) (0.226698825758202 + 1.46771150871022j) A nice application is to compute nontrivial roots of the Riemann zeta function with many digits (good initial values are needed for convergence):: >>> mp.dps = 30 >>> findroot(zeta, 0.5+14j) (0.5 + 14.1347251417346937904572519836j) The secant method can also be used as an optimization algorithm, by passing it a derivative of a function. The following example locates the positive minimum of the gamma function:: >>> mp.dps = 20 >>> findroot(lambda x: diff(gamma, x), 1) 1.4616321449683623413 Finally, a useful application is to compute inverse functions, such as the Lambert W function which is the inverse of `w e^w`, given the first term of the solution's asymptotic expansion as the initial value. In basic cases, this gives identical results to mpmath's built-in ``lambertw`` function:: >>> def lambert(x): ... return findroot(lambda w: w*exp(w) - x, log(1+x)) ... >>> mp.dps = 15 >>> lambert(1); lambertw(1) 0.567143290409784 0.567143290409784 >>> lambert(1000); lambert(1000) 5.2496028524016 5.2496028524016 Multidimensional functions are also supported:: >>> f = [lambda x1, x2: x1**2 + x2, ... lambda x1, x2: 5*x1**2 - 3*x1 + 2*x2 - 3] >>> findroot(f, (0, 0)) [-0.618033988749895] [-0.381966011250105] >>> findroot(f, (10, 10)) [ 1.61803398874989] [-2.61803398874989] You can verify this by solving the system manually. Please note that the following (more general) syntax also works:: >>> def f(x1, x2): ... return x1**2 + x2, 5*x1**2 - 3*x1 + 2*x2 - 3 ... >>> findroot(f, (0, 0)) [-0.618033988749895] [-0.381966011250105] **Multiple roots** For multiple roots all methods of the Newtonian family (including secant) converge slowly. Consider this example:: >>> f = lambda x: (x - 1)**99 >>> findroot(f, 0.9, verify=False) 0.918073542444929 Even for a very close starting point the secant method converges very slowly. Use ``verbose=True`` to illustrate this. It is possible to modify Newton's method to make it converge regardless of the root's multiplicity:: >>> findroot(f, -10, solver='mnewton') 1.0 This variant uses the first and second derivative of the function, which is not very efficient. Alternatively you can use an experimental Newtonian solver that keeps track of the speed of convergence and accelerates it using Steffensen's method if necessary:: >>> findroot(f, -10, solver='anewton', verbose=True) x: -9.88888888888888888889 error: 0.111111111111111111111 converging slowly x: -9.77890011223344556678 error: 0.10998877665544332211 converging slowly x: -9.67002233332199662166 error: 0.108877778911448945119 converging slowly accelerating convergence x: -9.5622443299551077669 error: 0.107778003366888854764 converging slowly x: 0.99999999999999999214 error: 10.562244329955107759 x: 1.0 error: 7.8598304758094664213e-18 ZeroDivisionError: canceled with x = 1.0 1.0 **Complex roots** For complex roots it's recommended to use Muller's method as it converges even for real starting points very fast:: >>> findroot(lambda x: x**4 + x + 1, (0, 1, 2), solver='muller') (0.727136084491197 + 0.934099289460529j) **Intersection methods** When you need to find a root in a known interval, it's highly recommended to use an intersection-based solver like ``'anderson'`` or ``'ridder'``. Usually they converge faster and more reliable. They have however problems with multiple roots and usually need a sign change to find a root:: >>> findroot(lambda x: x**3, (-1, 1), solver='anderson') 0.0 Be careful with symmetric functions:: >>> findroot(lambda x: x**2, (-1, 1), solver='anderson') #doctest:+ELLIPSIS Traceback (most recent call last): ... ZeroDivisionError It fails even for better starting points, because there is no sign change:: >>> findroot(lambda x: x**2, (-1, .5), solver='anderson') Traceback (most recent call last): ... ValueError: Could not find root within given tolerance. (1.0 > 2.16840434497100886801e-19) Try another starting point or tweak arguments. """ prec = ctx.prec try: ctx.prec += 20 # initialize arguments if tol is None: tol = ctx.eps * 2**10 kwargs['verbose'] = kwargs.get('verbose', verbose) if 'd1f' in kwargs: kwargs['df'] = kwargs['d1f'] kwargs['tol'] = tol if isinstance(x0, (list, tuple)): x0 = [ctx.convert(x) for x in x0] else: x0 = [ctx.convert(x0)] if isinstance(solver, str): try: solver = str2solver[solver] except KeyError: raise ValueError('could not recognize solver') # accept list of functions if isinstance(f, (list, tuple)): f2 = copy(f) def tmp(*args): return [fn(*args) for fn in f2] f = tmp # detect multidimensional functions try: fx = f(*x0) multidimensional = isinstance(fx, (list, tuple, ctx.matrix)) except TypeError: fx = f(x0[0]) multidimensional = False if 'multidimensional' in kwargs: multidimensional = kwargs['multidimensional'] if multidimensional: # only one multidimensional solver available at the moment solver = MDNewton if not 'norm' in kwargs: norm = lambda x: ctx.norm(x, 'inf') kwargs['norm'] = norm else: norm = kwargs['norm'] else: norm = abs # happily return starting point if it's a root if norm(fx) == 0: if multidimensional: return ctx.matrix(x0) else: return x0[0] # use solver iterations = solver(ctx, f, x0, **kwargs) if 'maxsteps' in kwargs: maxsteps = kwargs['maxsteps'] else: maxsteps = iterations.maxsteps i = 0 for x, error in iterations: if verbose: print_('x: ', x) print_('error:', error) i += 1 if error < tol * max(1, norm(x)) or i >= maxsteps: break else: if not i: raise ValueError('Could not find root using the given solver.\n' 'Try another starting point or tweak arguments.') if not isinstance(x, (list, tuple, ctx.matrix)): xl = [x] else: xl = x if verify and norm(f(*xl))**2 > tol: # TODO: better condition? raise ValueError('Could not find root within given tolerance. ' '(%s > %s)\n' 'Try another starting point or tweak arguments.' % (norm(f(*xl))**2, tol)) return x finally: ctx.prec = prec def multiplicity(ctx, f, root, tol=None, maxsteps=10, **kwargs): """ Return the multiplicity of a given root of f. Internally, numerical derivatives are used. This might be inefficient for higher order derviatives. Due to this, ``multiplicity`` cancels after evaluating 10 derivatives by default. You can be specify the n-th derivative using the dnf keyword. >>> from mpmath import * >>> multiplicity(lambda x: sin(x) - 1, pi/2) 2 """ if tol is None: tol = ctx.eps ** 0.8 kwargs['d0f'] = f for i in xrange(maxsteps): dfstr = 'd' + str(i) + 'f' if dfstr in kwargs: df = kwargs[dfstr] else: df = lambda x: ctx.diff(f, x, i) if not abs(df(root)) < tol: break return i def steffensen(f): """ linear convergent function -> quadratic convergent function Steffensen's method for quadratic convergence of a linear converging sequence. Don not use it for higher rates of convergence. It may even work for divergent sequences. Definition: F(x) = (x*f(f(x)) - f(x)**2) / (f(f(x)) - 2*f(x) + x) Example ....... You can use Steffensen's method to accelerate a fixpoint iteration of linear (or less) convergence. x* is a fixpoint of the iteration x_{k+1} = phi(x_k) if x* = phi(x*). For phi(x) = x**2 there are two fixpoints: 0 and 1. Let's try Steffensen's method: >>> f = lambda x: x**2 >>> from mpmath.calculus.optimization import steffensen >>> F = steffensen(f) >>> for x in [0.5, 0.9, 2.0]: ... fx = Fx = x ... for i in xrange(9): ... try: ... fx = f(fx) ... except OverflowError: ... pass ... try: ... Fx = F(Fx) ... except ZeroDivisionError: ... pass ... print('%20g %20g' % (fx, Fx)) 0.25 -0.5 0.0625 0.1 0.00390625 -0.0011236 1.52588e-05 1.41691e-09 2.32831e-10 -2.84465e-27 5.42101e-20 2.30189e-80 2.93874e-39 -1.2197e-239 8.63617e-78 0 7.45834e-155 0 0.81 1.02676 0.6561 1.00134 0.430467 1 0.185302 1 0.0343368 1 0.00117902 1 1.39008e-06 1 1.93233e-12 1 3.73392e-24 1 4 1.6 16 1.2962 256 1.10194 65536 1.01659 4.29497e+09 1.00053 1.84467e+19 1 3.40282e+38 1 1.15792e+77 1 1.34078e+154 1 Unmodified, the iteration converges only towards 0. Modified it converges not only much faster, it converges even to the repelling fixpoint 1. """ def F(x): fx = f(x) ffx = f(fx) return (x*ffx - fx**2) / (ffx - 2*fx + x) return F OptimizationMethods.jacobian = jacobian OptimizationMethods.findroot = findroot OptimizationMethods.multiplicity = multiplicity if __name__ == '__main__': import doctest doctest.testmod() mpmath-1.1.0/mpmath/calculus/polynomials.py000066400000000000000000000172561340375245600210440ustar00rootroot00000000000000from ..libmp.backend import xrange from .calculus import defun #----------------------------------------------------------------------------# # Polynomials # #----------------------------------------------------------------------------# # XXX: extra precision @defun def polyval(ctx, coeffs, x, derivative=False): r""" Given coefficients `[c_n, \ldots, c_2, c_1, c_0]` and a number `x`, :func:`~mpmath.polyval` evaluates the polynomial .. math :: P(x) = c_n x^n + \ldots + c_2 x^2 + c_1 x + c_0. If *derivative=True* is set, :func:`~mpmath.polyval` simultaneously evaluates `P(x)` with the derivative, `P'(x)`, and returns the tuple `(P(x), P'(x))`. >>> from mpmath import * >>> mp.pretty = True >>> polyval([3, 0, 2], 0.5) 2.75 >>> polyval([3, 0, 2], 0.5, derivative=True) (2.75, 3.0) The coefficients and the evaluation point may be any combination of real or complex numbers. """ if not coeffs: return ctx.zero p = ctx.convert(coeffs[0]) q = ctx.zero for c in coeffs[1:]: if derivative: q = p + x*q p = c + x*p if derivative: return p, q else: return p @defun def polyroots(ctx, coeffs, maxsteps=50, cleanup=True, extraprec=10, error=False, roots_init=None): """ Computes all roots (real or complex) of a given polynomial. The roots are returned as a sorted list, where real roots appear first followed by complex conjugate roots as adjacent elements. The polynomial should be given as a list of coefficients, in the format used by :func:`~mpmath.polyval`. The leading coefficient must be nonzero. With *error=True*, :func:`~mpmath.polyroots` returns a tuple *(roots, err)* where *err* is an estimate of the maximum error among the computed roots. **Examples** Finding the three real roots of `x^3 - x^2 - 14x + 24`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nprint(polyroots([1,-1,-14,24]), 4) [-4.0, 2.0, 3.0] Finding the two complex conjugate roots of `4x^2 + 3x + 2`, with an error estimate:: >>> roots, err = polyroots([4,3,2], error=True) >>> for r in roots: ... print(r) ... (-0.375 + 0.59947894041409j) (-0.375 - 0.59947894041409j) >>> >>> err 2.22044604925031e-16 >>> >>> polyval([4,3,2], roots[0]) (2.22044604925031e-16 + 0.0j) >>> polyval([4,3,2], roots[1]) (2.22044604925031e-16 + 0.0j) The following example computes all the 5th roots of unity; that is, the roots of `x^5 - 1`:: >>> mp.dps = 20 >>> for r in polyroots([1, 0, 0, 0, 0, -1]): ... print(r) ... 1.0 (-0.8090169943749474241 + 0.58778525229247312917j) (-0.8090169943749474241 - 0.58778525229247312917j) (0.3090169943749474241 + 0.95105651629515357212j) (0.3090169943749474241 - 0.95105651629515357212j) **Precision and conditioning** The roots are computed to the current working precision accuracy. If this accuracy cannot be achieved in `maxsteps` steps, then a `NoConvergence` exception is raised. The algorithm internally is using the current working precision extended by `extraprec`. If `NoConvergence` was raised, that is caused either by not having enough extra precision to achieve convergence (in which case increasing `extraprec` should fix the problem) or too low `maxsteps` (in which case increasing `maxsteps` should fix the problem), or a combination of both. The user should always do a convergence study with regards to `extraprec` to ensure accurate results. It is possible to get convergence to a wrong answer with too low `extraprec`. Provided there are no repeated roots, :func:`~mpmath.polyroots` can typically compute all roots of an arbitrary polynomial to high precision:: >>> mp.dps = 60 >>> for r in polyroots([1, 0, -10, 0, 1]): ... print r ... -3.14626436994197234232913506571557044551247712918732870123249 -0.317837245195782244725757617296174288373133378433432554879127 0.317837245195782244725757617296174288373133378433432554879127 3.14626436994197234232913506571557044551247712918732870123249 >>> >>> sqrt(3) + sqrt(2) 3.14626436994197234232913506571557044551247712918732870123249 >>> sqrt(3) - sqrt(2) 0.317837245195782244725757617296174288373133378433432554879127 **Algorithm** :func:`~mpmath.polyroots` implements the Durand-Kerner method [1], which uses complex arithmetic to locate all roots simultaneously. The Durand-Kerner method can be viewed as approximately performing simultaneous Newton iteration for all the roots. In particular, the convergence to simple roots is quadratic, just like Newton's method. Although all roots are internally calculated using complex arithmetic, any root found to have an imaginary part smaller than the estimated numerical error is truncated to a real number (small real parts are also chopped). Real roots are placed first in the returned list, sorted by value. The remaining complex roots are sorted by their real parts so that conjugate roots end up next to each other. **References** 1. http://en.wikipedia.org/wiki/Durand-Kerner_method """ if len(coeffs) <= 1: if not coeffs or not coeffs[0]: raise ValueError("Input to polyroots must not be the zero polynomial") # Constant polynomial with no roots return [] orig = ctx.prec tol = +ctx.eps with ctx.extraprec(extraprec): deg = len(coeffs) - 1 # Must be monic lead = ctx.convert(coeffs[0]) if lead == 1: coeffs = [ctx.convert(c) for c in coeffs] else: coeffs = [c/lead for c in coeffs] f = lambda x: ctx.polyval(coeffs, x) if roots_init is None: roots = [ctx.mpc((0.4+0.9j)**n) for n in xrange(deg)] else: roots = [None]*deg; deg_init = min(deg, len(roots_init)) roots[:deg_init] = list(roots_init[:deg_init]) roots[deg_init:] = [ctx.mpc((0.4+0.9j)**n) for n in xrange(deg_init,deg)] err = [ctx.one for n in xrange(deg)] # Durand-Kerner iteration until convergence for step in xrange(maxsteps): if abs(max(err)) < tol: break for i in xrange(deg): p = roots[i] x = f(p) for j in range(deg): if i != j: try: x /= (p-roots[j]) except ZeroDivisionError: continue roots[i] = p - x err[i] = abs(x) if abs(max(err)) >= tol: raise ctx.NoConvergence("Didn't converge in maxsteps=%d steps." \ % maxsteps) # Remove small real or imaginary parts if cleanup: for i in xrange(deg): if abs(roots[i]) < tol: roots[i] = ctx.zero elif abs(ctx._im(roots[i])) < tol: roots[i] = roots[i].real elif abs(ctx._re(roots[i])) < tol: roots[i] = roots[i].imag * 1j roots.sort(key=lambda x: (abs(ctx._im(x)), ctx._re(x))) if error: err = max(err) err = max(err, ctx.ldexp(1, -orig+1)) return [+r for r in roots], +err else: return [+r for r in roots] mpmath-1.1.0/mpmath/calculus/quadrature.py000066400000000000000000001126501340375245600206450ustar00rootroot00000000000000import math from ..libmp.backend import xrange class QuadratureRule(object): """ Quadrature rules are implemented using this class, in order to simplify the code and provide a common infrastructure for tasks such as error estimation and node caching. You can implement a custom quadrature rule by subclassing :class:`QuadratureRule` and implementing the appropriate methods. The subclass can then be used by :func:`~mpmath.quad` by passing it as the *method* argument. :class:`QuadratureRule` instances are supposed to be singletons. :class:`QuadratureRule` therefore implements instance caching in :func:`~mpmath.__new__`. """ def __init__(self, ctx): self.ctx = ctx self.standard_cache = {} self.transformed_cache = {} self.interval_count = {} def clear(self): """ Delete cached node data. """ self.standard_cache = {} self.transformed_cache = {} self.interval_count = {} def calc_nodes(self, degree, prec, verbose=False): r""" Compute nodes for the standard interval `[-1, 1]`. Subclasses should probably implement only this method, and use :func:`~mpmath.get_nodes` method to retrieve the nodes. """ raise NotImplementedError def get_nodes(self, a, b, degree, prec, verbose=False): """ Return nodes for given interval, degree and precision. The nodes are retrieved from a cache if already computed; otherwise they are computed by calling :func:`~mpmath.calc_nodes` and are then cached. Subclasses should probably not implement this method, but just implement :func:`~mpmath.calc_nodes` for the actual node computation. """ key = (a, b, degree, prec) if key in self.transformed_cache: return self.transformed_cache[key] orig = self.ctx.prec try: self.ctx.prec = prec+20 # Get nodes on standard interval if (degree, prec) in self.standard_cache: nodes = self.standard_cache[degree, prec] else: nodes = self.calc_nodes(degree, prec, verbose) self.standard_cache[degree, prec] = nodes # Transform to general interval nodes = self.transform_nodes(nodes, a, b, verbose) if key in self.interval_count: self.transformed_cache[key] = nodes else: self.interval_count[key] = True finally: self.ctx.prec = orig return nodes def transform_nodes(self, nodes, a, b, verbose=False): r""" Rescale standardized nodes (for `[-1, 1]`) to a general interval `[a, b]`. For a finite interval, a simple linear change of variables is used. Otherwise, the following transformations are used: .. math :: \lbrack a, \infty \rbrack : t = \frac{1}{x} + (a-1) \lbrack -\infty, b \rbrack : t = (b+1) - \frac{1}{x} \lbrack -\infty, \infty \rbrack : t = \frac{x}{\sqrt{1-x^2}} """ ctx = self.ctx a = ctx.convert(a) b = ctx.convert(b) one = ctx.one if (a, b) == (-one, one): return nodes half = ctx.mpf(0.5) new_nodes = [] if ctx.isinf(a) or ctx.isinf(b): if (a, b) == (ctx.ninf, ctx.inf): p05 = -half for x, w in nodes: x2 = x*x px1 = one-x2 spx1 = px1**p05 x = x*spx1 w *= spx1/px1 new_nodes.append((x, w)) elif a == ctx.ninf: b1 = b+1 for x, w in nodes: u = 2/(x+one) x = b1-u w *= half*u**2 new_nodes.append((x, w)) elif b == ctx.inf: a1 = a-1 for x, w in nodes: u = 2/(x+one) x = a1+u w *= half*u**2 new_nodes.append((x, w)) elif a == ctx.inf or b == ctx.ninf: return [(x,-w) for (x,w) in self.transform_nodes(nodes, b, a, verbose)] else: raise NotImplementedError else: # Simple linear change of variables C = (b-a)/2 D = (b+a)/2 for x, w in nodes: new_nodes.append((D+C*x, C*w)) return new_nodes def guess_degree(self, prec): """ Given a desired precision `p` in bits, estimate the degree `m` of the quadrature required to accomplish full accuracy for typical integrals. By default, :func:`~mpmath.quad` will perform up to `m` iterations. The value of `m` should be a slight overestimate, so that "slightly bad" integrals can be dealt with automatically using a few extra iterations. On the other hand, it should not be too big, so :func:`~mpmath.quad` can quit within a reasonable amount of time when it is given an "unsolvable" integral. The default formula used by :func:`~mpmath.guess_degree` is tuned for both :class:`TanhSinh` and :class:`GaussLegendre`. The output is roughly as follows: +---------+---------+ | `p` | `m` | +=========+=========+ | 50 | 6 | +---------+---------+ | 100 | 7 | +---------+---------+ | 500 | 10 | +---------+---------+ | 3000 | 12 | +---------+---------+ This formula is based purely on a limited amount of experimentation and will sometimes be wrong. """ # Expected degree # XXX: use mag g = int(4 + max(0, self.ctx.log(prec/30.0, 2))) # Reasonable "worst case" g += 2 return g def estimate_error(self, results, prec, epsilon): r""" Given results from integrations `[I_1, I_2, \ldots, I_k]` done with a quadrature of rule of degree `1, 2, \ldots, k`, estimate the error of `I_k`. For `k = 2`, we estimate `|I_{\infty}-I_2|` as `|I_2-I_1|`. For `k > 2`, we extrapolate `|I_{\infty}-I_k| \approx |I_{k+1}-I_k|` from `|I_k-I_{k-1}|` and `|I_k-I_{k-2}|` under the assumption that each degree increment roughly doubles the accuracy of the quadrature rule (this is true for both :class:`TanhSinh` and :class:`GaussLegendre`). The extrapolation formula is given by Borwein, Bailey & Girgensohn. Although not very conservative, this method seems to be very robust in practice. """ if len(results) == 2: return abs(results[0]-results[1]) try: if results[-1] == results[-2] == results[-3]: return self.ctx.zero D1 = self.ctx.log(abs(results[-1]-results[-2]), 10) D2 = self.ctx.log(abs(results[-1]-results[-3]), 10) except ValueError: return epsilon D3 = -prec D4 = min(0, max(D1**2/D2, 2*D1, D3)) return self.ctx.mpf(10) ** int(D4) def summation(self, f, points, prec, epsilon, max_degree, verbose=False): """ Main integration function. Computes the 1D integral over the interval specified by *points*. For each subinterval, performs quadrature of degree from 1 up to *max_degree* until :func:`~mpmath.estimate_error` signals convergence. :func:`~mpmath.summation` transforms each subintegration to the standard interval and then calls :func:`~mpmath.sum_next`. """ ctx = self.ctx I = err = ctx.zero for i in xrange(len(points)-1): a, b = points[i], points[i+1] if a == b: continue # XXX: we could use a single variable transformation, # but this is not good in practice. We get better accuracy # by having 0 as an endpoint. if (a, b) == (ctx.ninf, ctx.inf): _f = f f = lambda x: _f(-x) + _f(x) a, b = (ctx.zero, ctx.inf) results = [] for degree in xrange(1, max_degree+1): nodes = self.get_nodes(a, b, degree, prec, verbose) if verbose: print("Integrating from %s to %s (degree %s of %s)" % \ (ctx.nstr(a), ctx.nstr(b), degree, max_degree)) results.append(self.sum_next(f, nodes, degree, prec, results, verbose)) if degree > 1: err = self.estimate_error(results, prec, epsilon) if err <= epsilon: break if verbose: print("Estimated error:", ctx.nstr(err)) I += results[-1] if err > epsilon: if verbose: print("Failed to reach full accuracy. Estimated error:", ctx.nstr(err)) return I, err def sum_next(self, f, nodes, degree, prec, previous, verbose=False): r""" Evaluates the step sum `\sum w_k f(x_k)` where the *nodes* list contains the `(w_k, x_k)` pairs. :func:`~mpmath.summation` will supply the list *results* of values computed by :func:`~mpmath.sum_next` at previous degrees, in case the quadrature rule is able to reuse them. """ return self.ctx.fdot((w, f(x)) for (x,w) in nodes) class TanhSinh(QuadratureRule): r""" This class implements "tanh-sinh" or "doubly exponential" quadrature. This quadrature rule is based on the Euler-Maclaurin integral formula. By performing a change of variables involving nested exponentials / hyperbolic functions (hence the name), the derivatives at the endpoints vanish rapidly. Since the error term in the Euler-Maclaurin formula depends on the derivatives at the endpoints, a simple step sum becomes extremely accurate. In practice, this means that doubling the number of evaluation points roughly doubles the number of accurate digits. Comparison to Gauss-Legendre: * Initial computation of nodes is usually faster * Handles endpoint singularities better * Handles infinite integration intervals better * Is slower for smooth integrands once nodes have been computed The implementation of the tanh-sinh algorithm is based on the description given in Borwein, Bailey & Girgensohn, "Experimentation in Mathematics - Computational Paths to Discovery", A K Peters, 2003, pages 312-313. In the present implementation, a few improvements have been made: * A more efficient scheme is used to compute nodes (exploiting recurrence for the exponential function) * The nodes are computed successively instead of all at once Various documents describing the algorithm are available online, e.g.: * http://crd.lbl.gov/~dhbailey/dhbpapers/dhb-tanh-sinh.pdf * http://users.cs.dal.ca/~jborwein/tanh-sinh.pdf """ def sum_next(self, f, nodes, degree, prec, previous, verbose=False): """ Step sum for tanh-sinh quadrature of degree `m`. We exploit the fact that half of the abscissas at degree `m` are precisely the abscissas from degree `m-1`. Thus reusing the result from the previous level allows a 2x speedup. """ h = self.ctx.mpf(2)**(-degree) # Abscissas overlap, so reusing saves half of the time if previous: S = previous[-1]/(h*2) else: S = self.ctx.zero S += self.ctx.fdot((w,f(x)) for (x,w) in nodes) return h*S def calc_nodes(self, degree, prec, verbose=False): r""" The abscissas and weights for tanh-sinh quadrature of degree `m` are given by .. math:: x_k = \tanh(\pi/2 \sinh(t_k)) w_k = \pi/2 \cosh(t_k) / \cosh(\pi/2 \sinh(t_k))^2 where `t_k = t_0 + hk` for a step length `h \sim 2^{-m}`. The list of nodes is actually infinite, but the weights die off so rapidly that only a few are needed. """ ctx = self.ctx nodes = [] extra = 20 ctx.prec += extra tol = ctx.ldexp(1, -prec-10) pi4 = ctx.pi/4 # For simplicity, we work in steps h = 1/2^n, with the first point # offset so that we can reuse the sum from the previous degree # We define degree 1 to include the "degree 0" steps, including # the point x = 0. (It doesn't work well otherwise; not sure why.) t0 = ctx.ldexp(1, -degree) if degree == 1: #nodes.append((mpf(0), pi4)) #nodes.append((-mpf(0), pi4)) nodes.append((ctx.zero, ctx.pi/2)) h = t0 else: h = t0*2 # Since h is fixed, we can compute the next exponential # by simply multiplying by exp(h) expt0 = ctx.exp(t0) a = pi4 * expt0 b = pi4 / expt0 udelta = ctx.exp(h) urdelta = 1/udelta for k in xrange(0, 20*2**degree+1): # Reference implementation: # t = t0 + k*h # x = tanh(pi/2 * sinh(t)) # w = pi/2 * cosh(t) / cosh(pi/2 * sinh(t))**2 # Fast implementation. Note that c = exp(pi/2 * sinh(t)) c = ctx.exp(a-b) d = 1/c co = (c+d)/2 si = (c-d)/2 x = si / co w = (a+b) / co**2 diff = abs(x-1) if diff <= tol: break nodes.append((x, w)) nodes.append((-x, w)) a *= udelta b *= urdelta if verbose and k % 300 == 150: # Note: the number displayed is rather arbitrary. Should # figure out how to print something that looks more like a # percentage print("Calculating nodes:", ctx.nstr(-ctx.log(diff, 10) / prec)) ctx.prec -= extra return nodes class GaussLegendre(QuadratureRule): r""" This class implements Gauss-Legendre quadrature, which is exceptionally efficient for polynomials and polynomial-like (i.e. very smooth) integrands. The abscissas and weights are given by roots and values of Legendre polynomials, which are the orthogonal polynomials on `[-1, 1]` with respect to the unit weight (see :func:`~mpmath.legendre`). In this implementation, we take the "degree" `m` of the quadrature to denote a Gauss-Legendre rule of degree `3 \cdot 2^m` (following Borwein, Bailey & Girgensohn). This way we get quadratic, rather than linear, convergence as the degree is incremented. Comparison to tanh-sinh quadrature: * Is faster for smooth integrands once nodes have been computed * Initial computation of nodes is usually slower * Handles endpoint singularities worse * Handles infinite integration intervals worse """ def calc_nodes(self, degree, prec, verbose=False): r""" Calculates the abscissas and weights for Gauss-Legendre quadrature of degree of given degree (actually `3 \cdot 2^m`). """ ctx = self.ctx # It is important that the epsilon is set lower than the # "real" epsilon epsilon = ctx.ldexp(1, -prec-8) # Fairly high precision might be required for accurate # evaluation of the roots orig = ctx.prec ctx.prec = int(prec*1.5) if degree == 1: x = ctx.sqrt(ctx.mpf(3)/5) w = ctx.mpf(5)/9 nodes = [(-x,w),(ctx.zero,ctx.mpf(8)/9),(x,w)] ctx.prec = orig return nodes nodes = [] n = 3*2**(degree-1) upto = n//2 + 1 for j in xrange(1, upto): # Asymptotic formula for the roots r = ctx.mpf(math.cos(math.pi*(j-0.25)/(n+0.5))) # Newton iteration while 1: t1, t2 = 1, 0 # Evaluates the Legendre polynomial using its defining # recurrence relation for j1 in xrange(1,n+1): t3, t2, t1 = t2, t1, ((2*j1-1)*r*t1 - (j1-1)*t2)/j1 t4 = n*(r*t1-t2)/(r**2-1) a = t1/t4 r = r - a if abs(a) < epsilon: break x = r w = 2/((1-r**2)*t4**2) if verbose and j % 30 == 15: print("Computing nodes (%i of %i)" % (j, upto)) nodes.append((x, w)) nodes.append((-x, w)) ctx.prec = orig return nodes class QuadratureMethods(object): def __init__(ctx, *args, **kwargs): ctx._gauss_legendre = GaussLegendre(ctx) ctx._tanh_sinh = TanhSinh(ctx) def quad(ctx, f, *points, **kwargs): r""" Computes a single, double or triple integral over a given 1D interval, 2D rectangle, or 3D cuboid. A basic example:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> quad(sin, [0, pi]) 2.0 A basic 2D integral:: >>> f = lambda x, y: cos(x+y/2) >>> quad(f, [-pi/2, pi/2], [0, pi]) 4.0 **Interval format** The integration range for each dimension may be specified using a list or tuple. Arguments are interpreted as follows: ``quad(f, [x1, x2])`` -- calculates `\int_{x_1}^{x_2} f(x) \, dx` ``quad(f, [x1, x2], [y1, y2])`` -- calculates `\int_{x_1}^{x_2} \int_{y_1}^{y_2} f(x,y) \, dy \, dx` ``quad(f, [x1, x2], [y1, y2], [z1, z2])`` -- calculates `\int_{x_1}^{x_2} \int_{y_1}^{y_2} \int_{z_1}^{z_2} f(x,y,z) \, dz \, dy \, dx` Endpoints may be finite or infinite. An interval descriptor may also contain more than two points. In this case, the integration is split into subintervals, between each pair of consecutive points. This is useful for dealing with mid-interval discontinuities, or integrating over large intervals where the function is irregular or oscillates. **Options** :func:`~mpmath.quad` recognizes the following keyword arguments: *method* Chooses integration algorithm (described below). *error* If set to true, :func:`~mpmath.quad` returns `(v, e)` where `v` is the integral and `e` is the estimated error. *maxdegree* Maximum degree of the quadrature rule to try before quitting. *verbose* Print details about progress. **Algorithms** Mpmath presently implements two integration algorithms: tanh-sinh quadrature and Gauss-Legendre quadrature. These can be selected using *method='tanh-sinh'* or *method='gauss-legendre'* or by passing the classes *method=TanhSinh*, *method=GaussLegendre*. The functions :func:`~mpmath.quadts` and :func:`~mpmath.quadgl` are also available as shortcuts. Both algorithms have the property that doubling the number of evaluation points roughly doubles the accuracy, so both are ideal for high precision quadrature (hundreds or thousands of digits). At high precision, computing the nodes and weights for the integration can be expensive (more expensive than computing the function values). To make repeated integrations fast, nodes are automatically cached. The advantages of the tanh-sinh algorithm are that it tends to handle endpoint singularities well, and that the nodes are cheap to compute on the first run. For these reasons, it is used by :func:`~mpmath.quad` as the default algorithm. Gauss-Legendre quadrature often requires fewer function evaluations, and is therefore often faster for repeated use, but the algorithm does not handle endpoint singularities as well and the nodes are more expensive to compute. Gauss-Legendre quadrature can be a better choice if the integrand is smooth and repeated integrations are required (e.g. for multiple integrals). See the documentation for :class:`TanhSinh` and :class:`GaussLegendre` for additional details. **Examples of 1D integrals** Intervals may be infinite or half-infinite. The following two examples evaluate the limits of the inverse tangent function (`\int 1/(1+x^2) = \tan^{-1} x`), and the Gaussian integral `\int_{\infty}^{\infty} \exp(-x^2)\,dx = \sqrt{\pi}`:: >>> mp.dps = 15 >>> quad(lambda x: 2/(x**2+1), [0, inf]) 3.14159265358979 >>> quad(lambda x: exp(-x**2), [-inf, inf])**2 3.14159265358979 Integrals can typically be resolved to high precision. The following computes 50 digits of `\pi` by integrating the area of the half-circle defined by `x^2 + y^2 \le 1`, `-1 \le x \le 1`, `y \ge 0`:: >>> mp.dps = 50 >>> 2*quad(lambda x: sqrt(1-x**2), [-1, 1]) 3.1415926535897932384626433832795028841971693993751 One can just as well compute 1000 digits (output truncated):: >>> mp.dps = 1000 >>> 2*quad(lambda x: sqrt(1-x**2), [-1, 1]) #doctest:+ELLIPSIS 3.141592653589793238462643383279502884...216420199 Complex integrals are supported. The following computes a residue at `z = 0` by integrating counterclockwise along the diamond-shaped path from `1` to `+i` to `-1` to `-i` to `1`:: >>> mp.dps = 15 >>> chop(quad(lambda z: 1/z, [1,j,-1,-j,1])) (0.0 + 6.28318530717959j) **Examples of 2D and 3D integrals** Here are several nice examples of analytically solvable 2D integrals (taken from MathWorld [1]) that can be evaluated to high precision fairly rapidly by :func:`~mpmath.quad`:: >>> mp.dps = 30 >>> f = lambda x, y: (x-1)/((1-x*y)*log(x*y)) >>> quad(f, [0, 1], [0, 1]) 0.577215664901532860606512090082 >>> +euler 0.577215664901532860606512090082 >>> f = lambda x, y: 1/sqrt(1+x**2+y**2) >>> quad(f, [-1, 1], [-1, 1]) 3.17343648530607134219175646705 >>> 4*log(2+sqrt(3))-2*pi/3 3.17343648530607134219175646705 >>> f = lambda x, y: 1/(1-x**2 * y**2) >>> quad(f, [0, 1], [0, 1]) 1.23370055013616982735431137498 >>> pi**2 / 8 1.23370055013616982735431137498 >>> quad(lambda x, y: 1/(1-x*y), [0, 1], [0, 1]) 1.64493406684822643647241516665 >>> pi**2 / 6 1.64493406684822643647241516665 Multiple integrals may be done over infinite ranges:: >>> mp.dps = 15 >>> print(quad(lambda x,y: exp(-x-y), [0, inf], [1, inf])) 0.367879441171442 >>> print(1/e) 0.367879441171442 For nonrectangular areas, one can call :func:`~mpmath.quad` recursively. For example, we can replicate the earlier example of calculating `\pi` by integrating over the unit-circle, and actually use double quadrature to actually measure the area circle:: >>> f = lambda x: quad(lambda y: 1, [-sqrt(1-x**2), sqrt(1-x**2)]) >>> quad(f, [-1, 1]) 3.14159265358979 Here is a simple triple integral:: >>> mp.dps = 15 >>> f = lambda x,y,z: x*y/(1+z) >>> quad(f, [0,1], [0,1], [1,2], method='gauss-legendre') 0.101366277027041 >>> (log(3)-log(2))/4 0.101366277027041 **Singularities** Both tanh-sinh and Gauss-Legendre quadrature are designed to integrate smooth (infinitely differentiable) functions. Neither algorithm copes well with mid-interval singularities (such as mid-interval discontinuities in `f(x)` or `f'(x)`). The best solution is to split the integral into parts:: >>> mp.dps = 15 >>> quad(lambda x: abs(sin(x)), [0, 2*pi]) # Bad 3.99900894176779 >>> quad(lambda x: abs(sin(x)), [0, pi, 2*pi]) # Good 4.0 The tanh-sinh rule often works well for integrands having a singularity at one or both endpoints:: >>> mp.dps = 15 >>> quad(log, [0, 1], method='tanh-sinh') # Good -1.0 >>> quad(log, [0, 1], method='gauss-legendre') # Bad -0.999932197413801 However, the result may still be inaccurate for some functions:: >>> quad(lambda x: 1/sqrt(x), [0, 1], method='tanh-sinh') 1.99999999946942 This problem is not due to the quadrature rule per se, but to numerical amplification of errors in the nodes. The problem can be circumvented by temporarily increasing the precision:: >>> mp.dps = 30 >>> a = quad(lambda x: 1/sqrt(x), [0, 1], method='tanh-sinh') >>> mp.dps = 15 >>> +a 2.0 **Highly variable functions** For functions that are smooth (in the sense of being infinitely differentiable) but contain sharp mid-interval peaks or many "bumps", :func:`~mpmath.quad` may fail to provide full accuracy. For example, with default settings, :func:`~mpmath.quad` is able to integrate `\sin(x)` accurately over an interval of length 100 but not over length 1000:: >>> quad(sin, [0, 100]); 1-cos(100) # Good 0.137681127712316 0.137681127712316 >>> quad(sin, [0, 1000]); 1-cos(1000) # Bad -37.8587612408485 0.437620923709297 One solution is to break the integration into 10 intervals of length 100:: >>> quad(sin, linspace(0, 1000, 10)) # Good 0.437620923709297 Another is to increase the degree of the quadrature:: >>> quad(sin, [0, 1000], maxdegree=10) # Also good 0.437620923709297 Whether splitting the interval or increasing the degree is more efficient differs from case to case. Another example is the function `1/(1+x^2)`, which has a sharp peak centered around `x = 0`:: >>> f = lambda x: 1/(1+x**2) >>> quad(f, [-100, 100]) # Bad 3.64804647105268 >>> quad(f, [-100, 100], maxdegree=10) # Good 3.12159332021646 >>> quad(f, [-100, 0, 100]) # Also good 3.12159332021646 **References** 1. http://mathworld.wolfram.com/DoubleIntegral.html """ rule = kwargs.get('method', 'tanh-sinh') if type(rule) is str: if rule == 'tanh-sinh': rule = ctx._tanh_sinh elif rule == 'gauss-legendre': rule = ctx._gauss_legendre else: raise ValueError("unknown quadrature rule: %s" % rule) else: rule = rule(ctx) verbose = kwargs.get('verbose') dim = len(points) orig = prec = ctx.prec epsilon = ctx.eps/8 m = kwargs.get('maxdegree') or rule.guess_degree(prec) points = [ctx._as_points(p) for p in points] try: ctx.prec += 20 if dim == 1: v, err = rule.summation(f, points[0], prec, epsilon, m, verbose) elif dim == 2: v, err = rule.summation(lambda x: \ rule.summation(lambda y: f(x,y), \ points[1], prec, epsilon, m)[0], points[0], prec, epsilon, m, verbose) elif dim == 3: v, err = rule.summation(lambda x: \ rule.summation(lambda y: \ rule.summation(lambda z: f(x,y,z), \ points[2], prec, epsilon, m)[0], points[1], prec, epsilon, m)[0], points[0], prec, epsilon, m, verbose) else: raise NotImplementedError("quadrature must have dim 1, 2 or 3") finally: ctx.prec = orig if kwargs.get("error"): return +v, err return +v def quadts(ctx, *args, **kwargs): """ Performs tanh-sinh quadrature. The call quadts(func, *points, ...) is simply a shortcut for: quad(func, *points, ..., method=TanhSinh) For example, a single integral and a double integral: quadts(lambda x: exp(cos(x)), [0, 1]) quadts(lambda x, y: exp(cos(x+y)), [0, 1], [0, 1]) See the documentation for quad for information about how points arguments and keyword arguments are parsed. See documentation for TanhSinh for algorithmic information about tanh-sinh quadrature. """ kwargs['method'] = 'tanh-sinh' return ctx.quad(*args, **kwargs) def quadgl(ctx, *args, **kwargs): """ Performs Gauss-Legendre quadrature. The call quadgl(func, *points, ...) is simply a shortcut for: quad(func, *points, ..., method=GaussLegendre) For example, a single integral and a double integral: quadgl(lambda x: exp(cos(x)), [0, 1]) quadgl(lambda x, y: exp(cos(x+y)), [0, 1], [0, 1]) See the documentation for quad for information about how points arguments and keyword arguments are parsed. See documentation for TanhSinh for algorithmic information about tanh-sinh quadrature. """ kwargs['method'] = 'gauss-legendre' return ctx.quad(*args, **kwargs) def quadosc(ctx, f, interval, omega=None, period=None, zeros=None): r""" Calculates .. math :: I = \int_a^b f(x) dx where at least one of `a` and `b` is infinite and where `f(x) = g(x) \cos(\omega x + \phi)` for some slowly decreasing function `g(x)`. With proper input, :func:`~mpmath.quadosc` can also handle oscillatory integrals where the oscillation rate is different from a pure sine or cosine wave. In the standard case when `|a| < \infty, b = \infty`, :func:`~mpmath.quadosc` works by evaluating the infinite series .. math :: I = \int_a^{x_1} f(x) dx + \sum_{k=1}^{\infty} \int_{x_k}^{x_{k+1}} f(x) dx where `x_k` are consecutive zeros (alternatively some other periodic reference point) of `f(x)`. Accordingly, :func:`~mpmath.quadosc` requires information about the zeros of `f(x)`. For a periodic function, you can specify the zeros by either providing the angular frequency `\omega` (*omega*) or the *period* `2 \pi/\omega`. In general, you can specify the `n`-th zero by providing the *zeros* arguments. Below is an example of each:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> f = lambda x: sin(3*x)/(x**2+1) >>> quadosc(f, [0,inf], omega=3) 0.37833007080198 >>> quadosc(f, [0,inf], period=2*pi/3) 0.37833007080198 >>> quadosc(f, [0,inf], zeros=lambda n: pi*n/3) 0.37833007080198 >>> (ei(3)*exp(-3)-exp(3)*ei(-3))/2 # Computed by Mathematica 0.37833007080198 Note that *zeros* was specified to multiply `n` by the *half-period*, not the full period. In theory, it does not matter whether each partial integral is done over a half period or a full period. However, if done over half-periods, the infinite series passed to :func:`~mpmath.nsum` becomes an *alternating series* and this typically makes the extrapolation much more efficient. Here is an example of an integration over the entire real line, and a half-infinite integration starting at `-\infty`:: >>> quadosc(lambda x: cos(x)/(1+x**2), [-inf, inf], omega=1) 1.15572734979092 >>> pi/e 1.15572734979092 >>> quadosc(lambda x: cos(x)/x**2, [-inf, -1], period=2*pi) -0.0844109505595739 >>> cos(1)+si(1)-pi/2 -0.0844109505595738 Of course, the integrand may contain a complex exponential just as well as a real sine or cosine:: >>> quadosc(lambda x: exp(3*j*x)/(1+x**2), [-inf,inf], omega=3) (0.156410688228254 + 0.0j) >>> pi/e**3 0.156410688228254 >>> quadosc(lambda x: exp(3*j*x)/(2+x+x**2), [-inf,inf], omega=3) (0.00317486988463794 - 0.0447701735209082j) >>> 2*pi/sqrt(7)/exp(3*(j+sqrt(7))/2) (0.00317486988463794 - 0.0447701735209082j) **Non-periodic functions** If `f(x) = g(x) h(x)` for some function `h(x)` that is not strictly periodic, *omega* or *period* might not work, and it might be necessary to use *zeros*. A notable exception can be made for Bessel functions which, though not periodic, are "asymptotically periodic" in a sufficiently strong sense that the sum extrapolation will work out:: >>> quadosc(j0, [0, inf], period=2*pi) 1.0 >>> quadosc(j1, [0, inf], period=2*pi) 1.0 More properly, one should provide the exact Bessel function zeros:: >>> j0zero = lambda n: findroot(j0, pi*(n-0.25)) >>> quadosc(j0, [0, inf], zeros=j0zero) 1.0 For an example where *zeros* becomes necessary, consider the complete Fresnel integrals .. math :: \int_0^{\infty} \cos x^2\,dx = \int_0^{\infty} \sin x^2\,dx = \sqrt{\frac{\pi}{8}}. Although the integrands do not decrease in magnitude as `x \to \infty`, the integrals are convergent since the oscillation rate increases (causing consecutive periods to asymptotically cancel out). These integrals are virtually impossible to calculate to any kind of accuracy using standard quadrature rules. However, if one provides the correct asymptotic distribution of zeros (`x_n \sim \sqrt{n}`), :func:`~mpmath.quadosc` works:: >>> mp.dps = 30 >>> f = lambda x: cos(x**2) >>> quadosc(f, [0,inf], zeros=lambda n:sqrt(pi*n)) 0.626657068657750125603941321203 >>> f = lambda x: sin(x**2) >>> quadosc(f, [0,inf], zeros=lambda n:sqrt(pi*n)) 0.626657068657750125603941321203 >>> sqrt(pi/8) 0.626657068657750125603941321203 (Interestingly, these integrals can still be evaluated if one places some other constant than `\pi` in the square root sign.) In general, if `f(x) \sim g(x) \cos(h(x))`, the zeros follow the inverse-function distribution `h^{-1}(x)`:: >>> mp.dps = 15 >>> f = lambda x: sin(exp(x)) >>> quadosc(f, [1,inf], zeros=lambda n: log(n)) -0.25024394235267 >>> pi/2-si(e) -0.250243942352671 **Non-alternating functions** If the integrand oscillates around a positive value, without alternating signs, the extrapolation might fail. A simple trick that sometimes works is to multiply or divide the frequency by 2:: >>> f = lambda x: 1/x**2+sin(x)/x**4 >>> quadosc(f, [1,inf], omega=1) # Bad 1.28642190869861 >>> quadosc(f, [1,inf], omega=0.5) # Perfect 1.28652953559617 >>> 1+(cos(1)+ci(1)+sin(1))/6 1.28652953559617 **Fast decay** :func:`~mpmath.quadosc` is primarily useful for slowly decaying integrands. If the integrand decreases exponentially or faster, :func:`~mpmath.quad` will likely handle it without trouble (and generally be much faster than :func:`~mpmath.quadosc`):: >>> quadosc(lambda x: cos(x)/exp(x), [0, inf], omega=1) 0.5 >>> quad(lambda x: cos(x)/exp(x), [0, inf]) 0.5 """ a, b = ctx._as_points(interval) a = ctx.convert(a) b = ctx.convert(b) if [omega, period, zeros].count(None) != 2: raise ValueError( \ "must specify exactly one of omega, period, zeros") if a == ctx.ninf and b == ctx.inf: s1 = ctx.quadosc(f, [a, 0], omega=omega, zeros=zeros, period=period) s2 = ctx.quadosc(f, [0, b], omega=omega, zeros=zeros, period=period) return s1 + s2 if a == ctx.ninf: if zeros: return ctx.quadosc(lambda x:f(-x), [-b,-a], lambda n: zeros(-n)) else: return ctx.quadosc(lambda x:f(-x), [-b,-a], omega=omega, period=period) if b != ctx.inf: raise ValueError("quadosc requires an infinite integration interval") if not zeros: if omega: period = 2*ctx.pi/omega zeros = lambda n: n*period/2 #for n in range(1,10): # p = zeros(n) # if p > a: # break #if n >= 9: # raise ValueError("zeros do not appear to be correctly indexed") n = 1 s = ctx.quadgl(f, [a, zeros(n)]) def term(k): return ctx.quadgl(f, [zeros(k), zeros(k+1)]) s += ctx.nsum(term, [n, ctx.inf]) return s if __name__ == '__main__': import doctest doctest.testmod() mpmath-1.1.0/mpmath/ctx_base.py000066400000000000000000000371611340375245600164500ustar00rootroot00000000000000from operator import gt, lt from .libmp.backend import xrange from .functions.functions import SpecialFunctions from .functions.rszeta import RSCache from .calculus.quadrature import QuadratureMethods from .calculus.inverselaplace import LaplaceTransformInversionMethods from .calculus.calculus import CalculusMethods from .calculus.optimization import OptimizationMethods from .calculus.odes import ODEMethods from .matrices.matrices import MatrixMethods from .matrices.calculus import MatrixCalculusMethods from .matrices.linalg import LinearAlgebraMethods from .matrices.eigen import Eigen from .identification import IdentificationMethods from .visualization import VisualizationMethods from . import libmp class Context(object): pass class StandardBaseContext(Context, SpecialFunctions, RSCache, QuadratureMethods, LaplaceTransformInversionMethods, CalculusMethods, MatrixMethods, MatrixCalculusMethods, LinearAlgebraMethods, Eigen, IdentificationMethods, OptimizationMethods, ODEMethods, VisualizationMethods): NoConvergence = libmp.NoConvergence ComplexResult = libmp.ComplexResult def __init__(ctx): ctx._aliases = {} # Call those that need preinitialization (e.g. for wrappers) SpecialFunctions.__init__(ctx) RSCache.__init__(ctx) QuadratureMethods.__init__(ctx) LaplaceTransformInversionMethods.__init__(ctx) CalculusMethods.__init__(ctx) MatrixMethods.__init__(ctx) def _init_aliases(ctx): for alias, value in ctx._aliases.items(): try: setattr(ctx, alias, getattr(ctx, value)) except AttributeError: pass _fixed_precision = False # XXX verbose = False def warn(ctx, msg): print("Warning:", msg) def bad_domain(ctx, msg): raise ValueError(msg) def _re(ctx, x): if hasattr(x, "real"): return x.real return x def _im(ctx, x): if hasattr(x, "imag"): return x.imag return ctx.zero def _as_points(ctx, x): return x def fneg(ctx, x, **kwargs): return -ctx.convert(x) def fadd(ctx, x, y, **kwargs): return ctx.convert(x)+ctx.convert(y) def fsub(ctx, x, y, **kwargs): return ctx.convert(x)-ctx.convert(y) def fmul(ctx, x, y, **kwargs): return ctx.convert(x)*ctx.convert(y) def fdiv(ctx, x, y, **kwargs): return ctx.convert(x)/ctx.convert(y) def fsum(ctx, args, absolute=False, squared=False): if absolute: if squared: return sum((abs(x)**2 for x in args), ctx.zero) return sum((abs(x) for x in args), ctx.zero) if squared: return sum((x**2 for x in args), ctx.zero) return sum(args, ctx.zero) def fdot(ctx, xs, ys=None, conjugate=False): if ys is not None: xs = zip(xs, ys) if conjugate: cf = ctx.conj return sum((x*cf(y) for (x,y) in xs), ctx.zero) else: return sum((x*y for (x,y) in xs), ctx.zero) def fprod(ctx, args): prod = ctx.one for arg in args: prod *= arg return prod def nprint(ctx, x, n=6, **kwargs): """ Equivalent to ``print(nstr(x, n))``. """ print(ctx.nstr(x, n, **kwargs)) def chop(ctx, x, tol=None): """ Chops off small real or imaginary parts, or converts numbers close to zero to exact zeros. The input can be a single number or an iterable:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> chop(5+1e-10j, tol=1e-9) mpf('5.0') >>> nprint(chop([1.0, 1e-20, 3+1e-18j, -4, 2])) [1.0, 0.0, 3.0, -4.0, 2.0] The tolerance defaults to ``100*eps``. """ if tol is None: tol = 100*ctx.eps try: x = ctx.convert(x) absx = abs(x) if abs(x) < tol: return ctx.zero if ctx._is_complex_type(x): #part_tol = min(tol, absx*tol) part_tol = max(tol, absx*tol) if abs(x.imag) < part_tol: return x.real if abs(x.real) < part_tol: return ctx.mpc(0, x.imag) except TypeError: if isinstance(x, ctx.matrix): return x.apply(lambda a: ctx.chop(a, tol)) if hasattr(x, "__iter__"): return [ctx.chop(a, tol) for a in x] return x def almosteq(ctx, s, t, rel_eps=None, abs_eps=None): r""" Determine whether the difference between `s` and `t` is smaller than a given epsilon, either relatively or absolutely. Both a maximum relative difference and a maximum difference ('epsilons') may be specified. The absolute difference is defined as `|s-t|` and the relative difference is defined as `|s-t|/\max(|s|, |t|)`. If only one epsilon is given, both are set to the same value. If none is given, both epsilons are set to `2^{-p+m}` where `p` is the current working precision and `m` is a small integer. The default setting typically allows :func:`~mpmath.almosteq` to be used to check for mathematical equality in the presence of small rounding errors. **Examples** >>> from mpmath import * >>> mp.dps = 15 >>> almosteq(3.141592653589793, 3.141592653589790) True >>> almosteq(3.141592653589793, 3.141592653589700) False >>> almosteq(3.141592653589793, 3.141592653589700, 1e-10) True >>> almosteq(1e-20, 2e-20) True >>> almosteq(1e-20, 2e-20, rel_eps=0, abs_eps=0) False """ t = ctx.convert(t) if abs_eps is None and rel_eps is None: rel_eps = abs_eps = ctx.ldexp(1, -ctx.prec+4) if abs_eps is None: abs_eps = rel_eps elif rel_eps is None: rel_eps = abs_eps diff = abs(s-t) if diff <= abs_eps: return True abss = abs(s) abst = abs(t) if abss < abst: err = diff/abst else: err = diff/abss return err <= rel_eps def arange(ctx, *args): r""" This is a generalized version of Python's :func:`~mpmath.range` function that accepts fractional endpoints and step sizes and returns a list of ``mpf`` instances. Like :func:`~mpmath.range`, :func:`~mpmath.arange` can be called with 1, 2 or 3 arguments: ``arange(b)`` `[0, 1, 2, \ldots, x]` ``arange(a, b)`` `[a, a+1, a+2, \ldots, x]` ``arange(a, b, h)`` `[a, a+h, a+h, \ldots, x]` where `b-1 \le x < b` (in the third case, `b-h \le x < b`). Like Python's :func:`~mpmath.range`, the endpoint is not included. To produce ranges where the endpoint is included, :func:`~mpmath.linspace` is more convenient. **Examples** >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> arange(4) [mpf('0.0'), mpf('1.0'), mpf('2.0'), mpf('3.0')] >>> arange(1, 2, 0.25) [mpf('1.0'), mpf('1.25'), mpf('1.5'), mpf('1.75')] >>> arange(1, -1, -0.75) [mpf('1.0'), mpf('0.25'), mpf('-0.5')] """ if not len(args) <= 3: raise TypeError('arange expected at most 3 arguments, got %i' % len(args)) if not len(args) >= 1: raise TypeError('arange expected at least 1 argument, got %i' % len(args)) # set default a = 0 dt = 1 # interpret arguments if len(args) == 1: b = args[0] elif len(args) >= 2: a = args[0] b = args[1] if len(args) == 3: dt = args[2] a, b, dt = ctx.mpf(a), ctx.mpf(b), ctx.mpf(dt) assert a + dt != a, 'dt is too small and would cause an infinite loop' # adapt code for sign of dt if a > b: if dt > 0: return [] op = gt else: if dt < 0: return [] op = lt # create list result = [] i = 0 t = a while 1: t = a + dt*i i += 1 if op(t, b): result.append(t) else: break return result def linspace(ctx, *args, **kwargs): """ ``linspace(a, b, n)`` returns a list of `n` evenly spaced samples from `a` to `b`. The syntax ``linspace(mpi(a,b), n)`` is also valid. This function is often more convenient than :func:`~mpmath.arange` for partitioning an interval into subintervals, since the endpoint is included:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> linspace(1, 4, 4) [mpf('1.0'), mpf('2.0'), mpf('3.0'), mpf('4.0')] You may also provide the keyword argument ``endpoint=False``:: >>> linspace(1, 4, 4, endpoint=False) [mpf('1.0'), mpf('1.75'), mpf('2.5'), mpf('3.25')] """ if len(args) == 3: a = ctx.mpf(args[0]) b = ctx.mpf(args[1]) n = int(args[2]) elif len(args) == 2: assert hasattr(args[0], '_mpi_') a = args[0].a b = args[0].b n = int(args[1]) else: raise TypeError('linspace expected 2 or 3 arguments, got %i' \ % len(args)) if n < 1: raise ValueError('n must be greater than 0') if not 'endpoint' in kwargs or kwargs['endpoint']: if n == 1: return [ctx.mpf(a)] step = (b - a) / ctx.mpf(n - 1) y = [i*step + a for i in xrange(n)] y[-1] = b else: step = (b - a) / ctx.mpf(n) y = [i*step + a for i in xrange(n)] return y def cos_sin(ctx, z, **kwargs): return ctx.cos(z, **kwargs), ctx.sin(z, **kwargs) def cospi_sinpi(ctx, z, **kwargs): return ctx.cospi(z, **kwargs), ctx.sinpi(z, **kwargs) def _default_hyper_maxprec(ctx, p): return int(1000 * p**0.25 + 4*p) _gcd = staticmethod(libmp.gcd) list_primes = staticmethod(libmp.list_primes) isprime = staticmethod(libmp.isprime) bernfrac = staticmethod(libmp.bernfrac) moebius = staticmethod(libmp.moebius) _ifac = staticmethod(libmp.ifac) _eulernum = staticmethod(libmp.eulernum) _stirling1 = staticmethod(libmp.stirling1) _stirling2 = staticmethod(libmp.stirling2) def sum_accurately(ctx, terms, check_step=1): prec = ctx.prec try: extraprec = 10 while 1: ctx.prec = prec + extraprec + 5 max_mag = ctx.ninf s = ctx.zero k = 0 for term in terms(): s += term if (not k % check_step) and term: term_mag = ctx.mag(term) max_mag = max(max_mag, term_mag) sum_mag = ctx.mag(s) if sum_mag - term_mag > ctx.prec: break k += 1 cancellation = max_mag - sum_mag if cancellation != cancellation: break if cancellation < extraprec or ctx._fixed_precision: break extraprec += min(ctx.prec, cancellation) return s finally: ctx.prec = prec def mul_accurately(ctx, factors, check_step=1): prec = ctx.prec try: extraprec = 10 while 1: ctx.prec = prec + extraprec + 5 max_mag = ctx.ninf one = ctx.one s = one k = 0 for factor in factors(): s *= factor term = factor - one if (not k % check_step): term_mag = ctx.mag(term) max_mag = max(max_mag, term_mag) sum_mag = ctx.mag(s-one) #if sum_mag - term_mag > ctx.prec: # break if -term_mag > ctx.prec: break k += 1 cancellation = max_mag - sum_mag if cancellation != cancellation: break if cancellation < extraprec or ctx._fixed_precision: break extraprec += min(ctx.prec, cancellation) return s finally: ctx.prec = prec def power(ctx, x, y): r"""Converts `x` and `y` to mpmath numbers and evaluates `x^y = \exp(y \log(x))`:: >>> from mpmath import * >>> mp.dps = 30; mp.pretty = True >>> power(2, 0.5) 1.41421356237309504880168872421 This shows the leading few digits of a large Mersenne prime (performing the exact calculation ``2**43112609-1`` and displaying the result in Python would be very slow):: >>> power(2, 43112609)-1 3.16470269330255923143453723949e+12978188 """ return ctx.convert(x) ** ctx.convert(y) def _zeta_int(ctx, n): return ctx.zeta(n) def maxcalls(ctx, f, N): """ Return a wrapped copy of *f* that raises ``NoConvergence`` when *f* has been called more than *N* times:: >>> from mpmath import * >>> mp.dps = 15 >>> f = maxcalls(sin, 10) >>> print(sum(f(n) for n in range(10))) 1.95520948210738 >>> f(10) # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... NoConvergence: maxcalls: function evaluated 10 times """ counter = [0] def f_maxcalls_wrapped(*args, **kwargs): counter[0] += 1 if counter[0] > N: raise ctx.NoConvergence("maxcalls: function evaluated %i times" % N) return f(*args, **kwargs) return f_maxcalls_wrapped def memoize(ctx, f): """ Return a wrapped copy of *f* that caches computed values, i.e. a memoized copy of *f*. Values are only reused if the cached precision is equal to or higher than the working precision:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> f = memoize(maxcalls(sin, 1)) >>> f(2) 0.909297426825682 >>> f(2) 0.909297426825682 >>> mp.dps = 25 >>> f(2) # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... NoConvergence: maxcalls: function evaluated 1 times """ f_cache = {} def f_cached(*args, **kwargs): if kwargs: key = args, tuple(kwargs.items()) else: key = args prec = ctx.prec if key in f_cache: cprec, cvalue = f_cache[key] if cprec >= prec: return +cvalue value = f(*args, **kwargs) f_cache[key] = (prec, value) return value f_cached.__name__ = f.__name__ f_cached.__doc__ = f.__doc__ return f_cached mpmath-1.1.0/mpmath/ctx_fp.py000066400000000000000000000146541340375245600161450ustar00rootroot00000000000000from .ctx_base import StandardBaseContext import math import cmath from . import math2 from . import function_docs from .libmp import mpf_bernoulli, to_float, int_types from . import libmp class FPContext(StandardBaseContext): """ Context for fast low-precision arithmetic (53-bit precision, giving at most about 15-digit accuracy), using Python's builtin float and complex. """ def __init__(ctx): StandardBaseContext.__init__(ctx) # Override SpecialFunctions implementation ctx.loggamma = math2.loggamma ctx._bernoulli_cache = {} ctx.pretty = False ctx._init_aliases() _mpq = lambda cls, x: float(x[0])/x[1] NoConvergence = libmp.NoConvergence def _get_prec(ctx): return 53 def _set_prec(ctx, p): return def _get_dps(ctx): return 15 def _set_dps(ctx, p): return _fixed_precision = True prec = property(_get_prec, _set_prec) dps = property(_get_dps, _set_dps) zero = 0.0 one = 1.0 eps = math2.EPS inf = math2.INF ninf = math2.NINF nan = math2.NAN j = 1j # Called by SpecialFunctions.__init__() @classmethod def _wrap_specfun(cls, name, f, wrap): if wrap: def f_wrapped(ctx, *args, **kwargs): convert = ctx.convert args = [convert(a) for a in args] return f(ctx, *args, **kwargs) else: f_wrapped = f f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__) setattr(cls, name, f_wrapped) def bernoulli(ctx, n): cache = ctx._bernoulli_cache if n in cache: return cache[n] cache[n] = to_float(mpf_bernoulli(n, 53, 'n'), strict=True) return cache[n] pi = math2.pi e = math2.e euler = math2.euler sqrt2 = 1.4142135623730950488 sqrt5 = 2.2360679774997896964 phi = 1.6180339887498948482 ln2 = 0.69314718055994530942 ln10 = 2.302585092994045684 euler = 0.57721566490153286061 catalan = 0.91596559417721901505 khinchin = 2.6854520010653064453 apery = 1.2020569031595942854 glaisher = 1.2824271291006226369 absmin = absmax = abs def is_special(ctx, x): return x - x != 0.0 def isnan(ctx, x): return x != x def isinf(ctx, x): return abs(x) == math2.INF def isnormal(ctx, x): if x: return x - x == 0.0 return False def isnpint(ctx, x): if type(x) is complex: if x.imag: return False x = x.real return x <= 0.0 and round(x) == x mpf = float mpc = complex def convert(ctx, x): try: return float(x) except: return complex(x) power = staticmethod(math2.pow) sqrt = staticmethod(math2.sqrt) exp = staticmethod(math2.exp) ln = log = staticmethod(math2.log) cos = staticmethod(math2.cos) sin = staticmethod(math2.sin) tan = staticmethod(math2.tan) cos_sin = staticmethod(math2.cos_sin) acos = staticmethod(math2.acos) asin = staticmethod(math2.asin) atan = staticmethod(math2.atan) cosh = staticmethod(math2.cosh) sinh = staticmethod(math2.sinh) tanh = staticmethod(math2.tanh) gamma = staticmethod(math2.gamma) rgamma = staticmethod(math2.rgamma) fac = factorial = staticmethod(math2.factorial) floor = staticmethod(math2.floor) ceil = staticmethod(math2.ceil) cospi = staticmethod(math2.cospi) sinpi = staticmethod(math2.sinpi) cbrt = staticmethod(math2.cbrt) _nthroot = staticmethod(math2.nthroot) _ei = staticmethod(math2.ei) _e1 = staticmethod(math2.e1) _zeta = _zeta_int = staticmethod(math2.zeta) # XXX: math2 def arg(ctx, z): z = complex(z) return math.atan2(z.imag, z.real) def expj(ctx, x): return ctx.exp(ctx.j*x) def expjpi(ctx, x): return ctx.exp(ctx.j*ctx.pi*x) ldexp = math.ldexp frexp = math.frexp def mag(ctx, z): if z: return ctx.frexp(abs(z))[1] return ctx.ninf def isint(ctx, z): if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 if z.imag: return False z = z.real try: return z == int(z) except: return False def nint_distance(ctx, z): if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 n = round(z.real) else: n = round(z) if n == z: return n, ctx.ninf return n, ctx.mag(abs(z-n)) def _convert_param(ctx, z): if type(z) is tuple: p, q = z return ctx.mpf(p) / q, 'R' if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 intz = int(z.real) else: intz = int(z) if z == intz: return intz, 'Z' return z, 'R' def _is_real_type(ctx, z): return isinstance(z, float) or isinstance(z, int_types) def _is_complex_type(ctx, z): return isinstance(z, complex) def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs): coeffs = list(coeffs) num = range(p) den = range(p,p+q) tol = ctx.eps s = t = 1.0 k = 0 while 1: for i in num: t *= (coeffs[i]+k) for i in den: t /= (coeffs[i]+k) k += 1; t /= k; t *= z; s += t if abs(t) < tol: return s if k > maxterms: raise ctx.NoConvergence def atan2(ctx, x, y): return math.atan2(x, y) def psi(ctx, m, z): m = int(m) if m == 0: return ctx.digamma(z) return (-1)**(m+1) * ctx.fac(m) * ctx.zeta(m+1, z) digamma = staticmethod(math2.digamma) def harmonic(ctx, x): x = ctx.convert(x) if x == 0 or x == 1: return x return ctx.digamma(x+1) + ctx.euler nstr = str def to_fixed(ctx, x, prec): return int(math.ldexp(x, prec)) def rand(ctx): import random return random.random() _erf = staticmethod(math2.erf) _erfc = staticmethod(math2.erfc) def sum_accurately(ctx, terms, check_step=1): s = ctx.zero k = 0 for term in terms(): s += term if (not k % check_step) and term: if abs(term) <= 1e-18*abs(s): break k += 1 return s mpmath-1.1.0/mpmath/ctx_iv.py000066400000000000000000000406361340375245600161550ustar00rootroot00000000000000import operator from . import libmp from .libmp.backend import basestring from .libmp import ( int_types, MPZ_ONE, prec_to_dps, dps_to_prec, repr_dps, round_floor, round_ceiling, fzero, finf, fninf, fnan, mpf_le, mpf_neg, from_int, from_float, from_str, from_rational, mpi_mid, mpi_delta, mpi_str, mpi_abs, mpi_pos, mpi_neg, mpi_add, mpi_sub, mpi_mul, mpi_div, mpi_pow_int, mpi_pow, mpi_from_str, mpci_pos, mpci_neg, mpci_add, mpci_sub, mpci_mul, mpci_div, mpci_pow, mpci_abs, mpci_pow, mpci_exp, mpci_log, ComplexResult, mpf_hash, mpc_hash) mpi_zero = (fzero, fzero) from .ctx_base import StandardBaseContext new = object.__new__ def convert_mpf_(x, prec, rounding): if hasattr(x, "_mpf_"): return x._mpf_ if isinstance(x, int_types): return from_int(x, prec, rounding) if isinstance(x, float): return from_float(x, prec, rounding) if isinstance(x, basestring): return from_str(x, prec, rounding) class ivmpf(object): """ Interval arithmetic class. Precision is controlled by iv.prec. """ def __new__(cls, x=0): return cls.ctx.convert(x) def __int__(self): a, b = self._mpi_ if a == b: return int(libmp.to_int(a)) raise ValueError def __hash__(self): a, b = self._mpi_ if a == b: return mpf_hash(a) else: return hash(self._mpi_) @property def real(self): return self @property def imag(self): return self.ctx.zero def conjugate(self): return self @property def a(self): a, b = self._mpi_ return self.ctx.make_mpf((a, a)) @property def b(self): a, b = self._mpi_ return self.ctx.make_mpf((b, b)) @property def mid(self): ctx = self.ctx v = mpi_mid(self._mpi_, ctx.prec) return ctx.make_mpf((v, v)) @property def delta(self): ctx = self.ctx v = mpi_delta(self._mpi_, ctx.prec) return ctx.make_mpf((v,v)) @property def _mpci_(self): return self._mpi_, mpi_zero def _compare(*args): raise TypeError("no ordering relation is defined for intervals") __gt__ = _compare __le__ = _compare __gt__ = _compare __ge__ = _compare def __contains__(self, t): t = self.ctx.mpf(t) return (self.a <= t.a) and (t.b <= self.b) def __str__(self): return mpi_str(self._mpi_, self.ctx.prec) def __repr__(self): if self.ctx.pretty: return str(self) a, b = self._mpi_ n = repr_dps(self.ctx.prec) a = libmp.to_str(a, n) b = libmp.to_str(b, n) return "mpi(%r, %r)" % (a, b) def _compare(s, t, cmpfun): if not hasattr(t, "_mpi_"): try: t = s.ctx.convert(t) except: return NotImplemented return cmpfun(s._mpi_, t._mpi_) def __eq__(s, t): return s._compare(t, libmp.mpi_eq) def __ne__(s, t): return s._compare(t, libmp.mpi_ne) def __lt__(s, t): return s._compare(t, libmp.mpi_lt) def __le__(s, t): return s._compare(t, libmp.mpi_le) def __gt__(s, t): return s._compare(t, libmp.mpi_gt) def __ge__(s, t): return s._compare(t, libmp.mpi_ge) def __abs__(self): return self.ctx.make_mpf(mpi_abs(self._mpi_, self.ctx.prec)) def __pos__(self): return self.ctx.make_mpf(mpi_pos(self._mpi_, self.ctx.prec)) def __neg__(self): return self.ctx.make_mpf(mpi_neg(self._mpi_, self.ctx.prec)) def ae(s, t, rel_eps=None, abs_eps=None): return s.ctx.almosteq(s, t, rel_eps, abs_eps) class ivmpc(object): def __new__(cls, re=0, im=0): re = cls.ctx.convert(re) im = cls.ctx.convert(im) y = new(cls) y._mpci_ = re._mpi_, im._mpi_ return y def __hash__(self): (a, b), (c,d) = self._mpci_ if a == b and c == d: return mpc_hash((a, c)) else: return hash(self._mpci_) def __repr__(s): if s.ctx.pretty: return str(s) return "iv.mpc(%s, %s)" % (repr(s.real), repr(s.imag)) def __str__(s): return "(%s + %s*j)" % (str(s.real), str(s.imag)) @property def a(self): (a, b), (c,d) = self._mpci_ return self.ctx.make_mpf((a, a)) @property def b(self): (a, b), (c,d) = self._mpci_ return self.ctx.make_mpf((b, b)) @property def c(self): (a, b), (c,d) = self._mpci_ return self.ctx.make_mpf((c, c)) @property def d(self): (a, b), (c,d) = self._mpci_ return self.ctx.make_mpf((d, d)) @property def real(s): return s.ctx.make_mpf(s._mpci_[0]) @property def imag(s): return s.ctx.make_mpf(s._mpci_[1]) def conjugate(s): a, b = s._mpci_ return s.ctx.make_mpc((a, mpf_neg(b))) def overlap(s, t): t = s.ctx.convert(t) 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) 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) return real_overlap and imag_overlap def __contains__(s, t): t = s.ctx.convert(t) return t.real in s.real and t.imag in s.imag def _compare(s, t, ne=False): if not isinstance(t, s.ctx._types): try: t = s.ctx.convert(t) except: return NotImplemented if hasattr(t, '_mpi_'): tval = t._mpi_, mpi_zero elif hasattr(t, '_mpci_'): tval = t._mpci_ if ne: return s._mpci_ != tval return s._mpci_ == tval def __eq__(s, t): return s._compare(t) def __ne__(s, t): return s._compare(t, True) def __lt__(s, t): raise TypeError("complex intervals cannot be ordered") __le__ = __gt__ = __ge__ = __lt__ def __neg__(s): return s.ctx.make_mpc(mpci_neg(s._mpci_, s.ctx.prec)) def __pos__(s): return s.ctx.make_mpc(mpci_pos(s._mpci_, s.ctx.prec)) def __abs__(s): return s.ctx.make_mpf(mpci_abs(s._mpci_, s.ctx.prec)) def ae(s, t, rel_eps=None, abs_eps=None): return s.ctx.almosteq(s, t, rel_eps, abs_eps) def _binary_op(f_real, f_complex): def g_complex(ctx, sval, tval): return ctx.make_mpc(f_complex(sval, tval, ctx.prec)) def g_real(ctx, sval, tval): try: return ctx.make_mpf(f_real(sval, tval, ctx.prec)) except ComplexResult: sval = (sval, mpi_zero) tval = (tval, mpi_zero) return g_complex(ctx, sval, tval) def lop_real(s, t): ctx = s.ctx if not isinstance(t, ctx._types): t = ctx.convert(t) if hasattr(t, "_mpi_"): return g_real(ctx, s._mpi_, t._mpi_) if hasattr(t, "_mpci_"): return g_complex(ctx, (s._mpi_, mpi_zero), t._mpci_) return NotImplemented def rop_real(s, t): ctx = s.ctx if not isinstance(t, ctx._types): t = ctx.convert(t) if hasattr(t, "_mpi_"): return g_real(ctx, t._mpi_, s._mpi_) if hasattr(t, "_mpci_"): return g_complex(ctx, t._mpci_, (s._mpi_, mpi_zero)) return NotImplemented def lop_complex(s, t): ctx = s.ctx if not isinstance(t, s.ctx._types): try: t = s.ctx.convert(t) except (ValueError, TypeError): return NotImplemented return g_complex(ctx, s._mpci_, t._mpci_) def rop_complex(s, t): ctx = s.ctx if not isinstance(t, s.ctx._types): t = s.ctx.convert(t) return g_complex(ctx, t._mpci_, s._mpci_) return lop_real, rop_real, lop_complex, rop_complex ivmpf.__add__, ivmpf.__radd__, ivmpc.__add__, ivmpc.__radd__ = _binary_op(mpi_add, mpci_add) ivmpf.__sub__, ivmpf.__rsub__, ivmpc.__sub__, ivmpc.__rsub__ = _binary_op(mpi_sub, mpci_sub) ivmpf.__mul__, ivmpf.__rmul__, ivmpc.__mul__, ivmpc.__rmul__ = _binary_op(mpi_mul, mpci_mul) ivmpf.__div__, ivmpf.__rdiv__, ivmpc.__div__, ivmpc.__rdiv__ = _binary_op(mpi_div, mpci_div) ivmpf.__pow__, ivmpf.__rpow__, ivmpc.__pow__, ivmpc.__rpow__ = _binary_op(mpi_pow, mpci_pow) ivmpf.__truediv__ = ivmpf.__div__; ivmpf.__rtruediv__ = ivmpf.__rdiv__ ivmpc.__truediv__ = ivmpc.__div__; ivmpc.__rtruediv__ = ivmpc.__rdiv__ class ivmpf_constant(ivmpf): def __new__(cls, f): self = new(cls) self._f = f return self def _get_mpi_(self): prec = self.ctx._prec[0] a = self._f(prec, round_floor) b = self._f(prec, round_ceiling) return a, b _mpi_ = property(_get_mpi_) class MPIntervalContext(StandardBaseContext): def __init__(ctx): ctx.mpf = type('ivmpf', (ivmpf,), {}) ctx.mpc = type('ivmpc', (ivmpc,), {}) ctx._types = (ctx.mpf, ctx.mpc) ctx._constant = type('ivmpf_constant', (ivmpf_constant,), {}) ctx._prec = [53] ctx._set_prec(53) ctx._constant._ctxdata = ctx.mpf._ctxdata = ctx.mpc._ctxdata = [ctx.mpf, new, ctx._prec] ctx._constant.ctx = ctx.mpf.ctx = ctx.mpc.ctx = ctx ctx.pretty = False StandardBaseContext.__init__(ctx) ctx._init_builtins() def _mpi(ctx, a, b=None): if b is None: return ctx.mpf(a) return ctx.mpf((a,b)) def _init_builtins(ctx): ctx.one = ctx.mpf(1) ctx.zero = ctx.mpf(0) ctx.inf = ctx.mpf('inf') ctx.ninf = -ctx.inf ctx.nan = ctx.mpf('nan') ctx.j = ctx.mpc(0,1) ctx.exp = ctx._wrap_mpi_function(libmp.mpi_exp, libmp.mpci_exp) ctx.sqrt = ctx._wrap_mpi_function(libmp.mpi_sqrt) ctx.ln = ctx._wrap_mpi_function(libmp.mpi_log, libmp.mpci_log) ctx.cos = ctx._wrap_mpi_function(libmp.mpi_cos, libmp.mpci_cos) ctx.sin = ctx._wrap_mpi_function(libmp.mpi_sin, libmp.mpci_sin) ctx.tan = ctx._wrap_mpi_function(libmp.mpi_tan) ctx.gamma = ctx._wrap_mpi_function(libmp.mpi_gamma, libmp.mpci_gamma) ctx.loggamma = ctx._wrap_mpi_function(libmp.mpi_loggamma, libmp.mpci_loggamma) ctx.rgamma = ctx._wrap_mpi_function(libmp.mpi_rgamma, libmp.mpci_rgamma) ctx.factorial = ctx._wrap_mpi_function(libmp.mpi_factorial, libmp.mpci_factorial) ctx.fac = ctx.factorial ctx.eps = ctx._constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1)) ctx.pi = ctx._constant(libmp.mpf_pi) ctx.e = ctx._constant(libmp.mpf_e) ctx.ln2 = ctx._constant(libmp.mpf_ln2) ctx.ln10 = ctx._constant(libmp.mpf_ln10) ctx.phi = ctx._constant(libmp.mpf_phi) ctx.euler = ctx._constant(libmp.mpf_euler) ctx.catalan = ctx._constant(libmp.mpf_catalan) ctx.glaisher = ctx._constant(libmp.mpf_glaisher) ctx.khinchin = ctx._constant(libmp.mpf_khinchin) ctx.twinprime = ctx._constant(libmp.mpf_twinprime) def _wrap_mpi_function(ctx, f_real, f_complex=None): def g(x, **kwargs): if kwargs: prec = kwargs.get('prec', ctx._prec[0]) else: prec = ctx._prec[0] x = ctx.convert(x) if hasattr(x, "_mpi_"): return ctx.make_mpf(f_real(x._mpi_, prec)) if hasattr(x, "_mpci_"): return ctx.make_mpc(f_complex(x._mpci_, prec)) raise ValueError return g @classmethod def _wrap_specfun(cls, name, f, wrap): if wrap: def f_wrapped(ctx, *args, **kwargs): convert = ctx.convert args = [convert(a) for a in args] prec = ctx.prec try: ctx.prec += 10 retval = f(ctx, *args, **kwargs) finally: ctx.prec = prec return +retval else: f_wrapped = f setattr(cls, name, f_wrapped) def _set_prec(ctx, n): ctx._prec[0] = max(1, int(n)) ctx._dps = prec_to_dps(n) def _set_dps(ctx, n): ctx._prec[0] = dps_to_prec(n) ctx._dps = max(1, int(n)) prec = property(lambda ctx: ctx._prec[0], _set_prec) dps = property(lambda ctx: ctx._dps, _set_dps) def make_mpf(ctx, v): a = new(ctx.mpf) a._mpi_ = v return a def make_mpc(ctx, v): a = new(ctx.mpc) a._mpci_ = v return a def _mpq(ctx, pq): p, q = pq a = libmp.from_rational(p, q, ctx.prec, round_floor) b = libmp.from_rational(p, q, ctx.prec, round_ceiling) return ctx.make_mpf((a, b)) def convert(ctx, x): if isinstance(x, (ctx.mpf, ctx.mpc)): return x if isinstance(x, ctx._constant): return +x if isinstance(x, complex) or hasattr(x, "_mpc_"): re = ctx.convert(x.real) im = ctx.convert(x.imag) return ctx.mpc(re,im) if isinstance(x, basestring): v = mpi_from_str(x, ctx.prec) return ctx.make_mpf(v) if hasattr(x, "_mpi_"): a, b = x._mpi_ else: try: a, b = x except (TypeError, ValueError): a = b = x if hasattr(a, "_mpi_"): a = a._mpi_[0] else: a = convert_mpf_(a, ctx.prec, round_floor) if hasattr(b, "_mpi_"): b = b._mpi_[1] else: b = convert_mpf_(b, ctx.prec, round_ceiling) if a == fnan or b == fnan: a = fninf b = finf assert mpf_le(a, b), "endpoints must be properly ordered" return ctx.make_mpf((a, b)) def nstr(ctx, x, n=5, **kwargs): x = ctx.convert(x) if hasattr(x, "_mpi_"): return libmp.mpi_to_str(x._mpi_, n, **kwargs) if hasattr(x, "_mpci_"): re = libmp.mpi_to_str(x._mpci_[0], n, **kwargs) im = libmp.mpi_to_str(x._mpci_[1], n, **kwargs) return "(%s + %s*j)" % (re, im) def mag(ctx, x): x = ctx.convert(x) if isinstance(x, ctx.mpc): return max(ctx.mag(x.real), ctx.mag(x.imag)) + 1 a, b = libmp.mpi_abs(x._mpi_) sign, man, exp, bc = b if man: return exp+bc if b == fzero: return ctx.ninf if b == fnan: return ctx.nan return ctx.inf def isnan(ctx, x): return False def isinf(ctx, x): return x == ctx.inf def isint(ctx, x): x = ctx.convert(x) a, b = x._mpi_ if a == b: sign, man, exp, bc = a if man: return exp >= 0 return a == fzero return None def ldexp(ctx, x, n): a, b = ctx.convert(x)._mpi_ a = libmp.mpf_shift(a, n) b = libmp.mpf_shift(b, n) return ctx.make_mpf((a,b)) def absmin(ctx, x): return abs(ctx.convert(x)).a def absmax(ctx, x): return abs(ctx.convert(x)).b def atan2(ctx, y, x): y = ctx.convert(y)._mpi_ x = ctx.convert(x)._mpi_ return ctx.make_mpf(libmp.mpi_atan2(y,x,ctx.prec)) def _convert_param(ctx, x): if isinstance(x, libmp.int_types): return x, 'Z' if isinstance(x, tuple): p, q = x return (ctx.mpf(p) / ctx.mpf(q), 'R') x = ctx.convert(x) if isinstance(x, ctx.mpf): return x, 'R' if isinstance(x, ctx.mpc): return x, 'C' raise ValueError def _is_real_type(ctx, z): return isinstance(z, ctx.mpf) or isinstance(z, int_types) def _is_complex_type(ctx, z): return isinstance(z, ctx.mpc) def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs): coeffs = list(coeffs) num = range(p) den = range(p,p+q) #tol = ctx.eps s = t = ctx.one k = 0 while 1: for i in num: t *= (coeffs[i]+k) for i in den: t /= (coeffs[i]+k) k += 1; t /= k; t *= z; s += t if t == 0: return s #if abs(t) < tol: # return s if k > maxterms: raise ctx.NoConvergence # Register with "numbers" ABC # We do not subclass, hence we do not use the @abstractmethod checks. While # this is less invasive it may turn out that we do not actually support # parts of the expected interfaces. See # http://docs.python.org/2/library/numbers.html for list of abstract # methods. try: import numbers numbers.Complex.register(ivmpc) numbers.Real.register(ivmpf) except ImportError: pass mpmath-1.1.0/mpmath/ctx_mp.py000066400000000000000000001410101340375245600161370ustar00rootroot00000000000000""" This module defines the mpf, mpc classes, and standard functions for operating with them. """ __docformat__ = 'plaintext' import re from .ctx_base import StandardBaseContext from .libmp.backend import basestring, BACKEND from . import libmp from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps, round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps, ComplexResult, to_pickable, from_pickable, normalize, from_int, from_float, from_str, to_int, to_float, to_str, from_rational, from_man_exp, fone, fzero, finf, fninf, fnan, mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int, mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod, mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge, mpf_hash, mpf_rand, mpf_sum, bitcount, to_fixed, mpc_to_str, mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate, mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf, mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int, mpc_mpf_div, mpf_pow, mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10, mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin, mpf_glaisher, mpf_twinprime, mpf_mertens, int_types) from . import function_docs from . import rational new = object.__new__ get_complex = re.compile(r'^\(?(?P[\+\-]?\d*\.?\d*(e[\+\-]?\d+)?)??' r'(?P[\+\-]?\d*\.?\d*(e[\+\-]?\d+)?j)?\)?$') if BACKEND == 'sage': from sage.libs.mpmath.ext_main import Context as BaseMPContext # pickle hack import sage.libs.mpmath.ext_main as _mpf_module else: from .ctx_mp_python import PythonMPContext as BaseMPContext from . import ctx_mp_python as _mpf_module from .ctx_mp_python import _mpf, _mpc, mpnumeric class MPContext(BaseMPContext, StandardBaseContext): """ Context for multiprecision arithmetic with a global precision. """ def __init__(ctx): BaseMPContext.__init__(ctx) ctx.trap_complex = False ctx.pretty = False ctx.types = [ctx.mpf, ctx.mpc, ctx.constant] ctx._mpq = rational.mpq ctx.default() StandardBaseContext.__init__(ctx) ctx.mpq = rational.mpq ctx.init_builtins() ctx.hyp_summators = {} ctx._init_aliases() # XXX: automate try: ctx.bernoulli.im_func.func_doc = function_docs.bernoulli ctx.primepi.im_func.func_doc = function_docs.primepi ctx.psi.im_func.func_doc = function_docs.psi ctx.atan2.im_func.func_doc = function_docs.atan2 except AttributeError: # python 3 ctx.bernoulli.__func__.func_doc = function_docs.bernoulli ctx.primepi.__func__.func_doc = function_docs.primepi ctx.psi.__func__.func_doc = function_docs.psi ctx.atan2.__func__.func_doc = function_docs.atan2 ctx.digamma.func_doc = function_docs.digamma ctx.cospi.func_doc = function_docs.cospi ctx.sinpi.func_doc = function_docs.sinpi def init_builtins(ctx): mpf = ctx.mpf mpc = ctx.mpc # Exact constants ctx.one = ctx.make_mpf(fone) ctx.zero = ctx.make_mpf(fzero) ctx.j = ctx.make_mpc((fzero,fone)) ctx.inf = ctx.make_mpf(finf) ctx.ninf = ctx.make_mpf(fninf) ctx.nan = ctx.make_mpf(fnan) eps = ctx.constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1), "epsilon of working precision", "eps") ctx.eps = eps # Approximate constants ctx.pi = ctx.constant(mpf_pi, "pi", "pi") ctx.ln2 = ctx.constant(mpf_ln2, "ln(2)", "ln2") ctx.ln10 = ctx.constant(mpf_ln10, "ln(10)", "ln10") ctx.phi = ctx.constant(mpf_phi, "Golden ratio phi", "phi") ctx.e = ctx.constant(mpf_e, "e = exp(1)", "e") ctx.euler = ctx.constant(mpf_euler, "Euler's constant", "euler") ctx.catalan = ctx.constant(mpf_catalan, "Catalan's constant", "catalan") ctx.khinchin = ctx.constant(mpf_khinchin, "Khinchin's constant", "khinchin") ctx.glaisher = ctx.constant(mpf_glaisher, "Glaisher's constant", "glaisher") ctx.apery = ctx.constant(mpf_apery, "Apery's constant", "apery") ctx.degree = ctx.constant(mpf_degree, "1 deg = pi / 180", "degree") ctx.twinprime = ctx.constant(mpf_twinprime, "Twin prime constant", "twinprime") ctx.mertens = ctx.constant(mpf_mertens, "Mertens' constant", "mertens") # Standard functions ctx.sqrt = ctx._wrap_libmp_function(libmp.mpf_sqrt, libmp.mpc_sqrt) ctx.cbrt = ctx._wrap_libmp_function(libmp.mpf_cbrt, libmp.mpc_cbrt) ctx.ln = ctx._wrap_libmp_function(libmp.mpf_log, libmp.mpc_log) ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan) ctx.exp = ctx._wrap_libmp_function(libmp.mpf_exp, libmp.mpc_exp) ctx.expj = ctx._wrap_libmp_function(libmp.mpf_expj, libmp.mpc_expj) ctx.expjpi = ctx._wrap_libmp_function(libmp.mpf_expjpi, libmp.mpc_expjpi) ctx.sin = ctx._wrap_libmp_function(libmp.mpf_sin, libmp.mpc_sin) ctx.cos = ctx._wrap_libmp_function(libmp.mpf_cos, libmp.mpc_cos) ctx.tan = ctx._wrap_libmp_function(libmp.mpf_tan, libmp.mpc_tan) ctx.sinh = ctx._wrap_libmp_function(libmp.mpf_sinh, libmp.mpc_sinh) ctx.cosh = ctx._wrap_libmp_function(libmp.mpf_cosh, libmp.mpc_cosh) ctx.tanh = ctx._wrap_libmp_function(libmp.mpf_tanh, libmp.mpc_tanh) ctx.asin = ctx._wrap_libmp_function(libmp.mpf_asin, libmp.mpc_asin) ctx.acos = ctx._wrap_libmp_function(libmp.mpf_acos, libmp.mpc_acos) ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan) ctx.asinh = ctx._wrap_libmp_function(libmp.mpf_asinh, libmp.mpc_asinh) ctx.acosh = ctx._wrap_libmp_function(libmp.mpf_acosh, libmp.mpc_acosh) ctx.atanh = ctx._wrap_libmp_function(libmp.mpf_atanh, libmp.mpc_atanh) ctx.sinpi = ctx._wrap_libmp_function(libmp.mpf_sin_pi, libmp.mpc_sin_pi) ctx.cospi = ctx._wrap_libmp_function(libmp.mpf_cos_pi, libmp.mpc_cos_pi) ctx.floor = ctx._wrap_libmp_function(libmp.mpf_floor, libmp.mpc_floor) ctx.ceil = ctx._wrap_libmp_function(libmp.mpf_ceil, libmp.mpc_ceil) ctx.nint = ctx._wrap_libmp_function(libmp.mpf_nint, libmp.mpc_nint) ctx.frac = ctx._wrap_libmp_function(libmp.mpf_frac, libmp.mpc_frac) ctx.fib = ctx.fibonacci = ctx._wrap_libmp_function(libmp.mpf_fibonacci, libmp.mpc_fibonacci) ctx.gamma = ctx._wrap_libmp_function(libmp.mpf_gamma, libmp.mpc_gamma) ctx.rgamma = ctx._wrap_libmp_function(libmp.mpf_rgamma, libmp.mpc_rgamma) ctx.loggamma = ctx._wrap_libmp_function(libmp.mpf_loggamma, libmp.mpc_loggamma) ctx.fac = ctx.factorial = ctx._wrap_libmp_function(libmp.mpf_factorial, libmp.mpc_factorial) ctx.gamma_old = ctx._wrap_libmp_function(libmp.mpf_gamma_old, libmp.mpc_gamma_old) ctx.fac_old = ctx.factorial_old = ctx._wrap_libmp_function(libmp.mpf_factorial_old, libmp.mpc_factorial_old) ctx.digamma = ctx._wrap_libmp_function(libmp.mpf_psi0, libmp.mpc_psi0) ctx.harmonic = ctx._wrap_libmp_function(libmp.mpf_harmonic, libmp.mpc_harmonic) ctx.ei = ctx._wrap_libmp_function(libmp.mpf_ei, libmp.mpc_ei) ctx.e1 = ctx._wrap_libmp_function(libmp.mpf_e1, libmp.mpc_e1) ctx._ci = ctx._wrap_libmp_function(libmp.mpf_ci, libmp.mpc_ci) ctx._si = ctx._wrap_libmp_function(libmp.mpf_si, libmp.mpc_si) ctx.ellipk = ctx._wrap_libmp_function(libmp.mpf_ellipk, libmp.mpc_ellipk) ctx._ellipe = ctx._wrap_libmp_function(libmp.mpf_ellipe, libmp.mpc_ellipe) ctx.agm1 = ctx._wrap_libmp_function(libmp.mpf_agm1, libmp.mpc_agm1) ctx._erf = ctx._wrap_libmp_function(libmp.mpf_erf, None) ctx._erfc = ctx._wrap_libmp_function(libmp.mpf_erfc, None) ctx._zeta = ctx._wrap_libmp_function(libmp.mpf_zeta, libmp.mpc_zeta) ctx._altzeta = ctx._wrap_libmp_function(libmp.mpf_altzeta, libmp.mpc_altzeta) # Faster versions ctx.sqrt = getattr(ctx, "_sage_sqrt", ctx.sqrt) ctx.exp = getattr(ctx, "_sage_exp", ctx.exp) ctx.ln = getattr(ctx, "_sage_ln", ctx.ln) ctx.cos = getattr(ctx, "_sage_cos", ctx.cos) ctx.sin = getattr(ctx, "_sage_sin", ctx.sin) def to_fixed(ctx, x, prec): return x.to_fixed(prec) def hypot(ctx, x, y): r""" Computes the Euclidean norm of the vector `(x, y)`, equal to `\sqrt{x^2 + y^2}`. Both `x` and `y` must be real.""" x = ctx.convert(x) y = ctx.convert(y) return ctx.make_mpf(libmp.mpf_hypot(x._mpf_, y._mpf_, *ctx._prec_rounding)) def _gamma_upper_int(ctx, n, z): n = int(ctx._re(n)) if n == 0: return ctx.e1(z) if not hasattr(z, '_mpf_'): raise NotImplementedError prec, rounding = ctx._prec_rounding real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding, gamma=True) if imag is None: return ctx.make_mpf(real) else: return ctx.make_mpc((real, imag)) def _expint_int(ctx, n, z): n = int(n) if n == 1: return ctx.e1(z) if not hasattr(z, '_mpf_'): raise NotImplementedError prec, rounding = ctx._prec_rounding real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding) if imag is None: return ctx.make_mpf(real) else: return ctx.make_mpc((real, imag)) def _nthroot(ctx, x, n): if hasattr(x, '_mpf_'): try: return ctx.make_mpf(libmp.mpf_nthroot(x._mpf_, n, *ctx._prec_rounding)) except ComplexResult: if ctx.trap_complex: raise x = (x._mpf_, libmp.fzero) else: x = x._mpc_ return ctx.make_mpc(libmp.mpc_nthroot(x, n, *ctx._prec_rounding)) def _besselj(ctx, n, z): prec, rounding = ctx._prec_rounding if hasattr(z, '_mpf_'): return ctx.make_mpf(libmp.mpf_besseljn(n, z._mpf_, prec, rounding)) elif hasattr(z, '_mpc_'): return ctx.make_mpc(libmp.mpc_besseljn(n, z._mpc_, prec, rounding)) def _agm(ctx, a, b=1): prec, rounding = ctx._prec_rounding if hasattr(a, '_mpf_') and hasattr(b, '_mpf_'): try: v = libmp.mpf_agm(a._mpf_, b._mpf_, prec, rounding) return ctx.make_mpf(v) except ComplexResult: pass if hasattr(a, '_mpf_'): a = (a._mpf_, libmp.fzero) else: a = a._mpc_ if hasattr(b, '_mpf_'): b = (b._mpf_, libmp.fzero) else: b = b._mpc_ return ctx.make_mpc(libmp.mpc_agm(a, b, prec, rounding)) def bernoulli(ctx, n): return ctx.make_mpf(libmp.mpf_bernoulli(int(n), *ctx._prec_rounding)) def _zeta_int(ctx, n): return ctx.make_mpf(libmp.mpf_zeta_int(int(n), *ctx._prec_rounding)) def atan2(ctx, y, x): x = ctx.convert(x) y = ctx.convert(y) return ctx.make_mpf(libmp.mpf_atan2(y._mpf_, x._mpf_, *ctx._prec_rounding)) def psi(ctx, m, z): z = ctx.convert(z) m = int(m) if ctx._is_real_type(z): return ctx.make_mpf(libmp.mpf_psi(m, z._mpf_, *ctx._prec_rounding)) else: return ctx.make_mpc(libmp.mpc_psi(m, z._mpc_, *ctx._prec_rounding)) def cos_sin(ctx, x, **kwargs): if type(x) not in ctx.types: x = ctx.convert(x) prec, rounding = ctx._parse_prec(kwargs) if hasattr(x, '_mpf_'): c, s = libmp.mpf_cos_sin(x._mpf_, prec, rounding) return ctx.make_mpf(c), ctx.make_mpf(s) elif hasattr(x, '_mpc_'): c, s = libmp.mpc_cos_sin(x._mpc_, prec, rounding) return ctx.make_mpc(c), ctx.make_mpc(s) else: return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs) def cospi_sinpi(ctx, x, **kwargs): if type(x) not in ctx.types: x = ctx.convert(x) prec, rounding = ctx._parse_prec(kwargs) if hasattr(x, '_mpf_'): c, s = libmp.mpf_cos_sin_pi(x._mpf_, prec, rounding) return ctx.make_mpf(c), ctx.make_mpf(s) elif hasattr(x, '_mpc_'): c, s = libmp.mpc_cos_sin_pi(x._mpc_, prec, rounding) return ctx.make_mpc(c), ctx.make_mpc(s) else: return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs) def clone(ctx): """ Create a copy of the context, with the same working precision. """ a = ctx.__class__() a.prec = ctx.prec return a # Several helper methods # TODO: add more of these, make consistent, write docstrings, ... def _is_real_type(ctx, x): if hasattr(x, '_mpc_') or type(x) is complex: return False return True def _is_complex_type(ctx, x): if hasattr(x, '_mpc_') or type(x) is complex: return True return False def isnan(ctx, x): """ Return *True* if *x* is a NaN (not-a-number), or for a complex number, whether either the real or complex part is NaN; otherwise return *False*:: >>> from mpmath import * >>> isnan(3.14) False >>> isnan(nan) True >>> isnan(mpc(3.14,2.72)) False >>> isnan(mpc(3.14,nan)) True """ if hasattr(x, "_mpf_"): return x._mpf_ == fnan if hasattr(x, "_mpc_"): return fnan in x._mpc_ if isinstance(x, int_types) or isinstance(x, rational.mpq): return False x = ctx.convert(x) if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): return ctx.isnan(x) raise TypeError("isnan() needs a number as input") def isfinite(ctx, x): """ Return *True* if *x* is a finite number, i.e. neither an infinity or a NaN. >>> from mpmath import * >>> isfinite(inf) False >>> isfinite(-inf) False >>> isfinite(3) True >>> isfinite(nan) False >>> isfinite(3+4j) True >>> isfinite(mpc(3,inf)) False >>> isfinite(mpc(nan,3)) False """ if ctx.isinf(x) or ctx.isnan(x): return False return True def isnpint(ctx, x): """ Determine if *x* is a nonpositive integer. """ if not x: return True if hasattr(x, '_mpf_'): sign, man, exp, bc = x._mpf_ return sign and exp >= 0 if hasattr(x, '_mpc_'): return not x.imag and ctx.isnpint(x.real) if type(x) in int_types: return x <= 0 if isinstance(x, ctx.mpq): p, q = x._mpq_ if not p: return True return q == 1 and p <= 0 return ctx.isnpint(ctx.convert(x)) def __str__(ctx): lines = ["Mpmath settings:", (" mp.prec = %s" % ctx.prec).ljust(30) + "[default: 53]", (" mp.dps = %s" % ctx.dps).ljust(30) + "[default: 15]", (" mp.trap_complex = %s" % ctx.trap_complex).ljust(30) + "[default: False]", ] return "\n".join(lines) @property def _repr_digits(ctx): return repr_dps(ctx._prec) @property def _str_digits(ctx): return ctx._dps def extraprec(ctx, n, normalize_output=False): """ The block with extraprec(n): increases the precision n bits, executes , and then restores the precision. extraprec(n)(f) returns a decorated version of the function f that increases the working precision by n bits before execution, and restores the parent precision afterwards. With normalize_output=True, it rounds the return value to the parent precision. """ return PrecisionManager(ctx, lambda p: p + n, None, normalize_output) def extradps(ctx, n, normalize_output=False): """ This function is analogous to extraprec (see documentation) but changes the decimal precision instead of the number of bits. """ return PrecisionManager(ctx, None, lambda d: d + n, normalize_output) def workprec(ctx, n, normalize_output=False): """ The block with workprec(n): sets the precision to n bits, executes , and then restores the precision. workprec(n)(f) returns a decorated version of the function f that sets the precision to n bits before execution, and restores the precision afterwards. With normalize_output=True, it rounds the return value to the parent precision. """ return PrecisionManager(ctx, lambda p: n, None, normalize_output) def workdps(ctx, n, normalize_output=False): """ This function is analogous to workprec (see documentation) but changes the decimal precision instead of the number of bits. """ return PrecisionManager(ctx, None, lambda d: n, normalize_output) def autoprec(ctx, f, maxprec=None, catch=(), verbose=False): r""" Return a wrapped copy of *f* that repeatedly evaluates *f* with increasing precision until the result converges to the full precision used at the point of the call. This heuristically protects against rounding errors, at the cost of roughly a 2x slowdown compared to manually setting the optimal precision. This method can, however, easily be fooled if the results from *f* depend "discontinuously" on the precision, for instance if catastrophic cancellation can occur. Therefore, :func:`~mpmath.autoprec` should be used judiciously. **Examples** Many functions are sensitive to perturbations of the input arguments. If the arguments are decimal numbers, they may have to be converted to binary at a much higher precision. If the amount of required extra precision is unknown, :func:`~mpmath.autoprec` is convenient:: >>> from mpmath import * >>> mp.dps = 15 >>> mp.pretty = True >>> besselj(5, 125 * 10**28) # Exact input -8.03284785591801e-17 >>> besselj(5, '1.25e30') # Bad 7.12954868316652e-16 >>> autoprec(besselj)(5, '1.25e30') # Good -8.03284785591801e-17 The following fails to converge because `\sin(\pi) = 0` whereas all finite-precision approximations of `\pi` give nonzero values:: >>> autoprec(sin)(pi) # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... NoConvergence: autoprec: prec increased to 2910 without convergence As the following example shows, :func:`~mpmath.autoprec` can protect against cancellation, but is fooled by too severe cancellation:: >>> x = 1e-10 >>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x) 1.00000008274037e-10 1.00000000005e-10 1.00000000005e-10 >>> x = 1e-50 >>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x) 0.0 1.0e-50 0.0 With *catch*, an exception or list of exceptions to intercept may be specified. The raised exception is interpreted as signaling insufficient precision. This permits, for example, evaluating a function where a too low precision results in a division by zero:: >>> f = lambda x: 1/(exp(x)-1) >>> f(1e-30) Traceback (most recent call last): ... ZeroDivisionError >>> autoprec(f, catch=ZeroDivisionError)(1e-30) 1.0e+30 """ def f_autoprec_wrapped(*args, **kwargs): prec = ctx.prec if maxprec is None: maxprec2 = ctx._default_hyper_maxprec(prec) else: maxprec2 = maxprec try: ctx.prec = prec + 10 try: v1 = f(*args, **kwargs) except catch: v1 = ctx.nan prec2 = prec + 20 while 1: ctx.prec = prec2 try: v2 = f(*args, **kwargs) except catch: v2 = ctx.nan if v1 == v2: break err = ctx.mag(v2-v1) - ctx.mag(v2) if err < (-prec): break if verbose: print("autoprec: target=%s, prec=%s, accuracy=%s" \ % (prec, prec2, -err)) v1 = v2 if prec2 >= maxprec2: raise ctx.NoConvergence(\ "autoprec: prec increased to %i without convergence"\ % prec2) prec2 += int(prec2*2) prec2 = min(prec2, maxprec2) finally: ctx.prec = prec return +v2 return f_autoprec_wrapped def nstr(ctx, x, n=6, **kwargs): """ Convert an ``mpf`` or ``mpc`` to a decimal string literal with *n* significant digits. The small default value for *n* is chosen to make this function useful for printing collections of numbers (lists, matrices, etc). If *x* is a list or tuple, :func:`~mpmath.nstr` is applied recursively to each element. For unrecognized classes, :func:`~mpmath.nstr` simply returns ``str(x)``. The companion function :func:`~mpmath.nprint` prints the result instead of returning it. The keyword arguments *strip_zeros*, *min_fixed*, *max_fixed* and *show_zero_exponent* are forwarded to :func:`~mpmath.libmp.to_str`. The number will be printed in fixed-point format if the position of the leading digit is strictly between min_fixed (default = min(-dps/3,-5)) and max_fixed (default = dps). To force fixed-point format always, set min_fixed = -inf, max_fixed = +inf. To force floating-point format, set min_fixed >= max_fixed. >>> from mpmath import * >>> nstr([+pi, ldexp(1,-500)]) '[3.14159, 3.05494e-151]' >>> nprint([+pi, ldexp(1,-500)]) [3.14159, 3.05494e-151] >>> nstr(mpf("5e-10"), 5) '5.0e-10' >>> nstr(mpf("5e-10"), 5, strip_zeros=False) '5.0000e-10' >>> nstr(mpf("5e-10"), 5, strip_zeros=False, min_fixed=-11) '0.00000000050000' >>> nstr(mpf(0), 5, show_zero_exponent=True) '0.0e+0' """ if isinstance(x, list): return "[%s]" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x)) if isinstance(x, tuple): return "(%s)" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x)) if hasattr(x, '_mpf_'): return to_str(x._mpf_, n, **kwargs) if hasattr(x, '_mpc_'): return "(" + mpc_to_str(x._mpc_, n, **kwargs) + ")" if isinstance(x, basestring): return repr(x) if isinstance(x, ctx.matrix): return x.__nstr__(n, **kwargs) return str(x) def _convert_fallback(ctx, x, strings): if strings and isinstance(x, basestring): if 'j' in x.lower(): x = x.lower().replace(' ', '') match = get_complex.match(x) re = match.group('re') if not re: re = 0 im = match.group('im').rstrip('j') return ctx.mpc(ctx.convert(re), ctx.convert(im)) if hasattr(x, "_mpi_"): a, b = x._mpi_ if a == b: return ctx.make_mpf(a) else: raise ValueError("can only create mpf from zero-width interval") raise TypeError("cannot create mpf from " + repr(x)) def mpmathify(ctx, *args, **kwargs): return ctx.convert(*args, **kwargs) def _parse_prec(ctx, kwargs): if kwargs: if kwargs.get('exact'): return 0, 'f' prec, rounding = ctx._prec_rounding if 'rounding' in kwargs: rounding = kwargs['rounding'] if 'prec' in kwargs: prec = kwargs['prec'] if prec == ctx.inf: return 0, 'f' else: prec = int(prec) elif 'dps' in kwargs: dps = kwargs['dps'] if dps == ctx.inf: return 0, 'f' prec = dps_to_prec(dps) return prec, rounding return ctx._prec_rounding _exact_overflow_msg = "the exact result does not fit in memory" _hypsum_msg = """hypsum() failed to converge to the requested %i bits of accuracy using a working precision of %i bits. Try with a higher maxprec, maxterms, or set zeroprec.""" def hypsum(ctx, p, q, flags, coeffs, z, accurate_small=True, **kwargs): if hasattr(z, "_mpf_"): key = p, q, flags, 'R' v = z._mpf_ elif hasattr(z, "_mpc_"): key = p, q, flags, 'C' v = z._mpc_ if key not in ctx.hyp_summators: ctx.hyp_summators[key] = libmp.make_hyp_summator(key)[1] summator = ctx.hyp_summators[key] prec = ctx.prec maxprec = kwargs.get('maxprec', ctx._default_hyper_maxprec(prec)) extraprec = 50 epsshift = 25 # Jumps in magnitude occur when parameters are close to negative # integers. We must ensure that these terms are included in # the sum and added accurately magnitude_check = {} max_total_jump = 0 for i, c in enumerate(coeffs): if flags[i] == 'Z': if i >= p and c <= 0: ok = False for ii, cc in enumerate(coeffs[:p]): # Note: c <= cc or c < cc, depending on convention if flags[ii] == 'Z' and cc <= 0 and c <= cc: ok = True if not ok: raise ZeroDivisionError("pole in hypergeometric series") continue n, d = ctx.nint_distance(c) n = -int(n) d = -d if i >= p and n >= 0 and d > 4: if n in magnitude_check: magnitude_check[n] += d else: magnitude_check[n] = d extraprec = max(extraprec, d - prec + 60) max_total_jump += abs(d) while 1: if extraprec > maxprec: raise ValueError(ctx._hypsum_msg % (prec, prec+extraprec)) wp = prec + extraprec if magnitude_check: mag_dict = dict((n,None) for n in magnitude_check) else: mag_dict = {} zv, have_complex, magnitude = summator(coeffs, v, prec, wp, \ epsshift, mag_dict, **kwargs) cancel = -magnitude jumps_resolved = True if extraprec < max_total_jump: for n in mag_dict.values(): if (n is None) or (n < prec): jumps_resolved = False break accurate = (cancel < extraprec-25-5 or not accurate_small) if jumps_resolved: if accurate: break # zero? zeroprec = kwargs.get('zeroprec') if zeroprec is not None: if cancel > zeroprec: if have_complex: return ctx.mpc(0) else: return ctx.zero # Some near-singularities were not included, so increase # precision and repeat until they are extraprec *= 2 # Possible workaround for bad roundoff in fixed-point arithmetic epsshift += 5 extraprec += 5 if type(zv) is tuple: if have_complex: return ctx.make_mpc(zv) else: return ctx.make_mpf(zv) else: return zv def ldexp(ctx, x, n): r""" Computes `x 2^n` efficiently. No rounding is performed. The argument `x` must be a real floating-point number (or possible to convert into one) and `n` must be a Python ``int``. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> ldexp(1, 10) mpf('1024.0') >>> ldexp(1, -3) mpf('0.125') """ x = ctx.convert(x) return ctx.make_mpf(libmp.mpf_shift(x._mpf_, n)) def frexp(ctx, x): r""" Given a real number `x`, returns `(y, n)` with `y \in [0.5, 1)`, `n` a Python integer, and such that `x = y 2^n`. No rounding is performed. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> frexp(7.5) (mpf('0.9375'), 3) """ x = ctx.convert(x) y, n = libmp.mpf_frexp(x._mpf_) return ctx.make_mpf(y), n def fneg(ctx, x, **kwargs): """ Negates the number *x*, giving a floating-point result, optionally using a custom precision and rounding mode. See the documentation of :func:`~mpmath.fadd` for a detailed description of how to specify precision and rounding. **Examples** An mpmath number is returned:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fneg(2.5) mpf('-2.5') >>> fneg(-5+2j) mpc(real='5.0', imag='-2.0') Precise control over rounding is possible:: >>> x = fadd(2, 1e-100, exact=True) >>> fneg(x) mpf('-2.0') >>> fneg(x, rounding='f') mpf('-2.0000000000000004') Negating with and without roundoff:: >>> n = 200000000000000000000001 >>> print(int(-mpf(n))) -200000000000000016777216 >>> print(int(fneg(n))) -200000000000000016777216 >>> print(int(fneg(n, prec=log(n,2)+1))) -200000000000000000000001 >>> print(int(fneg(n, dps=log(n,10)+1))) -200000000000000000000001 >>> print(int(fneg(n, prec=inf))) -200000000000000000000001 >>> print(int(fneg(n, dps=inf))) -200000000000000000000001 >>> print(int(fneg(n, exact=True))) -200000000000000000000001 """ prec, rounding = ctx._parse_prec(kwargs) x = ctx.convert(x) if hasattr(x, '_mpf_'): return ctx.make_mpf(mpf_neg(x._mpf_, prec, rounding)) if hasattr(x, '_mpc_'): return ctx.make_mpc(mpc_neg(x._mpc_, prec, rounding)) raise ValueError("Arguments need to be mpf or mpc compatible numbers") def fadd(ctx, x, y, **kwargs): """ Adds the numbers *x* and *y*, giving a floating-point result, optionally using a custom precision and rounding mode. The default precision is the working precision of the context. You can specify a custom precision in bits by passing the *prec* keyword argument, or by providing an equivalent decimal precision with the *dps* keyword argument. If the precision is set to ``+inf``, or if the flag *exact=True* is passed, an exact addition with no rounding is performed. When the precision is finite, the optional *rounding* keyword argument specifies the direction of rounding. Valid options are ``'n'`` for nearest (default), ``'f'`` for floor, ``'c'`` for ceiling, ``'d'`` for down, ``'u'`` for up. **Examples** Using :func:`~mpmath.fadd` with precision and rounding control:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fadd(2, 1e-20) mpf('2.0') >>> fadd(2, 1e-20, rounding='u') mpf('2.0000000000000004') >>> nprint(fadd(2, 1e-20, prec=100), 25) 2.00000000000000000001 >>> nprint(fadd(2, 1e-20, dps=15), 25) 2.0 >>> nprint(fadd(2, 1e-20, dps=25), 25) 2.00000000000000000001 >>> nprint(fadd(2, 1e-20, exact=True), 25) 2.00000000000000000001 Exact addition avoids cancellation errors, enforcing familiar laws of numbers such as `x+y-x = y`, which don't hold in floating-point arithmetic with finite precision:: >>> x, y = mpf(2), mpf('1e-1000') >>> print(x + y - x) 0.0 >>> print(fadd(x, y, prec=inf) - x) 1.0e-1000 >>> print(fadd(x, y, exact=True) - x) 1.0e-1000 Exact addition can be inefficient and may be impossible to perform with large magnitude differences:: >>> fadd(1, '1e-100000000000000000000', prec=inf) Traceback (most recent call last): ... OverflowError: the exact result does not fit in memory """ prec, rounding = ctx._parse_prec(kwargs) x = ctx.convert(x) y = ctx.convert(y) try: if hasattr(x, '_mpf_'): if hasattr(y, '_mpf_'): return ctx.make_mpf(mpf_add(x._mpf_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_add_mpf(y._mpc_, x._mpf_, prec, rounding)) if hasattr(x, '_mpc_'): if hasattr(y, '_mpf_'): return ctx.make_mpc(mpc_add_mpf(x._mpc_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_add(x._mpc_, y._mpc_, prec, rounding)) except (ValueError, OverflowError): raise OverflowError(ctx._exact_overflow_msg) raise ValueError("Arguments need to be mpf or mpc compatible numbers") def fsub(ctx, x, y, **kwargs): """ Subtracts the numbers *x* and *y*, giving a floating-point result, optionally using a custom precision and rounding mode. See the documentation of :func:`~mpmath.fadd` for a detailed description of how to specify precision and rounding. **Examples** Using :func:`~mpmath.fsub` with precision and rounding control:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fsub(2, 1e-20) mpf('2.0') >>> fsub(2, 1e-20, rounding='d') mpf('1.9999999999999998') >>> nprint(fsub(2, 1e-20, prec=100), 25) 1.99999999999999999999 >>> nprint(fsub(2, 1e-20, dps=15), 25) 2.0 >>> nprint(fsub(2, 1e-20, dps=25), 25) 1.99999999999999999999 >>> nprint(fsub(2, 1e-20, exact=True), 25) 1.99999999999999999999 Exact subtraction avoids cancellation errors, enforcing familiar laws of numbers such as `x-y+y = x`, which don't hold in floating-point arithmetic with finite precision:: >>> x, y = mpf(2), mpf('1e1000') >>> print(x - y + y) 0.0 >>> print(fsub(x, y, prec=inf) + y) 2.0 >>> print(fsub(x, y, exact=True) + y) 2.0 Exact addition can be inefficient and may be impossible to perform with large magnitude differences:: >>> fsub(1, '1e-100000000000000000000', prec=inf) Traceback (most recent call last): ... OverflowError: the exact result does not fit in memory """ prec, rounding = ctx._parse_prec(kwargs) x = ctx.convert(x) y = ctx.convert(y) try: if hasattr(x, '_mpf_'): if hasattr(y, '_mpf_'): return ctx.make_mpf(mpf_sub(x._mpf_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_sub((x._mpf_, fzero), y._mpc_, prec, rounding)) if hasattr(x, '_mpc_'): if hasattr(y, '_mpf_'): return ctx.make_mpc(mpc_sub_mpf(x._mpc_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_sub(x._mpc_, y._mpc_, prec, rounding)) except (ValueError, OverflowError): raise OverflowError(ctx._exact_overflow_msg) raise ValueError("Arguments need to be mpf or mpc compatible numbers") def fmul(ctx, x, y, **kwargs): """ Multiplies the numbers *x* and *y*, giving a floating-point result, optionally using a custom precision and rounding mode. See the documentation of :func:`~mpmath.fadd` for a detailed description of how to specify precision and rounding. **Examples** The result is an mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fmul(2, 5.0) mpf('10.0') >>> fmul(0.5j, 0.5) mpc(real='0.0', imag='0.25') Avoiding roundoff:: >>> x, y = 10**10+1, 10**15+1 >>> print(x*y) 10000000001000010000000001 >>> print(mpf(x) * mpf(y)) 1.0000000001e+25 >>> print(int(mpf(x) * mpf(y))) 10000000001000011026399232 >>> print(int(fmul(x, y))) 10000000001000011026399232 >>> print(int(fmul(x, y, dps=25))) 10000000001000010000000001 >>> print(int(fmul(x, y, exact=True))) 10000000001000010000000001 Exact multiplication with complex numbers can be inefficient and may be impossible to perform with large magnitude differences between real and imaginary parts:: >>> x = 1+2j >>> y = mpc(2, '1e-100000000000000000000') >>> fmul(x, y) mpc(real='2.0', imag='4.0') >>> fmul(x, y, rounding='u') mpc(real='2.0', imag='4.0000000000000009') >>> fmul(x, y, exact=True) Traceback (most recent call last): ... OverflowError: the exact result does not fit in memory """ prec, rounding = ctx._parse_prec(kwargs) x = ctx.convert(x) y = ctx.convert(y) try: if hasattr(x, '_mpf_'): if hasattr(y, '_mpf_'): return ctx.make_mpf(mpf_mul(x._mpf_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_mul_mpf(y._mpc_, x._mpf_, prec, rounding)) if hasattr(x, '_mpc_'): if hasattr(y, '_mpf_'): return ctx.make_mpc(mpc_mul_mpf(x._mpc_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_mul(x._mpc_, y._mpc_, prec, rounding)) except (ValueError, OverflowError): raise OverflowError(ctx._exact_overflow_msg) raise ValueError("Arguments need to be mpf or mpc compatible numbers") def fdiv(ctx, x, y, **kwargs): """ Divides the numbers *x* and *y*, giving a floating-point result, optionally using a custom precision and rounding mode. See the documentation of :func:`~mpmath.fadd` for a detailed description of how to specify precision and rounding. **Examples** The result is an mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fdiv(3, 2) mpf('1.5') >>> fdiv(2, 3) mpf('0.66666666666666663') >>> fdiv(2+4j, 0.5) mpc(real='4.0', imag='8.0') The rounding direction and precision can be controlled:: >>> fdiv(2, 3, dps=3) # Should be accurate to at least 3 digits mpf('0.6666259765625') >>> fdiv(2, 3, rounding='d') mpf('0.66666666666666663') >>> fdiv(2, 3, prec=60) mpf('0.66666666666666667') >>> fdiv(2, 3, rounding='u') mpf('0.66666666666666674') Checking the error of a division by performing it at higher precision:: >>> fdiv(2, 3) - fdiv(2, 3, prec=100) mpf('-3.7007434154172148e-17') Unlike :func:`~mpmath.fadd`, :func:`~mpmath.fmul`, etc., exact division is not allowed since the quotient of two floating-point numbers generally does not have an exact floating-point representation. (In the future this might be changed to allow the case where the division is actually exact.) >>> fdiv(2, 3, exact=True) Traceback (most recent call last): ... ValueError: division is not an exact operation """ prec, rounding = ctx._parse_prec(kwargs) if not prec: raise ValueError("division is not an exact operation") x = ctx.convert(x) y = ctx.convert(y) if hasattr(x, '_mpf_'): if hasattr(y, '_mpf_'): return ctx.make_mpf(mpf_div(x._mpf_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_div((x._mpf_, fzero), y._mpc_, prec, rounding)) if hasattr(x, '_mpc_'): if hasattr(y, '_mpf_'): return ctx.make_mpc(mpc_div_mpf(x._mpc_, y._mpf_, prec, rounding)) if hasattr(y, '_mpc_'): return ctx.make_mpc(mpc_div(x._mpc_, y._mpc_, prec, rounding)) raise ValueError("Arguments need to be mpf or mpc compatible numbers") def nint_distance(ctx, x): r""" Return `(n,d)` where `n` is the nearest integer to `x` and `d` is an estimate of `\log_2(|x-n|)`. If `d < 0`, `-d` gives the precision (measured in bits) lost to cancellation when computing `x-n`. >>> from mpmath import * >>> n, d = nint_distance(5) >>> print(n); print(d) 5 -inf >>> n, d = nint_distance(mpf(5)) >>> print(n); print(d) 5 -inf >>> n, d = nint_distance(mpf(5.00000001)) >>> print(n); print(d) 5 -26 >>> n, d = nint_distance(mpf(4.99999999)) >>> print(n); print(d) 5 -26 >>> n, d = nint_distance(mpc(5,10)) >>> print(n); print(d) 5 4 >>> n, d = nint_distance(mpc(5,0.000001)) >>> print(n); print(d) 5 -19 """ typx = type(x) if typx in int_types: return int(x), ctx.ninf elif typx is rational.mpq: p, q = x._mpq_ n, r = divmod(p, q) if 2*r >= q: n += 1 elif not r: return n, ctx.ninf # log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q) d = bitcount(abs(p-n*q)) - bitcount(q) return n, d if hasattr(x, "_mpf_"): re = x._mpf_ im_dist = ctx.ninf elif hasattr(x, "_mpc_"): re, im = x._mpc_ isign, iman, iexp, ibc = im if iman: im_dist = iexp + ibc elif im == fzero: im_dist = ctx.ninf else: raise ValueError("requires a finite number") else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.nint_distance(x) else: raise TypeError("requires an mpf/mpc") sign, man, exp, bc = re mag = exp+bc # |x| < 0.5 if mag < 0: n = 0 re_dist = mag elif man: # exact integer if exp >= 0: n = man << exp re_dist = ctx.ninf # exact half-integer elif exp == -1: n = (man>>1)+1 re_dist = 0 else: d = (-exp-1) t = man >> d if t & 1: t += 1 man = (t<>1 # int(t)>>1 re_dist = exp+bitcount(man) if sign: n = -n elif re == fzero: re_dist = ctx.ninf n = 0 else: raise ValueError("requires a finite number") return n, max(re_dist, im_dist) def fprod(ctx, factors): r""" Calculates a product containing a finite number of factors (for infinite products, see :func:`~mpmath.nprod`). The factors will be converted to mpmath numbers. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fprod([1, 2, 0.5, 7]) mpf('7.0') """ orig = ctx.prec try: v = ctx.one for p in factors: v *= p finally: ctx.prec = orig return +v def rand(ctx): """ Returns an ``mpf`` with value chosen randomly from `[0, 1)`. The number of randomly generated bits in the mantissa is equal to the working precision. """ return ctx.make_mpf(mpf_rand(ctx._prec)) def fraction(ctx, p, q): """ Given Python integers `(p, q)`, returns a lazy ``mpf`` representing the fraction `p/q`. The value is updated with the precision. >>> from mpmath import * >>> mp.dps = 15 >>> a = fraction(1,100) >>> b = mpf(1)/100 >>> print(a); print(b) 0.01 0.01 >>> mp.dps = 30 >>> print(a); print(b) # a will be accurate 0.01 0.0100000000000000002081668171172 >>> mp.dps = 15 """ return ctx.constant(lambda prec, rnd: from_rational(p, q, prec, rnd), '%s/%s' % (p, q)) def absmin(ctx, x): return abs(ctx.convert(x)) def absmax(ctx, x): return abs(ctx.convert(x)) def _as_points(ctx, x): # XXX: remove this? if hasattr(x, '_mpi_'): a, b = x._mpi_ return [ctx.make_mpf(a), ctx.make_mpf(b)] return x ''' def _zetasum(ctx, s, a, b): """ Computes sum of k^(-s) for k = a, a+1, ..., b with a, b both small integers. """ a = int(a) b = int(b) s = ctx.convert(s) prec, rounding = ctx._prec_rounding if hasattr(s, '_mpf_'): v = ctx.make_mpf(libmp.mpf_zetasum(s._mpf_, a, b, prec)) elif hasattr(s, '_mpc_'): v = ctx.make_mpc(libmp.mpc_zetasum(s._mpc_, a, b, prec)) return v ''' def _zetasum_fast(ctx, s, a, n, derivatives=[0], reflect=False): if not (ctx.isint(a) and hasattr(s, "_mpc_")): raise NotImplementedError a = int(a) prec = ctx._prec xs, ys = libmp.mpc_zetasum(s._mpc_, a, n, derivatives, reflect, prec) xs = [ctx.make_mpc(x) for x in xs] ys = [ctx.make_mpc(y) for y in ys] return xs, ys class PrecisionManager: def __init__(self, ctx, precfun, dpsfun, normalize_output=False): self.ctx = ctx self.precfun = precfun self.dpsfun = dpsfun self.normalize_output = normalize_output def __call__(self, f): def g(*args, **kwargs): orig = self.ctx.prec try: if self.precfun: self.ctx.prec = self.precfun(self.ctx.prec) else: self.ctx.dps = self.dpsfun(self.ctx.dps) if self.normalize_output: v = f(*args, **kwargs) if type(v) is tuple: return tuple([+a for a in v]) return +v else: return f(*args, **kwargs) finally: self.ctx.prec = orig g.__name__ = f.__name__ g.__doc__ = f.__doc__ return g def __enter__(self): self.origp = self.ctx.prec if self.precfun: self.ctx.prec = self.precfun(self.ctx.prec) else: self.ctx.dps = self.dpsfun(self.ctx.dps) def __exit__(self, exc_type, exc_val, exc_tb): self.ctx.prec = self.origp return False if __name__ == '__main__': import doctest doctest.testmod() mpmath-1.1.0/mpmath/ctx_mp_python.py000066400000000000000000001123411340375245600175450ustar00rootroot00000000000000#from ctx_base import StandardBaseContext from .libmp.backend import basestring, exec_ from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps, round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps, ComplexResult, to_pickable, from_pickable, normalize, from_int, from_float, from_npfloat, from_Decimal, from_str, to_int, to_float, to_str, from_rational, from_man_exp, fone, fzero, finf, fninf, fnan, mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int, mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod, mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge, mpf_hash, mpf_rand, mpf_sum, bitcount, to_fixed, mpc_to_str, mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate, mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf, mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int, mpc_mpf_div, mpf_pow, mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10, mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin, mpf_glaisher, mpf_twinprime, mpf_mertens, int_types) from . import rational from . import function_docs new = object.__new__ class mpnumeric(object): """Base class for mpf and mpc.""" __slots__ = [] def __new__(cls, val): raise NotImplementedError class _mpf(mpnumeric): """ An mpf instance holds a real-valued floating-point number. mpf:s work analogously to Python floats, but support arbitrary-precision arithmetic. """ __slots__ = ['_mpf_'] def __new__(cls, val=fzero, **kwargs): """A new mpf can be created from a Python float, an int, a or a decimal string representing a number in floating-point format.""" prec, rounding = cls.context._prec_rounding if kwargs: prec = kwargs.get('prec', prec) if 'dps' in kwargs: prec = dps_to_prec(kwargs['dps']) rounding = kwargs.get('rounding', rounding) if type(val) is cls: sign, man, exp, bc = val._mpf_ if (not man) and exp: return val v = new(cls) v._mpf_ = normalize(sign, man, exp, bc, prec, rounding) return v elif type(val) is tuple: if len(val) == 2: v = new(cls) v._mpf_ = from_man_exp(val[0], val[1], prec, rounding) return v if len(val) == 4: sign, man, exp, bc = val v = new(cls) v._mpf_ = normalize(sign, MPZ(man), exp, bc, prec, rounding) return v raise ValueError else: v = new(cls) v._mpf_ = mpf_pos(cls.mpf_convert_arg(val, prec, rounding), prec, rounding) return v @classmethod def mpf_convert_arg(cls, x, prec, rounding): if isinstance(x, int_types): return from_int(x) if isinstance(x, float): return from_float(x) if isinstance(x, basestring): return from_str(x, prec, rounding) if isinstance(x, cls.context.constant): return x.func(prec, rounding) if hasattr(x, '_mpf_'): return x._mpf_ if hasattr(x, '_mpmath_'): t = cls.context.convert(x._mpmath_(prec, rounding)) if hasattr(t, '_mpf_'): return t._mpf_ if hasattr(x, '_mpi_'): a, b = x._mpi_ if a == b: return a raise ValueError("can only create mpf from zero-width interval") raise TypeError("cannot create mpf from " + repr(x)) @classmethod def mpf_convert_rhs(cls, x): if isinstance(x, int_types): return from_int(x) if isinstance(x, float): return from_float(x) if isinstance(x, complex_types): return cls.context.mpc(x) if isinstance(x, rational.mpq): p, q = x._mpq_ return from_rational(p, q, cls.context.prec) if hasattr(x, '_mpf_'): return x._mpf_ if hasattr(x, '_mpmath_'): t = cls.context.convert(x._mpmath_(*cls.context._prec_rounding)) if hasattr(t, '_mpf_'): return t._mpf_ return t return NotImplemented @classmethod def mpf_convert_lhs(cls, x): x = cls.mpf_convert_rhs(x) if type(x) is tuple: return cls.context.make_mpf(x) return x man_exp = property(lambda self: self._mpf_[1:3]) man = property(lambda self: self._mpf_[1]) exp = property(lambda self: self._mpf_[2]) bc = property(lambda self: self._mpf_[3]) real = property(lambda self: self) imag = property(lambda self: self.context.zero) conjugate = lambda self: self def __getstate__(self): return to_pickable(self._mpf_) def __setstate__(self, val): self._mpf_ = from_pickable(val) def __repr__(s): if s.context.pretty: return str(s) return "mpf('%s')" % to_str(s._mpf_, s.context._repr_digits) def __str__(s): return to_str(s._mpf_, s.context._str_digits) def __hash__(s): return mpf_hash(s._mpf_) def __int__(s): return int(to_int(s._mpf_)) def __long__(s): return long(to_int(s._mpf_)) def __float__(s): return to_float(s._mpf_, rnd=s.context._prec_rounding[1]) def __complex__(s): return complex(float(s)) def __nonzero__(s): return s._mpf_ != fzero __bool__ = __nonzero__ def __abs__(s): cls, new, (prec, rounding) = s._ctxdata v = new(cls) v._mpf_ = mpf_abs(s._mpf_, prec, rounding) return v def __pos__(s): cls, new, (prec, rounding) = s._ctxdata v = new(cls) v._mpf_ = mpf_pos(s._mpf_, prec, rounding) return v def __neg__(s): cls, new, (prec, rounding) = s._ctxdata v = new(cls) v._mpf_ = mpf_neg(s._mpf_, prec, rounding) return v def _cmp(s, t, func): if hasattr(t, '_mpf_'): t = t._mpf_ else: t = s.mpf_convert_rhs(t) if t is NotImplemented: return t return func(s._mpf_, t) def __cmp__(s, t): return s._cmp(t, mpf_cmp) def __lt__(s, t): return s._cmp(t, mpf_lt) def __gt__(s, t): return s._cmp(t, mpf_gt) def __le__(s, t): return s._cmp(t, mpf_le) def __ge__(s, t): return s._cmp(t, mpf_ge) def __ne__(s, t): v = s.__eq__(t) if v is NotImplemented: return v return not v def __rsub__(s, t): cls, new, (prec, rounding) = s._ctxdata if type(t) in int_types: v = new(cls) v._mpf_ = mpf_sub(from_int(t), s._mpf_, prec, rounding) return v t = s.mpf_convert_lhs(t) if t is NotImplemented: return t return t - s def __rdiv__(s, t): cls, new, (prec, rounding) = s._ctxdata if isinstance(t, int_types): v = new(cls) v._mpf_ = mpf_rdiv_int(t, s._mpf_, prec, rounding) return v t = s.mpf_convert_lhs(t) if t is NotImplemented: return t return t / s def __rpow__(s, t): t = s.mpf_convert_lhs(t) if t is NotImplemented: return t return t ** s def __rmod__(s, t): t = s.mpf_convert_lhs(t) if t is NotImplemented: return t return t % s def sqrt(s): return s.context.sqrt(s) def ae(s, t, rel_eps=None, abs_eps=None): return s.context.almosteq(s, t, rel_eps, abs_eps) def to_fixed(self, prec): return to_fixed(self._mpf_, prec) def __round__(self, *args): return round(float(self), *args) mpf_binary_op = """ def %NAME%(self, other): mpf, new, (prec, rounding) = self._ctxdata sval = self._mpf_ if hasattr(other, '_mpf_'): tval = other._mpf_ %WITH_MPF% ttype = type(other) if ttype in int_types: %WITH_INT% elif ttype is float: tval = from_float(other) %WITH_MPF% elif hasattr(other, '_mpc_'): tval = other._mpc_ mpc = type(other) %WITH_MPC% elif ttype is complex: tval = from_float(other.real), from_float(other.imag) mpc = self.context.mpc %WITH_MPC% if isinstance(other, mpnumeric): return NotImplemented try: other = mpf.context.convert(other, strings=False) except TypeError: return NotImplemented return self.%NAME%(other) """ return_mpf = "; obj = new(mpf); obj._mpf_ = val; return obj" return_mpc = "; obj = new(mpc); obj._mpc_ = val; return obj" mpf_pow_same = """ try: val = mpf_pow(sval, tval, prec, rounding) %s except ComplexResult: if mpf.context.trap_complex: raise mpc = mpf.context.mpc val = mpc_pow((sval, fzero), (tval, fzero), prec, rounding) %s """ % (return_mpf, return_mpc) def binary_op(name, with_mpf='', with_int='', with_mpc=''): code = mpf_binary_op code = code.replace("%WITH_INT%", with_int) code = code.replace("%WITH_MPC%", with_mpc) code = code.replace("%WITH_MPF%", with_mpf) code = code.replace("%NAME%", name) np = {} exec_(code, globals(), np) return np[name] _mpf.__eq__ = binary_op('__eq__', 'return mpf_eq(sval, tval)', 'return mpf_eq(sval, from_int(other))', 'return (tval[1] == fzero) and mpf_eq(tval[0], sval)') _mpf.__add__ = binary_op('__add__', 'val = mpf_add(sval, tval, prec, rounding)' + return_mpf, 'val = mpf_add(sval, from_int(other), prec, rounding)' + return_mpf, 'val = mpc_add_mpf(tval, sval, prec, rounding)' + return_mpc) _mpf.__sub__ = binary_op('__sub__', 'val = mpf_sub(sval, tval, prec, rounding)' + return_mpf, 'val = mpf_sub(sval, from_int(other), prec, rounding)' + return_mpf, 'val = mpc_sub((sval, fzero), tval, prec, rounding)' + return_mpc) _mpf.__mul__ = binary_op('__mul__', 'val = mpf_mul(sval, tval, prec, rounding)' + return_mpf, 'val = mpf_mul_int(sval, other, prec, rounding)' + return_mpf, 'val = mpc_mul_mpf(tval, sval, prec, rounding)' + return_mpc) _mpf.__div__ = binary_op('__div__', 'val = mpf_div(sval, tval, prec, rounding)' + return_mpf, 'val = mpf_div(sval, from_int(other), prec, rounding)' + return_mpf, 'val = mpc_mpf_div(sval, tval, prec, rounding)' + return_mpc) _mpf.__mod__ = binary_op('__mod__', 'val = mpf_mod(sval, tval, prec, rounding)' + return_mpf, 'val = mpf_mod(sval, from_int(other), prec, rounding)' + return_mpf, 'raise NotImplementedError("complex modulo")') _mpf.__pow__ = binary_op('__pow__', mpf_pow_same, 'val = mpf_pow_int(sval, other, prec, rounding)' + return_mpf, 'val = mpc_pow((sval, fzero), tval, prec, rounding)' + return_mpc) _mpf.__radd__ = _mpf.__add__ _mpf.__rmul__ = _mpf.__mul__ _mpf.__truediv__ = _mpf.__div__ _mpf.__rtruediv__ = _mpf.__rdiv__ class _constant(_mpf): """Represents a mathematical constant with dynamic precision. When printed or used in an arithmetic operation, a constant is converted to a regular mpf at the working precision. A regular mpf can also be obtained using the operation +x.""" def __new__(cls, func, name, docname=''): a = object.__new__(cls) a.name = name a.func = func a.__doc__ = getattr(function_docs, docname, '') return a def __call__(self, prec=None, dps=None, rounding=None): prec2, rounding2 = self.context._prec_rounding if not prec: prec = prec2 if not rounding: rounding = rounding2 if dps: prec = dps_to_prec(dps) return self.context.make_mpf(self.func(prec, rounding)) @property def _mpf_(self): prec, rounding = self.context._prec_rounding return self.func(prec, rounding) def __repr__(self): return "<%s: %s~>" % (self.name, self.context.nstr(self(dps=15))) class _mpc(mpnumeric): """ An mpc represents a complex number using a pair of mpf:s (one for the real part and another for the imaginary part.) The mpc class behaves fairly similarly to Python's complex type. """ __slots__ = ['_mpc_'] def __new__(cls, real=0, imag=0): s = object.__new__(cls) if isinstance(real, complex_types): real, imag = real.real, real.imag elif hasattr(real, '_mpc_'): s._mpc_ = real._mpc_ return s real = cls.context.mpf(real) imag = cls.context.mpf(imag) s._mpc_ = (real._mpf_, imag._mpf_) return s real = property(lambda self: self.context.make_mpf(self._mpc_[0])) imag = property(lambda self: self.context.make_mpf(self._mpc_[1])) def __getstate__(self): return to_pickable(self._mpc_[0]), to_pickable(self._mpc_[1]) def __setstate__(self, val): self._mpc_ = from_pickable(val[0]), from_pickable(val[1]) def __repr__(s): if s.context.pretty: return str(s) r = repr(s.real)[4:-1] i = repr(s.imag)[4:-1] return "%s(real=%s, imag=%s)" % (type(s).__name__, r, i) def __str__(s): return "(%s)" % mpc_to_str(s._mpc_, s.context._str_digits) def __complex__(s): return mpc_to_complex(s._mpc_, rnd=s.context._prec_rounding[1]) def __pos__(s): cls, new, (prec, rounding) = s._ctxdata v = new(cls) v._mpc_ = mpc_pos(s._mpc_, prec, rounding) return v def __abs__(s): prec, rounding = s.context._prec_rounding v = new(s.context.mpf) v._mpf_ = mpc_abs(s._mpc_, prec, rounding) return v def __neg__(s): cls, new, (prec, rounding) = s._ctxdata v = new(cls) v._mpc_ = mpc_neg(s._mpc_, prec, rounding) return v def conjugate(s): cls, new, (prec, rounding) = s._ctxdata v = new(cls) v._mpc_ = mpc_conjugate(s._mpc_, prec, rounding) return v def __nonzero__(s): return mpc_is_nonzero(s._mpc_) __bool__ = __nonzero__ def __hash__(s): return mpc_hash(s._mpc_) @classmethod def mpc_convert_lhs(cls, x): try: y = cls.context.convert(x) return y except TypeError: return NotImplemented def __eq__(s, t): if not hasattr(t, '_mpc_'): if isinstance(t, str): return False t = s.mpc_convert_lhs(t) if t is NotImplemented: return t return s.real == t.real and s.imag == t.imag def __ne__(s, t): b = s.__eq__(t) if b is NotImplemented: return b return not b def _compare(*args): raise TypeError("no ordering relation is defined for complex numbers") __gt__ = _compare __le__ = _compare __gt__ = _compare __ge__ = _compare def __add__(s, t): cls, new, (prec, rounding) = s._ctxdata if not hasattr(t, '_mpc_'): t = s.mpc_convert_lhs(t) if t is NotImplemented: return t if hasattr(t, '_mpf_'): v = new(cls) v._mpc_ = mpc_add_mpf(s._mpc_, t._mpf_, prec, rounding) return v v = new(cls) v._mpc_ = mpc_add(s._mpc_, t._mpc_, prec, rounding) return v def __sub__(s, t): cls, new, (prec, rounding) = s._ctxdata if not hasattr(t, '_mpc_'): t = s.mpc_convert_lhs(t) if t is NotImplemented: return t if hasattr(t, '_mpf_'): v = new(cls) v._mpc_ = mpc_sub_mpf(s._mpc_, t._mpf_, prec, rounding) return v v = new(cls) v._mpc_ = mpc_sub(s._mpc_, t._mpc_, prec, rounding) return v def __mul__(s, t): cls, new, (prec, rounding) = s._ctxdata if not hasattr(t, '_mpc_'): if isinstance(t, int_types): v = new(cls) v._mpc_ = mpc_mul_int(s._mpc_, t, prec, rounding) return v t = s.mpc_convert_lhs(t) if t is NotImplemented: return t if hasattr(t, '_mpf_'): v = new(cls) v._mpc_ = mpc_mul_mpf(s._mpc_, t._mpf_, prec, rounding) return v t = s.mpc_convert_lhs(t) v = new(cls) v._mpc_ = mpc_mul(s._mpc_, t._mpc_, prec, rounding) return v def __div__(s, t): cls, new, (prec, rounding) = s._ctxdata if not hasattr(t, '_mpc_'): t = s.mpc_convert_lhs(t) if t is NotImplemented: return t if hasattr(t, '_mpf_'): v = new(cls) v._mpc_ = mpc_div_mpf(s._mpc_, t._mpf_, prec, rounding) return v v = new(cls) v._mpc_ = mpc_div(s._mpc_, t._mpc_, prec, rounding) return v def __pow__(s, t): cls, new, (prec, rounding) = s._ctxdata if isinstance(t, int_types): v = new(cls) v._mpc_ = mpc_pow_int(s._mpc_, t, prec, rounding) return v t = s.mpc_convert_lhs(t) if t is NotImplemented: return t v = new(cls) if hasattr(t, '_mpf_'): v._mpc_ = mpc_pow_mpf(s._mpc_, t._mpf_, prec, rounding) else: v._mpc_ = mpc_pow(s._mpc_, t._mpc_, prec, rounding) return v __radd__ = __add__ def __rsub__(s, t): t = s.mpc_convert_lhs(t) if t is NotImplemented: return t return t - s def __rmul__(s, t): cls, new, (prec, rounding) = s._ctxdata if isinstance(t, int_types): v = new(cls) v._mpc_ = mpc_mul_int(s._mpc_, t, prec, rounding) return v t = s.mpc_convert_lhs(t) if t is NotImplemented: return t return t * s def __rdiv__(s, t): t = s.mpc_convert_lhs(t) if t is NotImplemented: return t return t / s def __rpow__(s, t): t = s.mpc_convert_lhs(t) if t is NotImplemented: return t return t ** s __truediv__ = __div__ __rtruediv__ = __rdiv__ def ae(s, t, rel_eps=None, abs_eps=None): return s.context.almosteq(s, t, rel_eps, abs_eps) complex_types = (complex, _mpc) class PythonMPContext(object): def __init__(ctx): ctx._prec_rounding = [53, round_nearest] ctx.mpf = type('mpf', (_mpf,), {}) ctx.mpc = type('mpc', (_mpc,), {}) ctx.mpf._ctxdata = [ctx.mpf, new, ctx._prec_rounding] ctx.mpc._ctxdata = [ctx.mpc, new, ctx._prec_rounding] ctx.mpf.context = ctx ctx.mpc.context = ctx ctx.constant = type('constant', (_constant,), {}) ctx.constant._ctxdata = [ctx.mpf, new, ctx._prec_rounding] ctx.constant.context = ctx def make_mpf(ctx, v): a = new(ctx.mpf) a._mpf_ = v return a def make_mpc(ctx, v): a = new(ctx.mpc) a._mpc_ = v return a def default(ctx): ctx._prec = ctx._prec_rounding[0] = 53 ctx._dps = 15 ctx.trap_complex = False def _set_prec(ctx, n): ctx._prec = ctx._prec_rounding[0] = max(1, int(n)) ctx._dps = prec_to_dps(n) def _set_dps(ctx, n): ctx._prec = ctx._prec_rounding[0] = dps_to_prec(n) ctx._dps = max(1, int(n)) prec = property(lambda ctx: ctx._prec, _set_prec) dps = property(lambda ctx: ctx._dps, _set_dps) def convert(ctx, x, strings=True): """ Converts *x* to an ``mpf`` or ``mpc``. If *x* is of type ``mpf``, ``mpc``, ``int``, ``float``, ``complex``, the conversion will be performed losslessly. If *x* is a string, the result will be rounded to the present working precision. Strings representing fractions or complex numbers are permitted. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> mpmathify(3.5) mpf('3.5') >>> mpmathify('2.1') mpf('2.1000000000000001') >>> mpmathify('3/4') mpf('0.75') >>> mpmathify('2+3j') mpc(real='2.0', imag='3.0') """ if type(x) in ctx.types: return x if isinstance(x, int_types): return ctx.make_mpf(from_int(x)) if isinstance(x, float): return ctx.make_mpf(from_float(x)) if isinstance(x, complex): return ctx.make_mpc((from_float(x.real), from_float(x.imag))) if type(x).__module__ == 'numpy': return ctx.npconvert(x) if isinstance(x, numbers.Rational): # e.g. Fraction try: x = rational.mpq(int(x.numerator), int(x.denominator)) except: pass prec, rounding = ctx._prec_rounding if isinstance(x, rational.mpq): p, q = x._mpq_ return ctx.make_mpf(from_rational(p, q, prec)) if strings and isinstance(x, basestring): try: _mpf_ = from_str(x, prec, rounding) return ctx.make_mpf(_mpf_) except ValueError: pass if hasattr(x, '_mpf_'): return ctx.make_mpf(x._mpf_) if hasattr(x, '_mpc_'): return ctx.make_mpc(x._mpc_) if hasattr(x, '_mpmath_'): return ctx.convert(x._mpmath_(prec, rounding)) if type(x).__module__ == 'decimal': try: return ctx.make_mpf(from_Decimal(x, prec, rounding)) except: pass return ctx._convert_fallback(x, strings) def npconvert(ctx, x): """ Converts *x* to an ``mpf`` or ``mpc``. *x* should be a numpy scalar. """ import numpy as np if isinstance(x, np.integer): return ctx.make_mpf(from_int(int(x))) if isinstance(x, np.floating): return ctx.make_mpf(from_npfloat(x)) if isinstance(x, np.complexfloating): return ctx.make_mpc((from_npfloat(x.real), from_npfloat(x.imag))) raise TypeError("cannot create mpf from " + repr(x)) def isnan(ctx, x): """ Return *True* if *x* is a NaN (not-a-number), or for a complex number, whether either the real or complex part is NaN; otherwise return *False*:: >>> from mpmath import * >>> isnan(3.14) False >>> isnan(nan) True >>> isnan(mpc(3.14,2.72)) False >>> isnan(mpc(3.14,nan)) True """ if hasattr(x, "_mpf_"): return x._mpf_ == fnan if hasattr(x, "_mpc_"): return fnan in x._mpc_ if isinstance(x, int_types) or isinstance(x, rational.mpq): return False x = ctx.convert(x) if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): return ctx.isnan(x) raise TypeError("isnan() needs a number as input") def isinf(ctx, x): """ Return *True* if the absolute value of *x* is infinite; otherwise return *False*:: >>> from mpmath import * >>> isinf(inf) True >>> isinf(-inf) True >>> isinf(3) False >>> isinf(3+4j) False >>> isinf(mpc(3,inf)) True >>> isinf(mpc(inf,3)) True """ if hasattr(x, "_mpf_"): return x._mpf_ in (finf, fninf) if hasattr(x, "_mpc_"): re, im = x._mpc_ return re in (finf, fninf) or im in (finf, fninf) if isinstance(x, int_types) or isinstance(x, rational.mpq): return False x = ctx.convert(x) if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): return ctx.isinf(x) raise TypeError("isinf() needs a number as input") def isnormal(ctx, x): """ Determine whether *x* is "normal" in the sense of floating-point representation; that is, return *False* if *x* is zero, an infinity or NaN; otherwise return *True*. By extension, a complex number *x* is considered "normal" if its magnitude is normal:: >>> from mpmath import * >>> isnormal(3) True >>> isnormal(0) False >>> isnormal(inf); isnormal(-inf); isnormal(nan) False False False >>> isnormal(0+0j) False >>> isnormal(0+3j) True >>> isnormal(mpc(2,nan)) False """ if hasattr(x, "_mpf_"): return bool(x._mpf_[1]) if hasattr(x, "_mpc_"): re, im = x._mpc_ re_normal = bool(re[1]) im_normal = bool(im[1]) if re == fzero: return im_normal if im == fzero: return re_normal return re_normal and im_normal if isinstance(x, int_types) or isinstance(x, rational.mpq): return bool(x) x = ctx.convert(x) if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): return ctx.isnormal(x) raise TypeError("isnormal() needs a number as input") def isint(ctx, x, gaussian=False): """ Return *True* if *x* is integer-valued; otherwise return *False*:: >>> from mpmath import * >>> isint(3) True >>> isint(mpf(3)) True >>> isint(3.2) False >>> isint(inf) False Optionally, Gaussian integers can be checked for:: >>> isint(3+0j) True >>> isint(3+2j) False >>> isint(3+2j, gaussian=True) True """ if isinstance(x, int_types): return True if hasattr(x, "_mpf_"): sign, man, exp, bc = xval = x._mpf_ return bool((man and exp >= 0) or xval == fzero) if hasattr(x, "_mpc_"): re, im = x._mpc_ rsign, rman, rexp, rbc = re isign, iman, iexp, ibc = im re_isint = (rman and rexp >= 0) or re == fzero if gaussian: im_isint = (iman and iexp >= 0) or im == fzero return re_isint and im_isint return re_isint and im == fzero if isinstance(x, rational.mpq): p, q = x._mpq_ return p % q == 0 x = ctx.convert(x) if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): return ctx.isint(x, gaussian) raise TypeError("isint() needs a number as input") def fsum(ctx, terms, absolute=False, squared=False): """ Calculates a sum containing a finite number of terms (for infinite series, see :func:`~mpmath.nsum`). The terms will be converted to mpmath numbers. For len(terms) > 2, this function is generally faster and produces more accurate results than the builtin Python function :func:`sum`. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fsum([1, 2, 0.5, 7]) mpf('10.5') With squared=True each term is squared, and with absolute=True the absolute value of each term is used. """ prec, rnd = ctx._prec_rounding real = [] imag = [] other = 0 for term in terms: reval = imval = 0 if hasattr(term, "_mpf_"): reval = term._mpf_ elif hasattr(term, "_mpc_"): reval, imval = term._mpc_ else: term = ctx.convert(term) if hasattr(term, "_mpf_"): reval = term._mpf_ elif hasattr(term, "_mpc_"): reval, imval = term._mpc_ else: if absolute: term = ctx.absmax(term) if squared: term = term**2 other += term continue if imval: if squared: if absolute: real.append(mpf_mul(reval,reval)) real.append(mpf_mul(imval,imval)) else: reval, imval = mpc_pow_int((reval,imval),2,prec+10) real.append(reval) imag.append(imval) elif absolute: real.append(mpc_abs((reval,imval), prec)) else: real.append(reval) imag.append(imval) else: if squared: reval = mpf_mul(reval, reval) elif absolute: reval = mpf_abs(reval) real.append(reval) s = mpf_sum(real, prec, rnd, absolute) if imag: s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd))) else: s = ctx.make_mpf(s) if other is 0: return s else: return s + other def fdot(ctx, A, B=None, conjugate=False): r""" Computes the dot product of the iterables `A` and `B`, .. math :: \sum_{k=0} A_k B_k. Alternatively, :func:`~mpmath.fdot` accepts a single iterable of pairs. In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent. The elements are automatically converted to mpmath numbers. With ``conjugate=True``, the elements in the second vector will be conjugated: .. math :: \sum_{k=0} A_k \overline{B_k} **Examples** >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> A = [2, 1.5, 3] >>> B = [1, -1, 2] >>> fdot(A, B) mpf('6.5') >>> list(zip(A, B)) [(2, 1), (1.5, -1), (3, 2)] >>> fdot(_) mpf('6.5') >>> A = [2, 1.5, 3j] >>> B = [1+j, 3, -1-j] >>> fdot(A, B) mpc(real='9.5', imag='-1.0') >>> fdot(A, B, conjugate=True) mpc(real='3.5', imag='-5.0') """ if B is not None: A = zip(A, B) prec, rnd = ctx._prec_rounding real = [] imag = [] other = 0 hasattr_ = hasattr types = (ctx.mpf, ctx.mpc) for a, b in A: if type(a) not in types: a = ctx.convert(a) if type(b) not in types: b = ctx.convert(b) a_real = hasattr_(a, "_mpf_") b_real = hasattr_(b, "_mpf_") if a_real and b_real: real.append(mpf_mul(a._mpf_, b._mpf_)) continue a_complex = hasattr_(a, "_mpc_") b_complex = hasattr_(b, "_mpc_") if a_real and b_complex: aval = a._mpf_ bre, bim = b._mpc_ if conjugate: bim = mpf_neg(bim) real.append(mpf_mul(aval, bre)) imag.append(mpf_mul(aval, bim)) elif b_real and a_complex: are, aim = a._mpc_ bval = b._mpf_ real.append(mpf_mul(are, bval)) imag.append(mpf_mul(aim, bval)) elif a_complex and b_complex: #re, im = mpc_mul(a._mpc_, b._mpc_, prec+20) are, aim = a._mpc_ bre, bim = b._mpc_ if conjugate: bim = mpf_neg(bim) real.append(mpf_mul(are, bre)) real.append(mpf_neg(mpf_mul(aim, bim))) imag.append(mpf_mul(are, bim)) imag.append(mpf_mul(aim, bre)) else: if conjugate: other += a*ctx.conj(b) else: other += a*b s = mpf_sum(real, prec, rnd) if imag: s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd))) else: s = ctx.make_mpf(s) if other is 0: return s else: return s + other def _wrap_libmp_function(ctx, mpf_f, mpc_f=None, mpi_f=None, doc=""): """ Given a low-level mpf_ function, and optionally similar functions for mpc_ and mpi_, defines the function as a context method. It is assumed that the return type is the same as that of the input; the exception is that propagation from mpf to mpc is possible by raising ComplexResult. """ def f(x, **kwargs): if type(x) not in ctx.types: x = ctx.convert(x) prec, rounding = ctx._prec_rounding if kwargs: prec = kwargs.get('prec', prec) if 'dps' in kwargs: prec = dps_to_prec(kwargs['dps']) rounding = kwargs.get('rounding', rounding) if hasattr(x, '_mpf_'): try: return ctx.make_mpf(mpf_f(x._mpf_, prec, rounding)) except ComplexResult: # Handle propagation to complex if ctx.trap_complex: raise return ctx.make_mpc(mpc_f((x._mpf_, fzero), prec, rounding)) elif hasattr(x, '_mpc_'): return ctx.make_mpc(mpc_f(x._mpc_, prec, rounding)) raise NotImplementedError("%s of a %s" % (name, type(x))) name = mpf_f.__name__[4:] f.__doc__ = function_docs.__dict__.get(name, "Computes the %s of x" % doc) return f # Called by SpecialFunctions.__init__() @classmethod def _wrap_specfun(cls, name, f, wrap): if wrap: def f_wrapped(ctx, *args, **kwargs): convert = ctx.convert args = [convert(a) for a in args] prec = ctx.prec try: ctx.prec += 10 retval = f(ctx, *args, **kwargs) finally: ctx.prec = prec return +retval else: f_wrapped = f f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__) setattr(cls, name, f_wrapped) def _convert_param(ctx, x): if hasattr(x, "_mpc_"): v, im = x._mpc_ if im != fzero: return x, 'C' elif hasattr(x, "_mpf_"): v = x._mpf_ else: if type(x) in int_types: return int(x), 'Z' p = None if isinstance(x, tuple): p, q = x elif hasattr(x, '_mpq_'): p, q = x._mpq_ elif isinstance(x, basestring) and '/' in x: p, q = x.split('/') p = int(p) q = int(q) if p is not None: if not p % q: return p // q, 'Z' return ctx.mpq(p,q), 'Q' x = ctx.convert(x) if hasattr(x, "_mpc_"): v, im = x._mpc_ if im != fzero: return x, 'C' elif hasattr(x, "_mpf_"): v = x._mpf_ else: return x, 'U' sign, man, exp, bc = v if man: if exp >= -4: if sign: man = -man if exp >= 0: return int(man) << exp, 'Z' if exp >= -4: p, q = int(man), (1<<(-exp)) return ctx.mpq(p,q), 'Q' x = ctx.make_mpf(v) return x, 'R' elif not exp: return 0, 'Z' else: return x, 'U' def _mpf_mag(ctx, x): sign, man, exp, bc = x if man: return exp+bc if x == fzero: return ctx.ninf if x == finf or x == fninf: return ctx.inf return ctx.nan def mag(ctx, x): """ Quick logarithmic magnitude estimate of a number. Returns an integer or infinity `m` such that `|x| <= 2^m`. It is not guaranteed that `m` is an optimal bound, but it will never be too large by more than 2 (and probably not more than 1). **Examples** >>> from mpmath import * >>> mp.pretty = True >>> mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2))) (4, 4, 4, 4) >>> mag(10j), mag(10+10j) (4, 5) >>> mag(0.01), int(ceil(log(0.01,2))) (-6, -6) >>> mag(0), mag(inf), mag(-inf), mag(nan) (-inf, +inf, +inf, nan) """ if hasattr(x, "_mpf_"): return ctx._mpf_mag(x._mpf_) elif hasattr(x, "_mpc_"): r, i = x._mpc_ if r == fzero: return ctx._mpf_mag(i) if i == fzero: return ctx._mpf_mag(r) return 1+max(ctx._mpf_mag(r), ctx._mpf_mag(i)) elif isinstance(x, int_types): if x: return bitcount(abs(x)) return ctx.ninf elif isinstance(x, rational.mpq): p, q = x._mpq_ if p: return 1 + bitcount(abs(p)) - bitcount(q) return ctx.ninf else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.mag(x) else: raise TypeError("requires an mpf/mpc") # Register with "numbers" ABC # We do not subclass, hence we do not use the @abstractmethod checks. While # this is less invasive it may turn out that we do not actually support # parts of the expected interfaces. See # http://docs.python.org/2/library/numbers.html for list of abstract # methods. try: import numbers numbers.Complex.register(_mpc) numbers.Real.register(_mpf) except ImportError: pass mpmath-1.1.0/mpmath/function_docs.py000066400000000000000000010436221340375245600175150ustar00rootroot00000000000000""" Extended docstrings for functions.py """ pi = r""" `\pi`, roughly equal to 3.141592654, represents the area of the unit circle, the half-period of trigonometric functions, and many other things in mathematics. Mpmath can evaluate `\pi` to arbitrary precision:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +pi 3.1415926535897932384626433832795028841971693993751 This shows digits 99991-100000 of `\pi` (the last digit is actually a 4 when the decimal expansion is truncated, but here the nearest rounding is used):: >>> mp.dps = 100000 >>> str(pi)[-10:] '5549362465' **Possible issues** :data:`pi` always rounds to the nearest floating-point number when used. This means that exact mathematical identities involving `\pi` will generally not be preserved in floating-point arithmetic. In particular, multiples of :data:`pi` (except for the trivial case ``0*pi``) are *not* the exact roots of :func:`~mpmath.sin`, but differ roughly by the current epsilon:: >>> mp.dps = 15 >>> sin(pi) 1.22464679914735e-16 One solution is to use the :func:`~mpmath.sinpi` function instead:: >>> sinpi(1) 0.0 See the documentation of trigonometric functions for additional details. """ degree = r""" Represents one degree of angle, `1^{\circ} = \pi/180`, or about 0.01745329. This constant may be evaluated to arbitrary precision:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +degree 0.017453292519943295769236907684886127134428718885417 The :data:`degree` object is convenient for conversion to radians:: >>> sin(30 * degree) 0.5 >>> asin(0.5) / degree 30.0 """ e = r""" The transcendental number `e` = 2.718281828... is the base of the natural logarithm (:func:`~mpmath.ln`) and of the exponential function (:func:`~mpmath.exp`). Mpmath can be evaluate `e` to arbitrary precision:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +e 2.7182818284590452353602874713526624977572470937 This shows digits 99991-100000 of `e` (the last digit is actually a 5 when the decimal expansion is truncated, but here the nearest rounding is used):: >>> mp.dps = 100000 >>> str(e)[-10:] '2100427166' **Possible issues** :data:`e` always rounds to the nearest floating-point number when used, and mathematical identities involving `e` may not hold in floating-point arithmetic. For example, ``ln(e)`` might not evaluate exactly to 1. In particular, don't use ``e**x`` to compute the exponential function. Use ``exp(x)`` instead; this is both faster and more accurate. """ phi = r""" Represents the golden ratio `\phi = (1+\sqrt 5)/2`, approximately equal to 1.6180339887. To high precision, its value is:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +phi 1.6180339887498948482045868343656381177203091798058 Formulas for the golden ratio include the following:: >>> (1+sqrt(5))/2 1.6180339887498948482045868343656381177203091798058 >>> findroot(lambda x: x**2-x-1, 1) 1.6180339887498948482045868343656381177203091798058 >>> limit(lambda n: fib(n+1)/fib(n), inf) 1.6180339887498948482045868343656381177203091798058 """ euler = r""" Euler's constant or the Euler-Mascheroni constant `\gamma` = 0.57721566... is a number of central importance to number theory and special functions. It is defined as the limit .. math :: \gamma = \lim_{n\to\infty} H_n - \log n where `H_n = 1 + \frac{1}{2} + \ldots + \frac{1}{n}` is a harmonic number (see :func:`~mpmath.harmonic`). Evaluation of `\gamma` is supported at arbitrary precision:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +euler 0.57721566490153286060651209008240243104215933593992 We can also compute `\gamma` directly from the definition, although this is less efficient:: >>> limit(lambda n: harmonic(n)-log(n), inf) 0.57721566490153286060651209008240243104215933593992 This shows digits 9991-10000 of `\gamma` (the last digit is actually a 5 when the decimal expansion is truncated, but here the nearest rounding is used):: >>> mp.dps = 10000 >>> str(euler)[-10:] '4679858166' Integrals, series, and representations for `\gamma` in terms of special functions include the following (there are many others):: >>> mp.dps = 25 >>> -quad(lambda x: exp(-x)*log(x), [0,inf]) 0.5772156649015328606065121 >>> quad(lambda x,y: (x-1)/(1-x*y)/log(x*y), [0,1], [0,1]) 0.5772156649015328606065121 >>> nsum(lambda k: 1/k-log(1+1/k), [1,inf]) 0.5772156649015328606065121 >>> nsum(lambda k: (-1)**k*zeta(k)/k, [2,inf]) 0.5772156649015328606065121 >>> -diff(gamma, 1) 0.5772156649015328606065121 >>> limit(lambda x: 1/x-gamma(x), 0) 0.5772156649015328606065121 >>> limit(lambda x: zeta(x)-1/(x-1), 1) 0.5772156649015328606065121 >>> (log(2*pi*nprod(lambda n: ... exp(-2+2/n)*(1+2/n)**n, [1,inf]))-3)/2 0.5772156649015328606065121 For generalizations of the identities `\gamma = -\Gamma'(1)` and `\gamma = \lim_{x\to1} \zeta(x)-1/(x-1)`, see :func:`~mpmath.psi` and :func:`~mpmath.stieltjes` respectively. """ catalan = r""" Catalan's constant `K` = 0.91596559... is given by the infinite series .. math :: K = \sum_{k=0}^{\infty} \frac{(-1)^k}{(2k+1)^2}. Mpmath can evaluate it to arbitrary precision:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +catalan 0.91596559417721901505460351493238411077414937428167 One can also compute `K` directly from the definition, although this is significantly less efficient:: >>> nsum(lambda k: (-1)**k/(2*k+1)**2, [0, inf]) 0.91596559417721901505460351493238411077414937428167 This shows digits 9991-10000 of `K` (the last digit is actually a 3 when the decimal expansion is truncated, but here the nearest rounding is used):: >>> mp.dps = 10000 >>> str(catalan)[-10:] '9537871504' Catalan's constant has numerous integral representations:: >>> mp.dps = 50 >>> quad(lambda x: -log(x)/(1+x**2), [0, 1]) 0.91596559417721901505460351493238411077414937428167 >>> quad(lambda x: atan(x)/x, [0, 1]) 0.91596559417721901505460351493238411077414937428167 >>> quad(lambda x: ellipk(x**2)/2, [0, 1]) 0.91596559417721901505460351493238411077414937428167 >>> quad(lambda x,y: 1/(1+(x*y)**2), [0, 1], [0, 1]) 0.91596559417721901505460351493238411077414937428167 As well as series representations:: >>> pi*log(sqrt(3)+2)/8 + 3*nsum(lambda n: ... (fac(n)/(2*n+1))**2/fac(2*n), [0, inf])/8 0.91596559417721901505460351493238411077414937428167 >>> 1-nsum(lambda n: n*zeta(2*n+1)/16**n, [1,inf]) 0.91596559417721901505460351493238411077414937428167 """ khinchin = r""" Khinchin's constant `K` = 2.68542... is a number that appears in the theory of continued fractions. Mpmath can evaluate it to arbitrary precision:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +khinchin 2.6854520010653064453097148354817956938203822939945 An integral representation is:: >>> I = quad(lambda x: log((1-x**2)/sincpi(x))/x/(1+x), [0, 1]) >>> 2*exp(1/log(2)*I) 2.6854520010653064453097148354817956938203822939945 The computation of ``khinchin`` is based on an efficient implementation of the following series:: >>> f = lambda n: (zeta(2*n)-1)/n*sum((-1)**(k+1)/mpf(k) ... for k in range(1,2*int(n))) >>> exp(nsum(f, [1,inf])/log(2)) 2.6854520010653064453097148354817956938203822939945 """ glaisher = r""" Glaisher's constant `A`, also known as the Glaisher-Kinkelin constant, is a number approximately equal to 1.282427129 that sometimes appears in formulas related to gamma and zeta functions. It is also related to the Barnes G-function (see :func:`~mpmath.barnesg`). The constant is defined as `A = \exp(1/12-\zeta'(-1))` where `\zeta'(s)` denotes the derivative of the Riemann zeta function (see :func:`~mpmath.zeta`). Mpmath can evaluate Glaisher's constant to arbitrary precision: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +glaisher 1.282427129100622636875342568869791727767688927325 We can verify that the value computed by :data:`glaisher` is correct using mpmath's facilities for numerical differentiation and arbitrary evaluation of the zeta function: >>> exp(mpf(1)/12 - diff(zeta, -1)) 1.282427129100622636875342568869791727767688927325 Here is an example of an integral that can be evaluated in terms of Glaisher's constant: >>> mp.dps = 15 >>> quad(lambda x: log(gamma(x)), [1, 1.5]) -0.0428537406502909 >>> -0.5 - 7*log(2)/24 + log(pi)/4 + 3*log(glaisher)/2 -0.042853740650291 Mpmath computes Glaisher's constant by applying Euler-Maclaurin summation to a slowly convergent series. The implementation is reasonably efficient up to about 10,000 digits. See the source code for additional details. References: http://mathworld.wolfram.com/Glaisher-KinkelinConstant.html """ apery = r""" Represents Apery's constant, which is the irrational number approximately equal to 1.2020569 given by .. math :: \zeta(3) = \sum_{k=1}^\infty\frac{1}{k^3}. The calculation is based on an efficient hypergeometric series. To 50 decimal places, the value is given by:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +apery 1.2020569031595942853997381615114499907649862923405 Other ways to evaluate Apery's constant using mpmath include:: >>> zeta(3) 1.2020569031595942853997381615114499907649862923405 >>> -psi(2,1)/2 1.2020569031595942853997381615114499907649862923405 >>> 8*nsum(lambda k: 1/(2*k+1)**3, [0,inf])/7 1.2020569031595942853997381615114499907649862923405 >>> f = lambda k: 2/k**3/(exp(2*pi*k)-1) >>> 7*pi**3/180 - nsum(f, [1,inf]) 1.2020569031595942853997381615114499907649862923405 This shows digits 9991-10000 of Apery's constant:: >>> mp.dps = 10000 >>> str(apery)[-10:] '3189504235' """ mertens = r""" Represents the Mertens or Meissel-Mertens constant, which is the prime number analog of Euler's constant: .. math :: B_1 = \lim_{N\to\infty} \left(\sum_{p_k \le N} \frac{1}{p_k} - \log \log N \right) Here `p_k` denotes the `k`-th prime number. Other names for this constant include the Hadamard-de la Vallee-Poussin constant or the prime reciprocal constant. The following gives the Mertens constant to 50 digits:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +mertens 0.2614972128476427837554268386086958590515666482612 References: http://mathworld.wolfram.com/MertensConstant.html """ twinprime = r""" Represents the twin prime constant, which is the factor `C_2` featuring in the Hardy-Littlewood conjecture for the growth of the twin prime counting function, .. math :: \pi_2(n) \sim 2 C_2 \frac{n}{\log^2 n}. It is given by the product over primes .. math :: C_2 = \prod_{p\ge3} \frac{p(p-2)}{(p-1)^2} \approx 0.66016 Computing `C_2` to 50 digits:: >>> from mpmath import * >>> mp.dps = 50; mp.pretty = True >>> +twinprime 0.66016181584686957392781211001455577843262336028473 References: http://mathworld.wolfram.com/TwinPrimesConstant.html """ ln = r""" Computes the natural logarithm of `x`, `\ln x`. See :func:`~mpmath.log` for additional documentation.""" sqrt = r""" ``sqrt(x)`` gives the principal square root of `x`, `\sqrt x`. For positive real numbers, the principal root is simply the positive square root. For arbitrary complex numbers, the principal square root is defined to satisfy `\sqrt x = \exp(\log(x)/2)`. The function thus has a branch cut along the negative half real axis. For all mpmath numbers ``x``, calling ``sqrt(x)`` is equivalent to performing ``x**0.5``. **Examples** Basic examples and limits:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> sqrt(10) 3.16227766016838 >>> sqrt(100) 10.0 >>> sqrt(-4) (0.0 + 2.0j) >>> sqrt(1+1j) (1.09868411346781 + 0.455089860562227j) >>> sqrt(inf) +inf Square root evaluation is fast at huge precision:: >>> mp.dps = 50000 >>> a = sqrt(3) >>> str(a)[-10:] '9329332815' :func:`mpmath.iv.sqrt` supports interval arguments:: >>> iv.dps = 15; iv.pretty = True >>> iv.sqrt([16,100]) [4.0, 10.0] >>> iv.sqrt(2) [1.4142135623730949234, 1.4142135623730951455] >>> iv.sqrt(2) ** 2 [1.9999999999999995559, 2.0000000000000004441] """ cbrt = r""" ``cbrt(x)`` computes the cube root of `x`, `x^{1/3}`. This function is faster and more accurate than raising to a floating-point fraction:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> 125**(mpf(1)/3) mpf('4.9999999999999991') >>> cbrt(125) mpf('5.0') Every nonzero complex number has three cube roots. This function returns the cube root defined by `\exp(\log(x)/3)` where the principal branch of the natural logarithm is used. Note that this does not give a real cube root for negative real numbers:: >>> mp.pretty = True >>> cbrt(-1) (0.5 + 0.866025403784439j) """ exp = r""" Computes the exponential function, .. math :: \exp(x) = e^x = \sum_{k=0}^{\infty} \frac{x^k}{k!}. For complex numbers, the exponential function also satisfies .. math :: \exp(x+yi) = e^x (\cos y + i \sin y). **Basic examples** Some values of the exponential function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> exp(0) 1.0 >>> exp(1) 2.718281828459045235360287 >>> exp(-1) 0.3678794411714423215955238 >>> exp(inf) +inf >>> exp(-inf) 0.0 Arguments can be arbitrarily large:: >>> exp(10000) 8.806818225662921587261496e+4342 >>> exp(-10000) 1.135483865314736098540939e-4343 Evaluation is supported for interval arguments via :func:`mpmath.iv.exp`:: >>> iv.dps = 25; iv.pretty = True >>> iv.exp([-inf,0]) [0.0, 1.0] >>> iv.exp([0,1]) [1.0, 2.71828182845904523536028749558] The exponential function can be evaluated efficiently to arbitrary precision:: >>> mp.dps = 10000 >>> exp(pi) #doctest: +ELLIPSIS 23.140692632779269005729...8984304016040616 **Functional properties** Numerical verification of Euler's identity for the complex exponential function:: >>> mp.dps = 15 >>> exp(j*pi)+1 (0.0 + 1.22464679914735e-16j) >>> chop(exp(j*pi)+1) 0.0 This recovers the coefficients (reciprocal factorials) in the Maclaurin series expansion of exp:: >>> nprint(taylor(exp, 0, 5)) [1.0, 1.0, 0.5, 0.166667, 0.0416667, 0.00833333] The exponential function is its own derivative and antiderivative:: >>> exp(pi) 23.1406926327793 >>> diff(exp, pi) 23.1406926327793 >>> quad(exp, [-inf, pi]) 23.1406926327793 The exponential function can be evaluated using various methods, including direct summation of the series, limits, and solving the defining differential equation:: >>> nsum(lambda k: pi**k/fac(k), [0,inf]) 23.1406926327793 >>> limit(lambda k: (1+pi/k)**k, inf) 23.1406926327793 >>> odefun(lambda t, x: x, 0, 1)(pi) 23.1406926327793 """ cosh = r""" Computes the hyperbolic cosine of `x`, `\cosh(x) = (e^x + e^{-x})/2`. Values and limits include:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> cosh(0) 1.0 >>> cosh(1) 1.543080634815243778477906 >>> cosh(-inf), cosh(+inf) (+inf, +inf) The hyperbolic cosine is an even, convex function with a global minimum at `x = 0`, having a Maclaurin series that starts:: >>> nprint(chop(taylor(cosh, 0, 5))) [1.0, 0.0, 0.5, 0.0, 0.0416667, 0.0] Generalized to complex numbers, the hyperbolic cosine is equivalent to a cosine with the argument rotated in the imaginary direction, or `\cosh x = \cos ix`:: >>> cosh(2+3j) (-3.724545504915322565473971 + 0.5118225699873846088344638j) >>> cos(3-2j) (-3.724545504915322565473971 + 0.5118225699873846088344638j) """ sinh = r""" Computes the hyperbolic sine of `x`, `\sinh(x) = (e^x - e^{-x})/2`. Values and limits include:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> sinh(0) 0.0 >>> sinh(1) 1.175201193643801456882382 >>> sinh(-inf), sinh(+inf) (-inf, +inf) The hyperbolic sine is an odd function, with a Maclaurin series that starts:: >>> nprint(chop(taylor(sinh, 0, 5))) [0.0, 1.0, 0.0, 0.166667, 0.0, 0.00833333] Generalized to complex numbers, the hyperbolic sine is essentially a sine with a rotation `i` applied to the argument; more precisely, `\sinh x = -i \sin ix`:: >>> sinh(2+3j) (-3.590564589985779952012565 + 0.5309210862485198052670401j) >>> j*sin(3-2j) (-3.590564589985779952012565 + 0.5309210862485198052670401j) """ tanh = r""" Computes the hyperbolic tangent of `x`, `\tanh(x) = \sinh(x)/\cosh(x)`. Values and limits include:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> tanh(0) 0.0 >>> tanh(1) 0.7615941559557648881194583 >>> tanh(-inf), tanh(inf) (-1.0, 1.0) The hyperbolic tangent is an odd, sigmoidal function, similar to the inverse tangent and error function. Its Maclaurin series is:: >>> nprint(chop(taylor(tanh, 0, 5))) [0.0, 1.0, 0.0, -0.333333, 0.0, 0.133333] Generalized to complex numbers, the hyperbolic tangent is essentially a tangent with a rotation `i` applied to the argument; more precisely, `\tanh x = -i \tan ix`:: >>> tanh(2+3j) (0.9653858790221331242784803 - 0.009884375038322493720314034j) >>> j*tan(3-2j) (0.9653858790221331242784803 - 0.009884375038322493720314034j) """ cos = r""" Computes the cosine of `x`, `\cos(x)`. >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> cos(pi/3) 0.5 >>> cos(100000001) -0.9802850113244713353133243 >>> cos(2+3j) (-4.189625690968807230132555 - 9.109227893755336597979197j) >>> cos(inf) nan >>> nprint(chop(taylor(cos, 0, 6))) [1.0, 0.0, -0.5, 0.0, 0.0416667, 0.0, -0.00138889] Intervals are supported via :func:`mpmath.iv.cos`:: >>> iv.dps = 25; iv.pretty = True >>> iv.cos([0,1]) [0.540302305868139717400936602301, 1.0] >>> iv.cos([0,2]) [-0.41614683654714238699756823214, 1.0] """ sin = r""" Computes the sine of `x`, `\sin(x)`. >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> sin(pi/3) 0.8660254037844386467637232 >>> sin(100000001) 0.1975887055794968911438743 >>> sin(2+3j) (9.1544991469114295734673 - 4.168906959966564350754813j) >>> sin(inf) nan >>> nprint(chop(taylor(sin, 0, 6))) [0.0, 1.0, 0.0, -0.166667, 0.0, 0.00833333, 0.0] Intervals are supported via :func:`mpmath.iv.sin`:: >>> iv.dps = 25; iv.pretty = True >>> iv.sin([0,1]) [0.0, 0.841470984807896506652502331201] >>> iv.sin([0,2]) [0.0, 1.0] """ tan = r""" Computes the tangent of `x`, `\tan(x) = \frac{\sin(x)}{\cos(x)}`. The tangent function is singular at `x = (n+1/2)\pi`, but ``tan(x)`` always returns a finite result since `(n+1/2)\pi` cannot be represented exactly using floating-point arithmetic. >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> tan(pi/3) 1.732050807568877293527446 >>> tan(100000001) -0.2015625081449864533091058 >>> tan(2+3j) (-0.003764025641504248292751221 + 1.003238627353609801446359j) >>> tan(inf) nan >>> nprint(chop(taylor(tan, 0, 6))) [0.0, 1.0, 0.0, 0.333333, 0.0, 0.133333, 0.0] Intervals are supported via :func:`mpmath.iv.tan`:: >>> iv.dps = 25; iv.pretty = True >>> iv.tan([0,1]) [0.0, 1.55740772465490223050697482944] >>> iv.tan([0,2]) # Interval includes a singularity [-inf, +inf] """ sec = r""" Computes the secant of `x`, `\mathrm{sec}(x) = \frac{1}{\cos(x)}`. The secant function is singular at `x = (n+1/2)\pi`, but ``sec(x)`` always returns a finite result since `(n+1/2)\pi` cannot be represented exactly using floating-point arithmetic. >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> sec(pi/3) 2.0 >>> sec(10000001) -1.184723164360392819100265 >>> sec(2+3j) (-0.04167496441114427004834991 + 0.0906111371962375965296612j) >>> sec(inf) nan >>> nprint(chop(taylor(sec, 0, 6))) [1.0, 0.0, 0.5, 0.0, 0.208333, 0.0, 0.0847222] Intervals are supported via :func:`mpmath.iv.sec`:: >>> iv.dps = 25; iv.pretty = True >>> iv.sec([0,1]) [1.0, 1.85081571768092561791175326276] >>> iv.sec([0,2]) # Interval includes a singularity [-inf, +inf] """ csc = r""" Computes the cosecant of `x`, `\mathrm{csc}(x) = \frac{1}{\sin(x)}`. This cosecant function is singular at `x = n \pi`, but with the exception of the point `x = 0`, ``csc(x)`` returns a finite result since `n \pi` cannot be represented exactly using floating-point arithmetic. >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> csc(pi/3) 1.154700538379251529018298 >>> csc(10000001) -1.864910497503629858938891 >>> csc(2+3j) (0.09047320975320743980579048 + 0.04120098628857412646300981j) >>> csc(inf) nan Intervals are supported via :func:`mpmath.iv.csc`:: >>> iv.dps = 25; iv.pretty = True >>> iv.csc([0,1]) # Interval includes a singularity [1.18839510577812121626159943988, +inf] >>> iv.csc([0,2]) [1.0, +inf] """ cot = r""" Computes the cotangent of `x`, `\mathrm{cot}(x) = \frac{1}{\tan(x)} = \frac{\cos(x)}{\sin(x)}`. This cotangent function is singular at `x = n \pi`, but with the exception of the point `x = 0`, ``cot(x)`` returns a finite result since `n \pi` cannot be represented exactly using floating-point arithmetic. >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> cot(pi/3) 0.5773502691896257645091488 >>> cot(10000001) 1.574131876209625656003562 >>> cot(2+3j) (-0.003739710376336956660117409 - 0.9967577965693583104609688j) >>> cot(inf) nan Intervals are supported via :func:`mpmath.iv.cot`:: >>> iv.dps = 25; iv.pretty = True >>> iv.cot([0,1]) # Interval includes a singularity [0.642092615934330703006419974862, +inf] >>> iv.cot([1,2]) [-inf, +inf] """ acos = r""" Computes the inverse cosine or arccosine of `x`, `\cos^{-1}(x)`. Since `-1 \le \cos(x) \le 1` for real `x`, the inverse cosine is real-valued only for `-1 \le x \le 1`. On this interval, :func:`~mpmath.acos` is defined to be a monotonically decreasing function assuming values between `+\pi` and `0`. Basic values are:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> acos(-1) 3.141592653589793238462643 >>> acos(0) 1.570796326794896619231322 >>> acos(1) 0.0 >>> nprint(chop(taylor(acos, 0, 6))) [1.5708, -1.0, 0.0, -0.166667, 0.0, -0.075, 0.0] :func:`~mpmath.acos` is defined so as to be a proper inverse function of `\cos(\theta)` for `0 \le \theta < \pi`. We have `\cos(\cos^{-1}(x)) = x` for all `x`, but `\cos^{-1}(\cos(x)) = x` only for `0 \le \Re[x] < \pi`:: >>> for x in [1, 10, -1, 2+3j, 10+3j]: ... print("%s %s" % (cos(acos(x)), acos(cos(x)))) ... 1.0 1.0 (10.0 + 0.0j) 2.566370614359172953850574 -1.0 1.0 (2.0 + 3.0j) (2.0 + 3.0j) (10.0 + 3.0j) (2.566370614359172953850574 - 3.0j) The inverse cosine has two branch points: `x = \pm 1`. :func:`~mpmath.acos` places the branch cuts along the line segments `(-\infty, -1)` and `(+1, +\infty)`. In general, .. math :: \cos^{-1}(x) = \frac{\pi}{2} + i \log\left(ix + \sqrt{1-x^2} \right) where the principal-branch log and square root are implied. """ asin = r""" Computes the inverse sine or arcsine of `x`, `\sin^{-1}(x)`. Since `-1 \le \sin(x) \le 1` for real `x`, the inverse sine is real-valued only for `-1 \le x \le 1`. On this interval, it is defined to be a monotonically increasing function assuming values between `-\pi/2` and `\pi/2`. Basic values are:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> asin(-1) -1.570796326794896619231322 >>> asin(0) 0.0 >>> asin(1) 1.570796326794896619231322 >>> nprint(chop(taylor(asin, 0, 6))) [0.0, 1.0, 0.0, 0.166667, 0.0, 0.075, 0.0] :func:`~mpmath.asin` is defined so as to be a proper inverse function of `\sin(\theta)` for `-\pi/2 < \theta < \pi/2`. We have `\sin(\sin^{-1}(x)) = x` for all `x`, but `\sin^{-1}(\sin(x)) = x` only for `-\pi/2 < \Re[x] < \pi/2`:: >>> for x in [1, 10, -1, 1+3j, -2+3j]: ... print("%s %s" % (chop(sin(asin(x))), asin(sin(x)))) ... 1.0 1.0 10.0 -0.5752220392306202846120698 -1.0 -1.0 (1.0 + 3.0j) (1.0 + 3.0j) (-2.0 + 3.0j) (-1.141592653589793238462643 - 3.0j) The inverse sine has two branch points: `x = \pm 1`. :func:`~mpmath.asin` places the branch cuts along the line segments `(-\infty, -1)` and `(+1, +\infty)`. In general, .. math :: \sin^{-1}(x) = -i \log\left(ix + \sqrt{1-x^2} \right) where the principal-branch log and square root are implied. """ atan = r""" Computes the inverse tangent or arctangent of `x`, `\tan^{-1}(x)`. This is a real-valued function for all real `x`, with range `(-\pi/2, \pi/2)`. Basic values are:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> atan(-inf) -1.570796326794896619231322 >>> atan(-1) -0.7853981633974483096156609 >>> atan(0) 0.0 >>> atan(1) 0.7853981633974483096156609 >>> atan(inf) 1.570796326794896619231322 >>> nprint(chop(taylor(atan, 0, 6))) [0.0, 1.0, 0.0, -0.333333, 0.0, 0.2, 0.0] The inverse tangent is often used to compute angles. However, the atan2 function is often better for this as it preserves sign (see :func:`~mpmath.atan2`). :func:`~mpmath.atan` is defined so as to be a proper inverse function of `\tan(\theta)` for `-\pi/2 < \theta < \pi/2`. We have `\tan(\tan^{-1}(x)) = x` for all `x`, but `\tan^{-1}(\tan(x)) = x` only for `-\pi/2 < \Re[x] < \pi/2`:: >>> mp.dps = 25 >>> for x in [1, 10, -1, 1+3j, -2+3j]: ... print("%s %s" % (tan(atan(x)), atan(tan(x)))) ... 1.0 1.0 10.0 0.5752220392306202846120698 -1.0 -1.0 (1.0 + 3.0j) (1.000000000000000000000001 + 3.0j) (-2.0 + 3.0j) (1.141592653589793238462644 + 3.0j) The inverse tangent has two branch points: `x = \pm i`. :func:`~mpmath.atan` places the branch cuts along the line segments `(-i \infty, -i)` and `(+i, +i \infty)`. In general, .. math :: \tan^{-1}(x) = \frac{i}{2}\left(\log(1-ix)-\log(1+ix)\right) where the principal-branch log is implied. """ acot = r"""Computes the inverse cotangent of `x`, `\mathrm{cot}^{-1}(x) = \tan^{-1}(1/x)`.""" asec = r"""Computes the inverse secant of `x`, `\mathrm{sec}^{-1}(x) = \cos^{-1}(1/x)`.""" acsc = r"""Computes the inverse cosecant of `x`, `\mathrm{csc}^{-1}(x) = \sin^{-1}(1/x)`.""" coth = r"""Computes the hyperbolic cotangent of `x`, `\mathrm{coth}(x) = \frac{\cosh(x)}{\sinh(x)}`. """ sech = r"""Computes the hyperbolic secant of `x`, `\mathrm{sech}(x) = \frac{1}{\cosh(x)}`. """ csch = r"""Computes the hyperbolic cosecant of `x`, `\mathrm{csch}(x) = \frac{1}{\sinh(x)}`. """ acosh = r"""Computes the inverse hyperbolic cosine of `x`, `\mathrm{cosh}^{-1}(x) = \log(x+\sqrt{x+1}\sqrt{x-1})`. """ asinh = r"""Computes the inverse hyperbolic sine of `x`, `\mathrm{sinh}^{-1}(x) = \log(x+\sqrt{1+x^2})`. """ atanh = r"""Computes the inverse hyperbolic tangent of `x`, `\mathrm{tanh}^{-1}(x) = \frac{1}{2}\left(\log(1+x)-\log(1-x)\right)`. """ acoth = r"""Computes the inverse hyperbolic cotangent of `x`, `\mathrm{coth}^{-1}(x) = \tanh^{-1}(1/x)`.""" asech = r"""Computes the inverse hyperbolic secant of `x`, `\mathrm{sech}^{-1}(x) = \cosh^{-1}(1/x)`.""" acsch = r"""Computes the inverse hyperbolic cosecant of `x`, `\mathrm{csch}^{-1}(x) = \sinh^{-1}(1/x)`.""" sinpi = r""" Computes `\sin(\pi x)`, more accurately than the expression ``sin(pi*x)``:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> sinpi(10**10), sin(pi*(10**10)) (0.0, -2.23936276195592e-6) >>> sinpi(10**10+0.5), sin(pi*(10**10+0.5)) (1.0, 0.999999999998721) """ cospi = r""" Computes `\cos(\pi x)`, more accurately than the expression ``cos(pi*x)``:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> cospi(10**10), cos(pi*(10**10)) (1.0, 0.999999999997493) >>> cospi(10**10+0.5), cos(pi*(10**10+0.5)) (0.0, 1.59960492420134e-6) """ sinc = r""" ``sinc(x)`` computes the unnormalized sinc function, defined as .. math :: \mathrm{sinc}(x) = \begin{cases} \sin(x)/x, & \mbox{if } x \ne 0 \\ 1, & \mbox{if } x = 0. \end{cases} See :func:`~mpmath.sincpi` for the normalized sinc function. Simple values and limits include:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> sinc(0) 1.0 >>> sinc(1) 0.841470984807897 >>> sinc(inf) 0.0 The integral of the sinc function is the sine integral Si:: >>> quad(sinc, [0, 1]) 0.946083070367183 >>> si(1) 0.946083070367183 """ sincpi = r""" ``sincpi(x)`` computes the normalized sinc function, defined as .. math :: \mathrm{sinc}_{\pi}(x) = \begin{cases} \sin(\pi x)/(\pi x), & \mbox{if } x \ne 0 \\ 1, & \mbox{if } x = 0. \end{cases} Equivalently, we have `\mathrm{sinc}_{\pi}(x) = \mathrm{sinc}(\pi x)`. The normalization entails that the function integrates to unity over the entire real line:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> quadosc(sincpi, [-inf, inf], period=2.0) 1.0 Like, :func:`~mpmath.sinpi`, :func:`~mpmath.sincpi` is evaluated accurately at its roots:: >>> sincpi(10) 0.0 """ expj = r""" Convenience function for computing `e^{ix}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> expj(0) (1.0 + 0.0j) >>> expj(-1) (0.5403023058681397174009366 - 0.8414709848078965066525023j) >>> expj(j) (0.3678794411714423215955238 + 0.0j) >>> expj(1+j) (0.1987661103464129406288032 + 0.3095598756531121984439128j) """ expjpi = r""" Convenience function for computing `e^{i \pi x}`. Evaluation is accurate near zeros (see also :func:`~mpmath.cospi`, :func:`~mpmath.sinpi`):: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> expjpi(0) (1.0 + 0.0j) >>> expjpi(1) (-1.0 + 0.0j) >>> expjpi(0.5) (0.0 + 1.0j) >>> expjpi(-1) (-1.0 + 0.0j) >>> expjpi(j) (0.04321391826377224977441774 + 0.0j) >>> expjpi(1+j) (-0.04321391826377224977441774 + 0.0j) """ floor = r""" Computes the floor of `x`, `\lfloor x \rfloor`, defined as the largest integer less than or equal to `x`:: >>> from mpmath import * >>> mp.pretty = False >>> floor(3.5) mpf('3.0') .. note :: :func:`~mpmath.floor`, :func:`~mpmath.ceil` and :func:`~mpmath.nint` return a floating-point number, not a Python ``int``. If `\lfloor x \rfloor` is too large to be represented exactly at the present working precision, the result will be rounded, not necessarily in the direction implied by the mathematical definition of the function. To avoid rounding, use *prec=0*:: >>> mp.dps = 15 >>> print(int(floor(10**30+1))) 1000000000000000019884624838656 >>> print(int(floor(10**30+1, prec=0))) 1000000000000000000000000000001 The floor function is defined for complex numbers and acts on the real and imaginary parts separately:: >>> floor(3.25+4.75j) mpc(real='3.0', imag='4.0') """ ceil = r""" Computes the ceiling of `x`, `\lceil x \rceil`, defined as the smallest integer greater than or equal to `x`:: >>> from mpmath import * >>> mp.pretty = False >>> ceil(3.5) mpf('4.0') The ceiling function is defined for complex numbers and acts on the real and imaginary parts separately:: >>> ceil(3.25+4.75j) mpc(real='4.0', imag='5.0') See notes about rounding for :func:`~mpmath.floor`. """ nint = r""" Evaluates the nearest integer function, `\mathrm{nint}(x)`. This gives the nearest integer to `x`; on a tie, it gives the nearest even integer:: >>> from mpmath import * >>> mp.pretty = False >>> nint(3.2) mpf('3.0') >>> nint(3.8) mpf('4.0') >>> nint(3.5) mpf('4.0') >>> nint(4.5) mpf('4.0') The nearest integer function is defined for complex numbers and acts on the real and imaginary parts separately:: >>> nint(3.25+4.75j) mpc(real='3.0', imag='5.0') See notes about rounding for :func:`~mpmath.floor`. """ frac = r""" Gives the fractional part of `x`, defined as `\mathrm{frac}(x) = x - \lfloor x \rfloor` (see :func:`~mpmath.floor`). In effect, this computes `x` modulo 1, or `x+n` where `n \in \mathbb{Z}` is such that `x+n \in [0,1)`:: >>> from mpmath import * >>> mp.pretty = False >>> frac(1.25) mpf('0.25') >>> frac(3) mpf('0.0') >>> frac(-1.25) mpf('0.75') For a complex number, the fractional part function applies to the real and imaginary parts separately:: >>> frac(2.25+3.75j) mpc(real='0.25', imag='0.75') Plotted, the fractional part function gives a sawtooth wave. The Fourier series coefficients have a simple form:: >>> mp.dps = 15 >>> nprint(fourier(lambda x: frac(x)-0.5, [0,1], 4)) ([0.0, 0.0, 0.0, 0.0, 0.0], [0.0, -0.31831, -0.159155, -0.106103, -0.0795775]) >>> nprint([-1/(pi*k) for k in range(1,5)]) [-0.31831, -0.159155, -0.106103, -0.0795775] .. note:: The fractional part is sometimes defined as a symmetric function, i.e. returning `-\mathrm{frac}(-x)` if `x < 0`. This convention is used, for instance, by Mathematica's ``FractionalPart``. """ sign = r""" Returns the sign of `x`, defined as `\mathrm{sign}(x) = x / |x|` (with the special case `\mathrm{sign}(0) = 0`):: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> sign(10) mpf('1.0') >>> sign(-10) mpf('-1.0') >>> sign(0) mpf('0.0') Note that the sign function is also defined for complex numbers, for which it gives the projection onto the unit circle:: >>> mp.dps = 15; mp.pretty = True >>> sign(1+j) (0.707106781186547 + 0.707106781186547j) """ arg = r""" Computes the complex argument (phase) of `x`, defined as the signed angle between the positive real axis and `x` in the complex plane:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> arg(3) 0.0 >>> arg(3+3j) 0.785398163397448 >>> arg(3j) 1.5707963267949 >>> arg(-3) 3.14159265358979 >>> arg(-3j) -1.5707963267949 The angle is defined to satisfy `-\pi < \arg(x) \le \pi` and with the sign convention that a nonnegative imaginary part results in a nonnegative argument. The value returned by :func:`~mpmath.arg` is an ``mpf`` instance. """ fabs = r""" Returns the absolute value of `x`, `|x|`. Unlike :func:`abs`, :func:`~mpmath.fabs` converts non-mpmath numbers (such as ``int``) into mpmath numbers:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> fabs(3) mpf('3.0') >>> fabs(-3) mpf('3.0') >>> fabs(3+4j) mpf('5.0') """ re = r""" Returns the real part of `x`, `\Re(x)`. :func:`~mpmath.re` converts a non-mpmath number to an mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> re(3) mpf('3.0') >>> re(-1+4j) mpf('-1.0') """ im = r""" Returns the imaginary part of `x`, `\Im(x)`. :func:`~mpmath.im` converts a non-mpmath number to an mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> im(3) mpf('0.0') >>> im(-1+4j) mpf('4.0') """ conj = r""" Returns the complex conjugate of `x`, `\overline{x}`. Unlike ``x.conjugate()``, :func:`~mpmath.im` converts `x` to a mpmath number:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> conj(3) mpf('3.0') >>> conj(-1+4j) mpc(real='-1.0', imag='-4.0') """ polar = r""" Returns the polar representation of the complex number `z` as a pair `(r, \phi)` such that `z = r e^{i \phi}`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> polar(-2) (2.0, 3.14159265358979) >>> polar(3-4j) (5.0, -0.927295218001612) """ rect = r""" Returns the complex number represented by polar coordinates `(r, \phi)`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> chop(rect(2, pi)) -2.0 >>> rect(sqrt(2), -pi/4) (1.0 - 1.0j) """ expm1 = r""" Computes `e^x - 1`, accurately for small `x`. Unlike the expression ``exp(x) - 1``, ``expm1(x)`` does not suffer from potentially catastrophic cancellation:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> exp(1e-10)-1; print(expm1(1e-10)) 1.00000008274037e-10 1.00000000005e-10 >>> exp(1e-20)-1; print(expm1(1e-20)) 0.0 1.0e-20 >>> 1/(exp(1e-20)-1) Traceback (most recent call last): ... ZeroDivisionError >>> 1/expm1(1e-20) 1.0e+20 Evaluation works for extremely tiny values:: >>> expm1(0) 0.0 >>> expm1('1e-10000000') 1.0e-10000000 """ log1p = r""" Computes `\log(1+x)`, accurately for small `x`. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> log(1+1e-10); print(mp.log1p(1e-10)) 1.00000008269037e-10 9.9999999995e-11 >>> mp.log1p(1e-100j) (5.0e-201 + 1.0e-100j) >>> mp.log1p(0) 0.0 """ powm1 = r""" Computes `x^y - 1`, accurately when `x^y` is very close to 1. This avoids potentially catastrophic cancellation:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> power(0.99999995, 1e-10) - 1 0.0 >>> powm1(0.99999995, 1e-10) -5.00000012791934e-18 Powers exactly equal to 1, and only those powers, yield 0 exactly:: >>> powm1(-j, 4) (0.0 + 0.0j) >>> powm1(3, 0) 0.0 >>> powm1(fadd(-1, 1e-100, exact=True), 4) -4.0e-100 Evaluation works for extremely tiny `y`:: >>> powm1(2, '1e-100000') 6.93147180559945e-100001 >>> powm1(j, '1e-1000') (-1.23370055013617e-2000 + 1.5707963267949e-1000j) """ root = r""" ``root(z, n, k=0)`` computes an `n`-th root of `z`, i.e. returns a number `r` that (up to possible approximation error) satisfies `r^n = z`. (``nthroot`` is available as an alias for ``root``.) Every complex number `z \ne 0` has `n` distinct `n`-th roots, which are equidistant points on a circle with radius `|z|^{1/n}`, centered around the origin. A specific root may be selected using the optional index `k`. The roots are indexed counterclockwise, starting with `k = 0` for the root closest to the positive real half-axis. The `k = 0` root is the so-called principal `n`-th root, often denoted by `\sqrt[n]{z}` or `z^{1/n}`, and also given by `\exp(\log(z) / n)`. If `z` is a positive real number, the principal root is just the unique positive `n`-th root of `z`. Under some circumstances, non-principal real roots exist: for positive real `z`, `n` even, there is a negative root given by `k = n/2`; for negative real `z`, `n` odd, there is a negative root given by `k = (n-1)/2`. To obtain all roots with a simple expression, use ``[root(z,n,k) for k in range(n)]``. An important special case, ``root(1, n, k)`` returns the `k`-th `n`-th root of unity, `\zeta_k = e^{2 \pi i k / n}`. Alternatively, :func:`~mpmath.unitroots` provides a slightly more convenient way to obtain the roots of unity, including the option to compute only the primitive roots of unity. Both `k` and `n` should be integers; `k` outside of ``range(n)`` will be reduced modulo `n`. If `n` is negative, `x^{-1/n} = 1/x^{1/n}` (or the equivalent reciprocal for a non-principal root with `k \ne 0`) is computed. :func:`~mpmath.root` is implemented to use Newton's method for small `n`. At high precision, this makes `x^{1/n}` not much more expensive than the regular exponentiation, `x^n`. For very large `n`, :func:`~mpmath.nthroot` falls back to use the exponential function. **Examples** :func:`~mpmath.nthroot`/:func:`~mpmath.root` is faster and more accurate than raising to a floating-point fraction:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> 16807 ** (mpf(1)/5) mpf('7.0000000000000009') >>> root(16807, 5) mpf('7.0') >>> nthroot(16807, 5) # Alias mpf('7.0') A high-precision root:: >>> mp.dps = 50; mp.pretty = True >>> nthroot(10, 5) 1.584893192461113485202101373391507013269442133825 >>> nthroot(10, 5) ** 5 10.0 Computing principal and non-principal square and cube roots:: >>> mp.dps = 15 >>> root(10, 2) 3.16227766016838 >>> root(10, 2, 1) -3.16227766016838 >>> root(-10, 3) (1.07721734501594 + 1.86579517236206j) >>> root(-10, 3, 1) -2.15443469003188 >>> root(-10, 3, 2) (1.07721734501594 - 1.86579517236206j) All the 7th roots of a complex number:: >>> for r in [root(3+4j, 7, k) for k in range(7)]: ... print("%s %s" % (r, r**7)) ... (1.24747270589553 + 0.166227124177353j) (3.0 + 4.0j) (0.647824911301003 + 1.07895435170559j) (3.0 + 4.0j) (-0.439648254723098 + 1.17920694574172j) (3.0 + 4.0j) (-1.19605731775069 + 0.391492658196305j) (3.0 + 4.0j) (-1.05181082538903 - 0.691023585965793j) (3.0 + 4.0j) (-0.115529328478668 - 1.25318497558335j) (3.0 + 4.0j) (0.907748109144957 - 0.871672518271819j) (3.0 + 4.0j) Cube roots of unity:: >>> for k in range(3): print(root(1, 3, k)) ... 1.0 (-0.5 + 0.866025403784439j) (-0.5 - 0.866025403784439j) Some exact high order roots:: >>> root(75**210, 105) 5625.0 >>> root(1, 128, 96) (0.0 - 1.0j) >>> root(4**128, 128, 96) (0.0 - 4.0j) """ unitroots = r""" ``unitroots(n)`` returns `\zeta_0, \zeta_1, \ldots, \zeta_{n-1}`, all the distinct `n`-th roots of unity, as a list. If the option *primitive=True* is passed, only the primitive roots are returned. Every `n`-th root of unity satisfies `(\zeta_k)^n = 1`. There are `n` distinct roots for each `n` (`\zeta_k` and `\zeta_j` are the same when `k = j \pmod n`), which form a regular polygon with vertices on the unit circle. They are ordered counterclockwise with increasing `k`, starting with `\zeta_0 = 1`. **Examples** The roots of unity up to `n = 4`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nprint(unitroots(1)) [1.0] >>> nprint(unitroots(2)) [1.0, -1.0] >>> nprint(unitroots(3)) [1.0, (-0.5 + 0.866025j), (-0.5 - 0.866025j)] >>> nprint(unitroots(4)) [1.0, (0.0 + 1.0j), -1.0, (0.0 - 1.0j)] Roots of unity form a geometric series that sums to 0:: >>> mp.dps = 50 >>> chop(fsum(unitroots(25))) 0.0 Primitive roots up to `n = 4`:: >>> mp.dps = 15 >>> nprint(unitroots(1, primitive=True)) [1.0] >>> nprint(unitroots(2, primitive=True)) [-1.0] >>> nprint(unitroots(3, primitive=True)) [(-0.5 + 0.866025j), (-0.5 - 0.866025j)] >>> nprint(unitroots(4, primitive=True)) [(0.0 + 1.0j), (0.0 - 1.0j)] There are only four primitive 12th roots:: >>> nprint(unitroots(12, primitive=True)) [(0.866025 + 0.5j), (-0.866025 + 0.5j), (-0.866025 - 0.5j), (0.866025 - 0.5j)] The `n`-th roots of unity form a group, the cyclic group of order `n`. Any primitive root `r` is a generator for this group, meaning that `r^0, r^1, \ldots, r^{n-1}` gives the whole set of unit roots (in some permuted order):: >>> for r in unitroots(6): print(r) ... 1.0 (0.5 + 0.866025403784439j) (-0.5 + 0.866025403784439j) -1.0 (-0.5 - 0.866025403784439j) (0.5 - 0.866025403784439j) >>> r = unitroots(6, primitive=True)[1] >>> for k in range(6): print(chop(r**k)) ... 1.0 (0.5 - 0.866025403784439j) (-0.5 - 0.866025403784439j) -1.0 (-0.5 + 0.866025403784438j) (0.5 + 0.866025403784438j) The number of primitive roots equals the Euler totient function `\phi(n)`:: >>> [len(unitroots(n, primitive=True)) for n in range(1,20)] [1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18] """ log = r""" Computes the base-`b` logarithm of `x`, `\log_b(x)`. If `b` is unspecified, :func:`~mpmath.log` computes the natural (base `e`) logarithm and is equivalent to :func:`~mpmath.ln`. In general, the base `b` logarithm is defined in terms of the natural logarithm as `\log_b(x) = \ln(x)/\ln(b)`. By convention, we take `\log(0) = -\infty`. The natural logarithm is real if `x > 0` and complex if `x < 0` or if `x` is complex. The principal branch of the complex logarithm is used, meaning that `\Im(\ln(x)) = -\pi < \arg(x) \le \pi`. **Examples** Some basic values and limits:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> log(1) 0.0 >>> log(2) 0.693147180559945 >>> log(1000,10) 3.0 >>> log(4, 16) 0.5 >>> log(j) (0.0 + 1.5707963267949j) >>> log(-1) (0.0 + 3.14159265358979j) >>> log(0) -inf >>> log(inf) +inf The natural logarithm is the antiderivative of `1/x`:: >>> quad(lambda x: 1/x, [1, 5]) 1.6094379124341 >>> log(5) 1.6094379124341 >>> diff(log, 10) 0.1 The Taylor series expansion of the natural logarithm around `x = 1` has coefficients `(-1)^{n+1}/n`:: >>> nprint(taylor(log, 1, 7)) [0.0, 1.0, -0.5, 0.333333, -0.25, 0.2, -0.166667, 0.142857] :func:`~mpmath.log` supports arbitrary precision evaluation:: >>> mp.dps = 50 >>> log(pi) 1.1447298858494001741434273513530587116472948129153 >>> log(pi, pi**3) 0.33333333333333333333333333333333333333333333333333 >>> mp.dps = 25 >>> log(3+4j) (1.609437912434100374600759 + 0.9272952180016122324285125j) """ log10 = r""" Computes the base-10 logarithm of `x`, `\log_{10}(x)`. ``log10(x)`` is equivalent to ``log(x, 10)``. """ fmod = r""" Converts `x` and `y` to mpmath numbers and returns `x \mod y`. For mpmath numbers, this is equivalent to ``x % y``. >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> fmod(100, pi) 2.61062773871641 You can use :func:`~mpmath.fmod` to compute fractional parts of numbers:: >>> fmod(10.25, 1) 0.25 """ radians = r""" Converts the degree angle `x` to radians:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> radians(60) 1.0471975511966 """ degrees = r""" Converts the radian angle `x` to a degree angle:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> degrees(pi/3) 60.0 """ atan2 = r""" Computes the two-argument arctangent, `\mathrm{atan2}(y, x)`, giving the signed angle between the positive `x`-axis and the point `(x, y)` in the 2D plane. This function is defined for real `x` and `y` only. The two-argument arctangent essentially computes `\mathrm{atan}(y/x)`, but accounts for the signs of both `x` and `y` to give the angle for the correct quadrant. The following examples illustrate the difference:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> atan2(1,1), atan(1/1.) (0.785398163397448, 0.785398163397448) >>> atan2(1,-1), atan(1/-1.) (2.35619449019234, -0.785398163397448) >>> atan2(-1,1), atan(-1/1.) (-0.785398163397448, -0.785398163397448) >>> atan2(-1,-1), atan(-1/-1.) (-2.35619449019234, 0.785398163397448) The angle convention is the same as that used for the complex argument; see :func:`~mpmath.arg`. """ fibonacci = r""" ``fibonacci(n)`` computes the `n`-th Fibonacci number, `F(n)`. The Fibonacci numbers are defined by the recurrence `F(n) = F(n-1) + F(n-2)` with the initial values `F(0) = 0`, `F(1) = 1`. :func:`~mpmath.fibonacci` extends this definition to arbitrary real and complex arguments using the formula .. math :: F(z) = \frac{\phi^z - \cos(\pi z) \phi^{-z}}{\sqrt 5} where `\phi` is the golden ratio. :func:`~mpmath.fibonacci` also uses this continuous formula to compute `F(n)` for extremely large `n`, where calculating the exact integer would be wasteful. For convenience, :func:`~mpmath.fib` is available as an alias for :func:`~mpmath.fibonacci`. **Basic examples** Some small Fibonacci numbers are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for i in range(10): ... print(fibonacci(i)) ... 0.0 1.0 1.0 2.0 3.0 5.0 8.0 13.0 21.0 34.0 >>> fibonacci(50) 12586269025.0 The recurrence for `F(n)` extends backwards to negative `n`:: >>> for i in range(10): ... print(fibonacci(-i)) ... 0.0 1.0 -1.0 2.0 -3.0 5.0 -8.0 13.0 -21.0 34.0 Large Fibonacci numbers will be computed approximately unless the precision is set high enough:: >>> fib(200) 2.8057117299251e+41 >>> mp.dps = 45 >>> fib(200) 280571172992510140037611932413038677189525.0 :func:`~mpmath.fibonacci` can compute approximate Fibonacci numbers of stupendous size:: >>> mp.dps = 15 >>> fibonacci(10**25) 3.49052338550226e+2089876402499787337692720 **Real and complex arguments** The extended Fibonacci function is an analytic function. The property `F(z) = F(z-1) + F(z-2)` holds for arbitrary `z`:: >>> mp.dps = 15 >>> fib(pi) 2.1170270579161 >>> fib(pi-1) + fib(pi-2) 2.1170270579161 >>> fib(3+4j) (-5248.51130728372 - 14195.962288353j) >>> fib(2+4j) + fib(1+4j) (-5248.51130728372 - 14195.962288353j) The Fibonacci function has infinitely many roots on the negative half-real axis. The first root is at 0, the second is close to -0.18, and then there are infinitely many roots that asymptotically approach `-n+1/2`:: >>> findroot(fib, -0.2) -0.183802359692956 >>> findroot(fib, -2) -1.57077646820395 >>> findroot(fib, -17) -16.4999999596115 >>> findroot(fib, -24) -23.5000000000479 **Mathematical relationships** For large `n`, `F(n+1)/F(n)` approaches the golden ratio:: >>> mp.dps = 50 >>> fibonacci(101)/fibonacci(100) 1.6180339887498948482045868343656381177203127439638 >>> +phi 1.6180339887498948482045868343656381177203091798058 The sum of reciprocal Fibonacci numbers converges to an irrational number for which no closed form expression is known:: >>> mp.dps = 15 >>> nsum(lambda n: 1/fib(n), [1, inf]) 3.35988566624318 Amazingly, however, the sum of odd-index reciprocal Fibonacci numbers can be expressed in terms of a Jacobi theta function:: >>> nsum(lambda n: 1/fib(2*n+1), [0, inf]) 1.82451515740692 >>> sqrt(5)*jtheta(2,0,(3-sqrt(5))/2)**2/4 1.82451515740692 Some related sums can be done in closed form:: >>> nsum(lambda k: 1/(1+fib(2*k+1)), [0, inf]) 1.11803398874989 >>> phi - 0.5 1.11803398874989 >>> f = lambda k:(-1)**(k+1) / sum(fib(n)**2 for n in range(1,int(k+1))) >>> nsum(f, [1, inf]) 0.618033988749895 >>> phi-1 0.618033988749895 **References** 1. http://mathworld.wolfram.com/FibonacciNumber.html """ altzeta = r""" Gives the Dirichlet eta function, `\eta(s)`, also known as the alternating zeta function. This function is defined in analogy with the Riemann zeta function as providing the sum of the alternating series .. math :: \eta(s) = \sum_{k=0}^{\infty} \frac{(-1)^k}{k^s} = 1-\frac{1}{2^s}+\frac{1}{3^s}-\frac{1}{4^s}+\ldots The eta function, unlike the Riemann zeta function, is an entire function, having a finite value for all complex `s`. The special case `\eta(1) = \log(2)` gives the value of the alternating harmonic series. The alternating zeta function may expressed using the Riemann zeta function as `\eta(s) = (1 - 2^{1-s}) \zeta(s)`. It can also be expressed in terms of the Hurwitz zeta function, for example using :func:`~mpmath.dirichlet` (see documentation for that function). **Examples** Some special values are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> altzeta(1) 0.693147180559945 >>> altzeta(0) 0.5 >>> altzeta(-1) 0.25 >>> altzeta(-2) 0.0 An example of a sum that can be computed more accurately and efficiently via :func:`~mpmath.altzeta` than via numerical summation:: >>> sum(-(-1)**n / mpf(n)**2.5 for n in range(1, 100)) 0.867204951503984 >>> altzeta(2.5) 0.867199889012184 At positive even integers, the Dirichlet eta function evaluates to a rational multiple of a power of `\pi`:: >>> altzeta(2) 0.822467033424113 >>> pi**2/12 0.822467033424113 Like the Riemann zeta function, `\eta(s)`, approaches 1 as `s` approaches positive infinity, although it does so from below rather than from above:: >>> altzeta(30) 0.999999999068682 >>> altzeta(inf) 1.0 >>> mp.pretty = False >>> altzeta(1000, rounding='d') mpf('0.99999999999999989') >>> altzeta(1000, rounding='u') mpf('1.0') **References** 1. http://mathworld.wolfram.com/DirichletEtaFunction.html 2. http://en.wikipedia.org/wiki/Dirichlet_eta_function """ factorial = r""" Computes the factorial, `x!`. For integers `n \ge 0`, we have `n! = 1 \cdot 2 \cdots (n-1) \cdot n` and more generally the factorial is defined for real or complex `x` by `x! = \Gamma(x+1)`. **Examples** Basic values and limits:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for k in range(6): ... print("%s %s" % (k, fac(k))) ... 0 1.0 1 1.0 2 2.0 3 6.0 4 24.0 5 120.0 >>> fac(inf) +inf >>> fac(0.5), sqrt(pi)/2 (0.886226925452758, 0.886226925452758) For large positive `x`, `x!` can be approximated by Stirling's formula:: >>> x = 10**10 >>> fac(x) 2.32579620567308e+95657055186 >>> sqrt(2*pi*x)*(x/e)**x 2.32579597597705e+95657055186 :func:`~mpmath.fac` supports evaluation for astronomically large values:: >>> fac(10**30) 6.22311232304258e+29565705518096748172348871081098 Reciprocal factorials appear in the Taylor series of the exponential function (among many other contexts):: >>> nsum(lambda k: 1/fac(k), [0, inf]), exp(1) (2.71828182845905, 2.71828182845905) >>> nsum(lambda k: pi**k/fac(k), [0, inf]), exp(pi) (23.1406926327793, 23.1406926327793) """ gamma = r""" Computes the gamma function, `\Gamma(x)`. The gamma function is a shifted version of the ordinary factorial, satisfying `\Gamma(n) = (n-1)!` for integers `n > 0`. More generally, it is defined by .. math :: \Gamma(x) = \int_0^{\infty} t^{x-1} e^{-t}\, dt for any real or complex `x` with `\Re(x) > 0` and for `\Re(x) < 0` by analytic continuation. **Examples** Basic values and limits:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for k in range(1, 6): ... print("%s %s" % (k, gamma(k))) ... 1 1.0 2 1.0 3 2.0 4 6.0 5 24.0 >>> gamma(inf) +inf >>> gamma(0) Traceback (most recent call last): ... ValueError: gamma function pole The gamma function of a half-integer is a rational multiple of `\sqrt{\pi}`:: >>> gamma(0.5), sqrt(pi) (1.77245385090552, 1.77245385090552) >>> gamma(1.5), sqrt(pi)/2 (0.886226925452758, 0.886226925452758) We can check the integral definition:: >>> gamma(3.5) 3.32335097044784 >>> quad(lambda t: t**2.5*exp(-t), [0,inf]) 3.32335097044784 :func:`~mpmath.gamma` supports arbitrary-precision evaluation and complex arguments:: >>> mp.dps = 50 >>> gamma(sqrt(3)) 0.91510229697308632046045539308226554038315280564184 >>> mp.dps = 25 >>> gamma(2j) (0.009902440080927490985955066 - 0.07595200133501806872408048j) Arguments can also be large. Note that the gamma function grows very quickly:: >>> mp.dps = 15 >>> gamma(10**20) 1.9328495143101e+1956570551809674817225 """ psi = r""" Gives the polygamma function of order `m` of `z`, `\psi^{(m)}(z)`. Special cases are known as the *digamma function* (`\psi^{(0)}(z)`), the *trigamma function* (`\psi^{(1)}(z)`), etc. The polygamma functions are defined as the logarithmic derivatives of the gamma function: .. math :: \psi^{(m)}(z) = \left(\frac{d}{dz}\right)^{m+1} \log \Gamma(z) In particular, `\psi^{(0)}(z) = \Gamma'(z)/\Gamma(z)`. In the present implementation of :func:`~mpmath.psi`, the order `m` must be a nonnegative integer, while the argument `z` may be an arbitrary complex number (with exception for the polygamma function's poles at `z = 0, -1, -2, \ldots`). **Examples** For various rational arguments, the polygamma function reduces to a combination of standard mathematical constants:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> psi(0, 1), -euler (-0.5772156649015328606065121, -0.5772156649015328606065121) >>> psi(1, '1/4'), pi**2+8*catalan (17.19732915450711073927132, 17.19732915450711073927132) >>> psi(2, '1/2'), -14*apery (-16.82879664423431999559633, -16.82879664423431999559633) The polygamma functions are derivatives of each other:: >>> diff(lambda x: psi(3, x), pi), psi(4, pi) (-0.1105749312578862734526952, -0.1105749312578862734526952) >>> quad(lambda x: psi(4, x), [2, 3]), psi(3,3)-psi(3,2) (-0.375, -0.375) The digamma function diverges logarithmically as `z \to \infty`, while higher orders tend to zero:: >>> psi(0,inf), psi(1,inf), psi(2,inf) (+inf, 0.0, 0.0) Evaluation for a complex argument:: >>> psi(2, -1-2j) (0.03902435405364952654838445 + 0.1574325240413029954685366j) Evaluation is supported for large orders `m` and/or large arguments `z`:: >>> psi(3, 10**100) 2.0e-300 >>> psi(250, 10**30+10**20*j) (-1.293142504363642687204865e-7010 + 3.232856260909107391513108e-7018j) **Application to infinite series** Any infinite series where the summand is a rational function of the index `k` can be evaluated in closed form in terms of polygamma functions of the roots and poles of the summand:: >>> a = sqrt(2) >>> b = sqrt(3) >>> nsum(lambda k: 1/((k+a)**2*(k+b)), [0, inf]) 0.4049668927517857061917531 >>> (psi(0,a)-psi(0,b)-a*psi(1,a)+b*psi(1,a))/(a-b)**2 0.4049668927517857061917531 This follows from the series representation (`m > 0`) .. math :: \psi^{(m)}(z) = (-1)^{m+1} m! \sum_{k=0}^{\infty} \frac{1}{(z+k)^{m+1}}. Since the roots of a polynomial may be complex, it is sometimes necessary to use the complex polygamma function to evaluate an entirely real-valued sum:: >>> nsum(lambda k: 1/(k**2-2*k+3), [0, inf]) 1.694361433907061256154665 >>> nprint(polyroots([1,-2,3])) [(1.0 - 1.41421j), (1.0 + 1.41421j)] >>> r1 = 1-sqrt(2)*j >>> r2 = r1.conjugate() >>> (psi(0,-r2)-psi(0,-r1))/(r1-r2) (1.694361433907061256154665 + 0.0j) """ digamma = r""" Shortcut for ``psi(0,z)``. """ harmonic = r""" If `n` is an integer, ``harmonic(n)`` gives a floating-point approximation of the `n`-th harmonic number `H(n)`, defined as .. math :: H(n) = 1 + \frac{1}{2} + \frac{1}{3} + \ldots + \frac{1}{n} The first few harmonic numbers are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(8): ... print("%s %s" % (n, harmonic(n))) ... 0 0.0 1 1.0 2 1.5 3 1.83333333333333 4 2.08333333333333 5 2.28333333333333 6 2.45 7 2.59285714285714 The infinite harmonic series `1 + 1/2 + 1/3 + \ldots` diverges:: >>> harmonic(inf) +inf :func:`~mpmath.harmonic` is evaluated using the digamma function rather than by summing the harmonic series term by term. It can therefore be computed quickly for arbitrarily large `n`, and even for nonintegral arguments:: >>> harmonic(10**100) 230.835724964306 >>> harmonic(0.5) 0.613705638880109 >>> harmonic(3+4j) (2.24757548223494 + 0.850502209186044j) :func:`~mpmath.harmonic` supports arbitrary precision evaluation:: >>> mp.dps = 50 >>> harmonic(11) 3.0198773448773448773448773448773448773448773448773 >>> harmonic(pi) 1.8727388590273302654363491032336134987519132374152 The harmonic series diverges, but at a glacial pace. It is possible to calculate the exact number of terms required before the sum exceeds a given amount, say 100:: >>> mp.dps = 50 >>> v = 10**findroot(lambda x: harmonic(10**x) - 100, 10) >>> v 15092688622113788323693563264538101449859496.864101 >>> v = int(ceil(v)) >>> print(v) 15092688622113788323693563264538101449859497 >>> harmonic(v-1) 99.999999999999999999999999999999999999999999942747 >>> harmonic(v) 100.000000000000000000000000000000000000000000009 """ bernoulli = r""" Computes the nth Bernoulli number, `B_n`, for any integer `n \ge 0`. The Bernoulli numbers are rational numbers, but this function returns a floating-point approximation. To obtain an exact fraction, use :func:`~mpmath.bernfrac` instead. **Examples** Numerical values of the first few Bernoulli numbers:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(15): ... print("%s %s" % (n, bernoulli(n))) ... 0 1.0 1 -0.5 2 0.166666666666667 3 0.0 4 -0.0333333333333333 5 0.0 6 0.0238095238095238 7 0.0 8 -0.0333333333333333 9 0.0 10 0.0757575757575758 11 0.0 12 -0.253113553113553 13 0.0 14 1.16666666666667 Bernoulli numbers can be approximated with arbitrary precision:: >>> mp.dps = 50 >>> bernoulli(100) -2.8382249570693706959264156336481764738284680928013e+78 Arbitrarily large `n` are supported:: >>> mp.dps = 15 >>> bernoulli(10**20 + 2) 3.09136296657021e+1876752564973863312327 The Bernoulli numbers are related to the Riemann zeta function at integer arguments:: >>> -bernoulli(8) * (2*pi)**8 / (2*fac(8)) 1.00407735619794 >>> zeta(8) 1.00407735619794 **Algorithm** For small `n` (`n < 3000`) :func:`~mpmath.bernoulli` uses a recurrence formula due to Ramanujan. All results in this range are cached, so sequential computation of small Bernoulli numbers is guaranteed to be fast. For larger `n`, `B_n` is evaluated in terms of the Riemann zeta function. """ stieltjes = r""" For a nonnegative integer `n`, ``stieltjes(n)`` computes the `n`-th Stieltjes constant `\gamma_n`, defined as the `n`-th coefficient in the Laurent series expansion of the Riemann zeta function around the pole at `s = 1`. That is, we have: .. math :: \zeta(s) = \frac{1}{s-1} \sum_{n=0}^{\infty} \frac{(-1)^n}{n!} \gamma_n (s-1)^n More generally, ``stieltjes(n, a)`` gives the corresponding coefficient `\gamma_n(a)` for the Hurwitz zeta function `\zeta(s,a)` (with `\gamma_n = \gamma_n(1)`). **Examples** The zeroth Stieltjes constant is just Euler's constant `\gamma`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> stieltjes(0) 0.577215664901533 Some more values are:: >>> stieltjes(1) -0.0728158454836767 >>> stieltjes(10) 0.000205332814909065 >>> stieltjes(30) 0.00355772885557316 >>> stieltjes(1000) -1.57095384420474e+486 >>> stieltjes(2000) 2.680424678918e+1109 >>> stieltjes(1, 2.5) -0.23747539175716 An alternative way to compute `\gamma_1`:: >>> diff(extradps(15)(lambda x: 1/(x-1) - zeta(x)), 1) -0.0728158454836767 :func:`~mpmath.stieltjes` supports arbitrary precision evaluation:: >>> mp.dps = 50 >>> stieltjes(2) -0.0096903631928723184845303860352125293590658061013408 **Algorithm** :func:`~mpmath.stieltjes` numerically evaluates the integral in the following representation due to Ainsworth, Howell and Coffey [1], [2]: .. math :: \gamma_n(a) = \frac{\log^n a}{2a} - \frac{\log^{n+1}(a)}{n+1} + \frac{2}{a} \Re \int_0^{\infty} \frac{(x/a-i)\log^n(a-ix)}{(1+x^2/a^2)(e^{2\pi x}-1)} dx. For some reference values with `a = 1`, see e.g. [4]. **References** 1. O. R. Ainsworth & L. W. Howell, "An integral representation of the generalized Euler-Mascheroni constants", NASA Technical Paper 2456 (1985), http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19850014994_1985014994.pdf 2. M. W. Coffey, "The Stieltjes constants, their relation to the `\eta_j` coefficients, and representation of the Hurwitz zeta function", arXiv:0706.0343v1 http://arxiv.org/abs/0706.0343 3. http://mathworld.wolfram.com/StieltjesConstants.html 4. http://pi.lacim.uqam.ca/piDATA/stieltjesgamma.txt """ gammaprod = r""" Given iterables `a` and `b`, ``gammaprod(a, b)`` computes the product / quotient of gamma functions: .. math :: \frac{\Gamma(a_0) \Gamma(a_1) \cdots \Gamma(a_p)} {\Gamma(b_0) \Gamma(b_1) \cdots \Gamma(b_q)} Unlike direct calls to :func:`~mpmath.gamma`, :func:`~mpmath.gammaprod` considers the entire product as a limit and evaluates this limit properly if any of the numerator or denominator arguments are nonpositive integers such that poles of the gamma function are encountered. That is, :func:`~mpmath.gammaprod` evaluates .. math :: \lim_{\epsilon \to 0} \frac{\Gamma(a_0+\epsilon) \Gamma(a_1+\epsilon) \cdots \Gamma(a_p+\epsilon)} {\Gamma(b_0+\epsilon) \Gamma(b_1+\epsilon) \cdots \Gamma(b_q+\epsilon)} In particular: * If there are equally many poles in the numerator and the denominator, the limit is a rational number times the remaining, regular part of the product. * If there are more poles in the numerator, :func:`~mpmath.gammaprod` returns ``+inf``. * If there are more poles in the denominator, :func:`~mpmath.gammaprod` returns 0. **Examples** The reciprocal gamma function `1/\Gamma(x)` evaluated at `x = 0`:: >>> from mpmath import * >>> mp.dps = 15 >>> gammaprod([], [0]) 0.0 A limit:: >>> gammaprod([-4], [-3]) -0.25 >>> limit(lambda x: gamma(x-1)/gamma(x), -3, direction=1) -0.25 >>> limit(lambda x: gamma(x-1)/gamma(x), -3, direction=-1) -0.25 """ beta = r""" Computes the beta function, `B(x,y) = \Gamma(x) \Gamma(y) / \Gamma(x+y)`. The beta function is also commonly defined by the integral representation .. math :: B(x,y) = \int_0^1 t^{x-1} (1-t)^{y-1} \, dt **Examples** For integer and half-integer arguments where all three gamma functions are finite, the beta function becomes either rational number or a rational multiple of `\pi`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> beta(5, 2) 0.0333333333333333 >>> beta(1.5, 2) 0.266666666666667 >>> 16*beta(2.5, 1.5) 3.14159265358979 Where appropriate, :func:`~mpmath.beta` evaluates limits. A pole of the beta function is taken to result in ``+inf``:: >>> beta(-0.5, 0.5) 0.0 >>> beta(-3, 3) -0.333333333333333 >>> beta(-2, 3) +inf >>> beta(inf, 1) 0.0 >>> beta(inf, 0) nan :func:`~mpmath.beta` supports complex numbers and arbitrary precision evaluation:: >>> beta(1, 2+j) (0.4 - 0.2j) >>> mp.dps = 25 >>> beta(j,0.5) (1.079424249270925780135675 - 1.410032405664160838288752j) >>> mp.dps = 50 >>> beta(pi, e) 0.037890298781212201348153837138927165984170287886464 Various integrals can be computed by means of the beta function:: >>> mp.dps = 15 >>> quad(lambda t: t**2.5*(1-t)**2, [0, 1]) 0.0230880230880231 >>> beta(3.5, 3) 0.0230880230880231 >>> quad(lambda t: sin(t)**4 * sqrt(cos(t)), [0, pi/2]) 0.319504062596158 >>> beta(2.5, 0.75)/2 0.319504062596158 """ betainc = r""" ``betainc(a, b, x1=0, x2=1, regularized=False)`` gives the generalized incomplete beta function, .. math :: I_{x_1}^{x_2}(a,b) = \int_{x_1}^{x_2} t^{a-1} (1-t)^{b-1} dt. When `x_1 = 0, x_2 = 1`, this reduces to the ordinary (complete) beta function `B(a,b)`; see :func:`~mpmath.beta`. With the keyword argument ``regularized=True``, :func:`~mpmath.betainc` computes the regularized incomplete beta function `I_{x_1}^{x_2}(a,b) / B(a,b)`. This is the cumulative distribution of the beta distribution with parameters `a`, `b`. .. note : Implementations of the incomplete beta function in some other software uses a different argument order. For example, Mathematica uses the reversed argument order ``Beta[x1,x2,a,b]``. For the equivalent of SciPy's three-argument incomplete beta integral (implicitly with `x1 = 0`), use ``betainc(a,b,0,x2,regularized=True)``. **Examples** Verifying that :func:`~mpmath.betainc` computes the integral in the definition:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> x,y,a,b = 3, 4, 0, 6 >>> betainc(x, y, a, b) -4010.4 >>> quad(lambda t: t**(x-1) * (1-t)**(y-1), [a, b]) -4010.4 The arguments may be arbitrary complex numbers:: >>> betainc(0.75, 1-4j, 0, 2+3j) (0.2241657956955709603655887 + 0.3619619242700451992411724j) With regularization:: >>> betainc(1, 2, 0, 0.25, regularized=True) 0.4375 >>> betainc(pi, e, 0, 1, regularized=True) # Complete 1.0 The beta integral satisfies some simple argument transformation symmetries:: >>> mp.dps = 15 >>> betainc(2,3,4,5), -betainc(2,3,5,4), betainc(3,2,1-5,1-4) (56.0833333333333, 56.0833333333333, 56.0833333333333) The beta integral can often be evaluated analytically. For integer and rational arguments, the incomplete beta function typically reduces to a simple algebraic-logarithmic expression:: >>> mp.dps = 25 >>> identify(chop(betainc(0, 0, 3, 4))) '-(log((9/8)))' >>> identify(betainc(2, 3, 4, 5)) '(673/12)' >>> identify(betainc(1.5, 1, 1, 2)) '((-12+sqrt(1152))/18)' """ binomial = r""" Computes the binomial coefficient .. math :: {n \choose k} = \frac{n!}{k!(n-k)!}. The binomial coefficient gives the number of ways that `k` items can be chosen from a set of `n` items. More generally, the binomial coefficient is a well-defined function of arbitrary real or complex `n` and `k`, via the gamma function. **Examples** Generate Pascal's triangle:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(5): ... nprint([binomial(n,k) for k in range(n+1)]) ... [1.0] [1.0, 1.0] [1.0, 2.0, 1.0] [1.0, 3.0, 3.0, 1.0] [1.0, 4.0, 6.0, 4.0, 1.0] There is 1 way to select 0 items from the empty set, and 0 ways to select 1 item from the empty set:: >>> binomial(0, 0) 1.0 >>> binomial(0, 1) 0.0 :func:`~mpmath.binomial` supports large arguments:: >>> binomial(10**20, 10**20-5) 8.33333333333333e+97 >>> binomial(10**20, 10**10) 2.60784095465201e+104342944813 Nonintegral binomial coefficients find use in series expansions:: >>> nprint(taylor(lambda x: (1+x)**0.25, 0, 4)) [1.0, 0.25, -0.09375, 0.0546875, -0.0375977] >>> nprint([binomial(0.25, k) for k in range(5)]) [1.0, 0.25, -0.09375, 0.0546875, -0.0375977] An integral representation:: >>> n, k = 5, 3 >>> f = lambda t: exp(-j*k*t)*(1+exp(j*t))**n >>> chop(quad(f, [-pi,pi])/(2*pi)) 10.0 >>> binomial(n,k) 10.0 """ rf = r""" Computes the rising factorial or Pochhammer symbol, .. math :: x^{(n)} = x (x+1) \cdots (x+n-1) = \frac{\Gamma(x+n)}{\Gamma(x)} where the rightmost expression is valid for nonintegral `n`. **Examples** For integral `n`, the rising factorial is a polynomial:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(5): ... nprint(taylor(lambda x: rf(x,n), 0, n)) ... [1.0] [0.0, 1.0] [0.0, 1.0, 1.0] [0.0, 2.0, 3.0, 1.0] [0.0, 6.0, 11.0, 6.0, 1.0] Evaluation is supported for arbitrary arguments:: >>> rf(2+3j, 5.5) (-7202.03920483347 - 3777.58810701527j) """ ff = r""" Computes the falling factorial, .. math :: (x)_n = x (x-1) \cdots (x-n+1) = \frac{\Gamma(x+1)}{\Gamma(x-n+1)} where the rightmost expression is valid for nonintegral `n`. **Examples** For integral `n`, the falling factorial is a polynomial:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(5): ... nprint(taylor(lambda x: ff(x,n), 0, n)) ... [1.0] [0.0, 1.0] [0.0, -1.0, 1.0] [0.0, 2.0, -3.0, 1.0] [0.0, -6.0, 11.0, -6.0, 1.0] Evaluation is supported for arbitrary arguments:: >>> ff(2+3j, 5.5) (-720.41085888203 + 316.101124983878j) """ fac2 = r""" Computes the double factorial `x!!`, defined for integers `x > 0` by .. math :: x!! = \begin{cases} 1 \cdot 3 \cdots (x-2) \cdot x & x \;\mathrm{odd} \\ 2 \cdot 4 \cdots (x-2) \cdot x & x \;\mathrm{even} \end{cases} and more generally by [1] .. math :: x!! = 2^{x/2} \left(\frac{\pi}{2}\right)^{(\cos(\pi x)-1)/4} \Gamma\left(\frac{x}{2}+1\right). **Examples** The integer sequence of double factorials begins:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nprint([fac2(n) for n in range(10)]) [1.0, 1.0, 2.0, 3.0, 8.0, 15.0, 48.0, 105.0, 384.0, 945.0] For large `x`, double factorials follow a Stirling-like asymptotic approximation:: >>> x = mpf(10000) >>> fac2(x) 5.97272691416282e+17830 >>> sqrt(pi)*x**((x+1)/2)*exp(-x/2) 5.97262736954392e+17830 The recurrence formula `x!! = x (x-2)!!` can be reversed to define the double factorial of negative odd integers (but not negative even integers):: >>> fac2(-1), fac2(-3), fac2(-5), fac2(-7) (1.0, -1.0, 0.333333333333333, -0.0666666666666667) >>> fac2(-2) Traceback (most recent call last): ... ValueError: gamma function pole With the exception of the poles at negative even integers, :func:`~mpmath.fac2` supports evaluation for arbitrary complex arguments. The recurrence formula is valid generally:: >>> fac2(pi+2j) (-1.3697207890154e-12 + 3.93665300979176e-12j) >>> (pi+2j)*fac2(pi-2+2j) (-1.3697207890154e-12 + 3.93665300979176e-12j) Double factorials should not be confused with nested factorials, which are immensely larger:: >>> fac(fac(20)) 5.13805976125208e+43675043585825292774 >>> fac2(20) 3715891200.0 Double factorials appear, among other things, in series expansions of Gaussian functions and the error function. Infinite series include:: >>> nsum(lambda k: 1/fac2(k), [0, inf]) 3.05940740534258 >>> sqrt(e)*(1+sqrt(pi/2)*erf(sqrt(2)/2)) 3.05940740534258 >>> nsum(lambda k: 2**k/fac2(2*k-1), [1, inf]) 4.06015693855741 >>> e * erf(1) * sqrt(pi) 4.06015693855741 A beautiful Ramanujan sum:: >>> nsum(lambda k: (-1)**k*(fac2(2*k-1)/fac2(2*k))**3, [0,inf]) 0.90917279454693 >>> (gamma('9/8')/gamma('5/4')/gamma('7/8'))**2 0.90917279454693 **References** 1. http://functions.wolfram.com/GammaBetaErf/Factorial2/27/01/0002/ 2. http://mathworld.wolfram.com/DoubleFactorial.html """ hyper = r""" Evaluates the generalized hypergeometric function .. math :: \,_pF_q(a_1,\ldots,a_p; b_1,\ldots,b_q; z) = \sum_{n=0}^\infty \frac{(a_1)_n (a_2)_n \ldots (a_p)_n} {(b_1)_n(b_2)_n\ldots(b_q)_n} \frac{z^n}{n!} where `(x)_n` denotes the rising factorial (see :func:`~mpmath.rf`). The parameters lists ``a_s`` and ``b_s`` may contain integers, real numbers, complex numbers, as well as exact fractions given in the form of tuples `(p, q)`. :func:`~mpmath.hyper` is optimized to handle integers and fractions more efficiently than arbitrary floating-point parameters (since rational parameters are by far the most common). **Examples** Verifying that :func:`~mpmath.hyper` gives the sum in the definition, by comparison with :func:`~mpmath.nsum`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a,b,c,d = 2,3,4,5 >>> x = 0.25 >>> hyper([a,b],[c,d],x) 1.078903941164934876086237 >>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)*x**n/fac(n) >>> nsum(fn, [0, inf]) 1.078903941164934876086237 The parameters can be any combination of integers, fractions, floats and complex numbers:: >>> a, b, c, d, e = 1, (-1,2), pi, 3+4j, (2,3) >>> x = 0.2j >>> hyper([a,b],[c,d,e],x) (0.9923571616434024810831887 - 0.005753848733883879742993122j) >>> b, e = -0.5, mpf(2)/3 >>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)/rf(e,n)*x**n/fac(n) >>> nsum(fn, [0, inf]) (0.9923571616434024810831887 - 0.005753848733883879742993122j) The `\,_0F_0` and `\,_1F_0` series are just elementary functions:: >>> a, z = sqrt(2), +pi >>> hyper([],[],z) 23.14069263277926900572909 >>> exp(z) 23.14069263277926900572909 >>> hyper([a],[],z) (-0.09069132879922920160334114 + 0.3283224323946162083579656j) >>> (1-z)**(-a) (-0.09069132879922920160334114 + 0.3283224323946162083579656j) If any `a_k` coefficient is a nonpositive integer, the series terminates into a finite polynomial:: >>> hyper([1,1,1,-3],[2,5],1) 0.7904761904761904761904762 >>> identify(_) '(83/105)' If any `b_k` is a nonpositive integer, the function is undefined (unless the series terminates before the division by zero occurs):: >>> hyper([1,1,1,-3],[-2,5],1) Traceback (most recent call last): ... ZeroDivisionError: pole in hypergeometric series >>> hyper([1,1,1,-1],[-2,5],1) 1.1 Except for polynomial cases, the radius of convergence `R` of the hypergeometric series is either `R = \infty` (if `p \le q`), `R = 1` (if `p = q+1`), or `R = 0` (if `p > q+1`). The analytic continuations of the functions with `p = q+1`, i.e. `\,_2F_1`, `\,_3F_2`, `\,_4F_3`, etc, are all implemented and therefore these functions can be evaluated for `|z| \ge 1`. The shortcuts :func:`~mpmath.hyp2f1`, :func:`~mpmath.hyp3f2` are available to handle the most common cases (see their documentation), but functions of higher degree are also supported via :func:`~mpmath.hyper`:: >>> hyper([1,2,3,4], [5,6,7], 1) # 4F3 at finite-valued branch point 1.141783505526870731311423 >>> hyper([4,5,6,7], [1,2,3], 1) # 4F3 at pole +inf >>> hyper([1,2,3,4,5], [6,7,8,9], 10) # 5F4 (1.543998916527972259717257 - 0.5876309929580408028816365j) >>> hyper([1,2,3,4,5,6], [7,8,9,10,11], 1j) # 6F5 (0.9996565821853579063502466 + 0.0129721075905630604445669j) Near `z = 1` with noninteger parameters:: >>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','41/8'], 1) 2.219433352235586121250027 >>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], 1) +inf >>> eps1 = extradps(6)(lambda: 1 - mpf('1e-6'))() >>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], eps1) 2923978034.412973409330956 Please note that, as currently implemented, evaluation of `\,_pF_{p-1}` with `p \ge 3` may be slow or inaccurate when `|z-1|` is small, for some parameter values. Evaluation may be aborted if convergence appears to be too slow. The optional ``maxterms`` (limiting the number of series terms) and ``maxprec`` (limiting the internal precision) keyword arguments can be used to control evaluation:: >>> hyper([1,2,3], [4,5,6], 10000) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. >>> hyper([1,2,3], [4,5,6], 10000, maxterms=10**6) 7.622806053177969474396918e+4310 Additional options include ``force_series`` (which forces direct use of a hypergeometric series even if another evaluation method might work better) and ``asymp_tol`` which controls the target tolerance for using asymptotic series. When `p > q+1`, ``hyper`` computes the (iterated) Borel sum of the divergent series. For `\,_2F_0` the Borel sum has an analytic solution and can be computed efficiently (see :func:`~mpmath.hyp2f0`). For higher degrees, the functions is evaluated first by attempting to sum it directly as an asymptotic series (this only works for tiny `|z|`), and then by evaluating the Borel regularized sum using numerical integration. Except for special parameter combinations, this can be extremely slow. >>> hyper([1,1], [], 0.5) # regularization of 2F0 (1.340965419580146562086448 + 0.8503366631752726568782447j) >>> hyper([1,1,1,1], [1], 0.5) # regularization of 4F1 (1.108287213689475145830699 + 0.5327107430640678181200491j) With the following magnitude of argument, the asymptotic series for `\,_3F_1` gives only a few digits. Using Borel summation, ``hyper`` can produce a value with full accuracy:: >>> mp.dps = 15 >>> hyper([2,0.5,4], [5.25], '0.08', force_series=True) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. >>> hyper([2,0.5,4], [5.25], '0.08', asymp_tol=1e-4) 1.0725535790737 >>> hyper([2,0.5,4], [5.25], '0.08') (1.07269542893559 + 5.54668863216891e-5j) >>> hyper([2,0.5,4], [5.25], '-0.08', asymp_tol=1e-4) 0.946344925484879 >>> hyper([2,0.5,4], [5.25], '-0.08') 0.946312503737771 >>> mp.dps = 25 >>> hyper([2,0.5,4], [5.25], '-0.08') 0.9463125037377662296700858 Note that with the positive `z` value, there is a complex part in the correct result, which falls below the tolerance of the asymptotic series. By default, a parameter that appears in both ``a_s`` and ``b_s`` will be removed unless it is a nonpositive integer. This generally speeds up evaluation by producing a hypergeometric function of lower order. This optimization can be disabled by passing ``eliminate=False``. >>> hyper([1,2,3], [4,5,3], 10000) 1.268943190440206905892212e+4321 >>> hyper([1,2,3], [4,5,3], 10000, eliminate=False) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. >>> hyper([1,2,3], [4,5,3], 10000, eliminate=False, maxterms=10**6) 1.268943190440206905892212e+4321 If a nonpositive integer `-n` appears in both ``a_s`` and ``b_s``, this parameter cannot be unambiguously removed since it creates a term 0 / 0. In this case the hypergeometric series is understood to terminate before the division by zero occurs. This convention is consistent with Mathematica. An alternative convention of eliminating the parameters can be toggled with ``eliminate_all=True``: >>> hyper([2,-1], [-1], 3) 7.0 >>> hyper([2,-1], [-1], 3, eliminate_all=True) 0.25 >>> hyper([2], [], 3) 0.25 """ hypercomb = r""" Computes a weighted combination of hypergeometric functions .. math :: \sum_{r=1}^N \left[ \prod_{k=1}^{l_r} {w_{r,k}}^{c_{r,k}} \frac{\prod_{k=1}^{m_r} \Gamma(\alpha_{r,k})}{\prod_{k=1}^{n_r} \Gamma(\beta_{r,k})} \,_{p_r}F_{q_r}(a_{r,1},\ldots,a_{r,p}; b_{r,1}, \ldots, b_{r,q}; z_r)\right]. Typically the parameters are linear combinations of a small set of base parameters; :func:`~mpmath.hypercomb` permits computing a correct value in the case that some of the `\alpha`, `\beta`, `b` turn out to be nonpositive integers, or if division by zero occurs for some `w^c`, assuming that there are opposing singularities that cancel out. The limit is computed by evaluating the function with the base parameters perturbed, at a higher working precision. The first argument should be a function that takes the perturbable base parameters ``params`` as input and returns `N` tuples ``(w, c, alpha, beta, a, b, z)``, where the coefficients ``w``, ``c``, gamma factors ``alpha``, ``beta``, and hypergeometric coefficients ``a``, ``b`` each should be lists of numbers, and ``z`` should be a single number. **Examples** The following evaluates .. math :: (a-1) \frac{\Gamma(a-3)}{\Gamma(a-4)} \,_1F_1(a,a-1,z) = e^z(a-4)(a+z-1) with `a=1, z=3`. There is a zero factor, two gamma function poles, and the 1F1 function is singular; all singularities cancel out to give a finite value:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> hypercomb(lambda a: [([a-1],[1],[a-3],[a-4],[a],[a-1],3)], [1]) -180.769832308689 >>> -9*exp(3) -180.769832308689 """ hyp0f1 = r""" Gives the hypergeometric function `\,_0F_1`, sometimes known as the confluent limit function, defined as .. math :: \,_0F_1(a,z) = \sum_{k=0}^{\infty} \frac{1}{(a)_k} \frac{z^k}{k!}. This function satisfies the differential equation `z f''(z) + a f'(z) = f(z)`, and is related to the Bessel function of the first kind (see :func:`~mpmath.besselj`). ``hyp0f1(a,z)`` is equivalent to ``hyper([],[a],z)``; see documentation for :func:`~mpmath.hyper` for more information. **Examples** Evaluation for arbitrary arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hyp0f1(2, 0.25) 1.130318207984970054415392 >>> hyp0f1((1,2), 1234567) 6.27287187546220705604627e+964 >>> hyp0f1(3+4j, 1000000j) (3.905169561300910030267132e+606 + 3.807708544441684513934213e+606j) Evaluation is supported for arbitrarily large values of `z`, using asymptotic expansions:: >>> hyp0f1(1, 10**50) 2.131705322874965310390701e+8685889638065036553022565 >>> hyp0f1(1, -10**50) 1.115945364792025420300208e-13 Verifying the differential equation:: >>> a = 2.5 >>> f = lambda z: hyp0f1(a,z) >>> for z in [0, 10, 3+4j]: ... chop(z*diff(f,z,2) + a*diff(f,z) - f(z)) ... 0.0 0.0 0.0 """ hyp1f1 = r""" Gives the confluent hypergeometric function of the first kind, .. math :: \,_1F_1(a,b,z) = \sum_{k=0}^{\infty} \frac{(a)_k}{(b)_k} \frac{z^k}{k!}, also known as Kummer's function and sometimes denoted by `M(a,b,z)`. This function gives one solution to the confluent (Kummer's) differential equation .. math :: z f''(z) + (b-z) f'(z) - af(z) = 0. A second solution is given by the `U` function; see :func:`~mpmath.hyperu`. Solutions are also given in an alternate form by the Whittaker functions (:func:`~mpmath.whitm`, :func:`~mpmath.whitw`). ``hyp1f1(a,b,z)`` is equivalent to ``hyper([a],[b],z)``; see documentation for :func:`~mpmath.hyper` for more information. **Examples** Evaluation for real and complex values of the argument `z`, with fixed parameters `a = 2, b = -1/3`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hyp1f1(2, (-1,3), 3.25) -2815.956856924817275640248 >>> hyp1f1(2, (-1,3), -3.25) -1.145036502407444445553107 >>> hyp1f1(2, (-1,3), 1000) -8.021799872770764149793693e+441 >>> hyp1f1(2, (-1,3), -1000) 0.000003131987633006813594535331 >>> hyp1f1(2, (-1,3), 100+100j) (-3.189190365227034385898282e+48 - 1.106169926814270418999315e+49j) Parameters may be complex:: >>> hyp1f1(2+3j, -1+j, 10j) (261.8977905181045142673351 + 160.8930312845682213562172j) Arbitrarily large values of `z` are supported:: >>> hyp1f1(3, 4, 10**20) 3.890569218254486878220752e+43429448190325182745 >>> hyp1f1(3, 4, -10**20) 6.0e-60 >>> hyp1f1(3, 4, 10**20*j) (-1.935753855797342532571597e-20 - 2.291911213325184901239155e-20j) Verifying the differential equation:: >>> a, b = 1.5, 2 >>> f = lambda z: hyp1f1(a,b,z) >>> for z in [0, -10, 3, 3+4j]: ... chop(z*diff(f,z,2) + (b-z)*diff(f,z) - a*f(z)) ... 0.0 0.0 0.0 0.0 An integral representation:: >>> a, b = 1.5, 3 >>> z = 1.5 >>> hyp1f1(a,b,z) 2.269381460919952778587441 >>> g = lambda t: exp(z*t)*t**(a-1)*(1-t)**(b-a-1) >>> gammaprod([b],[a,b-a])*quad(g, [0,1]) 2.269381460919952778587441 """ hyp1f2 = r""" Gives the hypergeometric function `\,_1F_2(a_1,a_2;b_1,b_2; z)`. The call ``hyp1f2(a1,b1,b2,z)`` is equivalent to ``hyper([a1],[b1,b2],z)``. Evaluation works for complex and arbitrarily large arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a, b, c = 1.5, (-1,3), 2.25 >>> hyp1f2(a, b, c, 10**20) -1.159388148811981535941434e+8685889639 >>> hyp1f2(a, b, c, -10**20) -12.60262607892655945795907 >>> hyp1f2(a, b, c, 10**20*j) (4.237220401382240876065501e+6141851464 - 2.950930337531768015892987e+6141851464j) >>> hyp1f2(2+3j, -2j, 0.5j, 10-20j) (135881.9905586966432662004 - 86681.95885418079535738828j) """ hyp2f2 = r""" Gives the hypergeometric function `\,_2F_2(a_1,a_2;b_1,b_2; z)`. The call ``hyp2f2(a1,a2,b1,b2,z)`` is equivalent to ``hyper([a1,a2],[b1,b2],z)``. Evaluation works for complex and arbitrarily large arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a, b, c, d = 1.5, (-1,3), 2.25, 4 >>> hyp2f2(a, b, c, d, 10**20) -5.275758229007902299823821e+43429448190325182663 >>> hyp2f2(a, b, c, d, -10**20) 2561445.079983207701073448 >>> hyp2f2(a, b, c, d, 10**20*j) (2218276.509664121194836667 - 1280722.539991603850462856j) >>> hyp2f2(2+3j, -2j, 0.5j, 4j, 10-20j) (80500.68321405666957342788 - 20346.82752982813540993502j) """ hyp2f3 = r""" Gives the hypergeometric function `\,_2F_3(a_1,a_2;b_1,b_2,b_3; z)`. The call ``hyp2f3(a1,a2,b1,b2,b3,z)`` is equivalent to ``hyper([a1,a2],[b1,b2,b3],z)``. Evaluation works for arbitrarily large arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a1,a2,b1,b2,b3 = 1.5, (-1,3), 2.25, 4, (1,5) >>> hyp2f3(a1,a2,b1,b2,b3,10**20) -4.169178177065714963568963e+8685889590 >>> hyp2f3(a1,a2,b1,b2,b3,-10**20) 7064472.587757755088178629 >>> hyp2f3(a1,a2,b1,b2,b3,10**20*j) (-5.163368465314934589818543e+6141851415 + 1.783578125755972803440364e+6141851416j) >>> hyp2f3(2+3j, -2j, 0.5j, 4j, -1-j, 10-20j) (-2280.938956687033150740228 + 13620.97336609573659199632j) >>> hyp2f3(2+3j, -2j, 0.5j, 4j, -1-j, 10000000-20000000j) (4.849835186175096516193e+3504 - 3.365981529122220091353633e+3504j) """ hyp2f1 = r""" Gives the Gauss hypergeometric function `\,_2F_1` (often simply referred to as *the* hypergeometric function), defined for `|z| < 1` as .. math :: \,_2F_1(a,b,c,z) = \sum_{k=0}^{\infty} \frac{(a)_k (b)_k}{(c)_k} \frac{z^k}{k!}. and for `|z| \ge 1` by analytic continuation, with a branch cut on `(1, \infty)` when necessary. Special cases of this function include many of the orthogonal polynomials as well as the incomplete beta function and other functions. Properties of the Gauss hypergeometric function are documented comprehensively in many references, for example Abramowitz & Stegun, section 15. The implementation supports the analytic continuation as well as evaluation close to the unit circle where `|z| \approx 1`. The syntax ``hyp2f1(a,b,c,z)`` is equivalent to ``hyper([a,b],[c],z)``. **Examples** Evaluation with `z` inside, outside and on the unit circle, for fixed parameters:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hyp2f1(2, (1,2), 4, 0.75) 1.303703703703703703703704 >>> hyp2f1(2, (1,2), 4, -1.75) 0.7431290566046919177853916 >>> hyp2f1(2, (1,2), 4, 1.75) (1.418075801749271137026239 - 1.114976146679907015775102j) >>> hyp2f1(2, (1,2), 4, 1) 1.6 >>> hyp2f1(2, (1,2), 4, -1) 0.8235498012182875315037882 >>> hyp2f1(2, (1,2), 4, j) (0.9144026291433065674259078 + 0.2050415770437884900574923j) >>> hyp2f1(2, (1,2), 4, 2+j) (0.9274013540258103029011549 + 0.7455257875808100868984496j) >>> hyp2f1(2, (1,2), 4, 0.25j) (0.9931169055799728251931672 + 0.06154836525312066938147793j) Evaluation with complex parameter values:: >>> hyp2f1(1+j, 0.75, 10j, 1+5j) (0.8834833319713479923389638 + 0.7053886880648105068343509j) Evaluation with `z = 1`:: >>> hyp2f1(-2.5, 3.5, 1.5, 1) 0.0 >>> hyp2f1(-2.5, 3, 4, 1) 0.06926406926406926406926407 >>> hyp2f1(2, 3, 4, 1) +inf Evaluation for huge arguments:: >>> hyp2f1((-1,3), 1.75, 4, '1e100') (7.883714220959876246415651e+32 + 1.365499358305579597618785e+33j) >>> hyp2f1((-1,3), 1.75, 4, '1e1000000') (7.883714220959876246415651e+333332 + 1.365499358305579597618785e+333333j) >>> hyp2f1((-1,3), 1.75, 4, '1e1000000j') (1.365499358305579597618785e+333333 - 7.883714220959876246415651e+333332j) An integral representation:: >>> a,b,c,z = -0.5, 1, 2.5, 0.25 >>> g = lambda t: t**(b-1) * (1-t)**(c-b-1) * (1-t*z)**(-a) >>> gammaprod([c],[b,c-b]) * quad(g, [0,1]) 0.9480458814362824478852618 >>> hyp2f1(a,b,c,z) 0.9480458814362824478852618 Verifying the hypergeometric differential equation:: >>> f = lambda z: hyp2f1(a,b,c,z) >>> chop(z*(1-z)*diff(f,z,2) + (c-(a+b+1)*z)*diff(f,z) - a*b*f(z)) 0.0 """ hyp3f2 = r""" Gives the generalized hypergeometric function `\,_3F_2`, defined for `|z| < 1` as .. math :: \,_3F_2(a_1,a_2,a_3,b_1,b_2,z) = \sum_{k=0}^{\infty} \frac{(a_1)_k (a_2)_k (a_3)_k}{(b_1)_k (b_2)_k} \frac{z^k}{k!}. and for `|z| \ge 1` by analytic continuation. The analytic structure of this function is similar to that of `\,_2F_1`, generally with a singularity at `z = 1` and a branch cut on `(1, \infty)`. Evaluation is supported inside, on, and outside the circle of convergence `|z| = 1`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hyp3f2(1,2,3,4,5,0.25) 1.083533123380934241548707 >>> hyp3f2(1,2+2j,3,4,5,-10+10j) (0.1574651066006004632914361 - 0.03194209021885226400892963j) >>> hyp3f2(1,2,3,4,5,-10) 0.3071141169208772603266489 >>> hyp3f2(1,2,3,4,5,10) (-0.4857045320523947050581423 - 0.5988311440454888436888028j) >>> hyp3f2(0.25,1,1,2,1.5,1) 1.157370995096772047567631 >>> (8-pi-2*ln2)/3 1.157370995096772047567631 >>> hyp3f2(1+j,0.5j,2,1,-2j,-1) (1.74518490615029486475959 + 0.1454701525056682297614029j) >>> hyp3f2(1+j,0.5j,2,1,-2j,sqrt(j)) (0.9829816481834277511138055 - 0.4059040020276937085081127j) >>> hyp3f2(-3,2,1,-5,4,1) 1.41 >>> hyp3f2(-3,2,1,-5,4,2) 2.12 Evaluation very close to the unit circle:: >>> hyp3f2(1,2,3,4,5,'1.0001') (1.564877796743282766872279 - 3.76821518787438186031973e-11j) >>> hyp3f2(1,2,3,4,5,'1+0.0001j') (1.564747153061671573212831 + 0.0001305757570366084557648482j) >>> hyp3f2(1,2,3,4,5,'0.9999') 1.564616644881686134983664 >>> hyp3f2(1,2,3,4,5,'-0.9999') 0.7823896253461678060196207 .. note :: Evaluation for `|z-1|` small can currently be inaccurate or slow for some parameter combinations. For various parameter combinations, `\,_3F_2` admits representation in terms of hypergeometric functions of lower degree, or in terms of simpler functions:: >>> for a, b, z in [(1,2,-1), (2,0.5,1)]: ... hyp2f1(a,b,a+b+0.5,z)**2 ... hyp3f2(2*a,a+b,2*b,a+b+0.5,2*a+2*b,z) ... 0.4246104461966439006086308 0.4246104461966439006086308 7.111111111111111111111111 7.111111111111111111111111 >>> z = 2+3j >>> hyp3f2(0.5,1,1.5,2,2,z) (0.7621440939243342419729144 + 0.4249117735058037649915723j) >>> 4*(pi-2*ellipe(z))/(pi*z) (0.7621440939243342419729144 + 0.4249117735058037649915723j) """ hyperu = r""" Gives the Tricomi confluent hypergeometric function `U`, also known as the Kummer or confluent hypergeometric function of the second kind. This function gives a second linearly independent solution to the confluent hypergeometric differential equation (the first is provided by `\,_1F_1` -- see :func:`~mpmath.hyp1f1`). **Examples** Evaluation for arbitrary complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hyperu(2,3,4) 0.0625 >>> hyperu(0.25, 5, 1000) 0.1779949416140579573763523 >>> hyperu(0.25, 5, -1000) (0.1256256609322773150118907 - 0.1256256609322773150118907j) The `U` function may be singular at `z = 0`:: >>> hyperu(1.5, 2, 0) +inf >>> hyperu(1.5, -2, 0) 0.1719434921288400112603671 Verifying the differential equation:: >>> a, b = 1.5, 2 >>> f = lambda z: hyperu(a,b,z) >>> for z in [-10, 3, 3+4j]: ... chop(z*diff(f,z,2) + (b-z)*diff(f,z) - a*f(z)) ... 0.0 0.0 0.0 An integral representation:: >>> a,b,z = 2, 3.5, 4.25 >>> hyperu(a,b,z) 0.06674960718150520648014567 >>> quad(lambda t: exp(-z*t)*t**(a-1)*(1+t)**(b-a-1),[0,inf]) / gamma(a) 0.06674960718150520648014567 [1] http://people.math.sfu.ca/~cbm/aands/page_504.htm """ hyp2f0 = r""" Gives the hypergeometric function `\,_2F_0`, defined formally by the series .. math :: \,_2F_0(a,b;;z) = \sum_{n=0}^{\infty} (a)_n (b)_n \frac{z^n}{n!}. This series usually does not converge. For small enough `z`, it can be viewed as an asymptotic series that may be summed directly with an appropriate truncation. When this is not the case, :func:`~mpmath.hyp2f0` gives a regularized sum, or equivalently, it uses a representation in terms of the hypergeometric U function [1]. The series also converges when either `a` or `b` is a nonpositive integer, as it then terminates into a polynomial after `-a` or `-b` terms. **Examples** Evaluation is supported for arbitrary complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hyp2f0((2,3), 1.25, -100) 0.07095851870980052763312791 >>> hyp2f0((2,3), 1.25, 100) (-0.03254379032170590665041131 + 0.07269254613282301012735797j) >>> hyp2f0(-0.75, 1-j, 4j) (-0.3579987031082732264862155 - 3.052951783922142735255881j) Even with real arguments, the regularized value of 2F0 is often complex-valued, but the imaginary part decreases exponentially as `z \to 0`. In the following example, the first call uses complex evaluation while the second has a small enough `z` to evaluate using the direct series and thus the returned value is strictly real (this should be taken to indicate that the imaginary part is less than ``eps``):: >>> mp.dps = 15 >>> hyp2f0(1.5, 0.5, 0.05) (1.04166637647907 + 8.34584913683906e-8j) >>> hyp2f0(1.5, 0.5, 0.0005) 1.00037535207621 The imaginary part can be retrieved by increasing the working precision:: >>> mp.dps = 80 >>> nprint(hyp2f0(1.5, 0.5, 0.009).imag) 1.23828e-46 In the polynomial case (the series terminating), 2F0 can evaluate exactly:: >>> mp.dps = 15 >>> hyp2f0(-6,-6,2) 291793.0 >>> identify(hyp2f0(-2,1,0.25)) '(5/8)' The coefficients of the polynomials can be recovered using Taylor expansion:: >>> nprint(taylor(lambda x: hyp2f0(-3,0.5,x), 0, 10)) [1.0, -1.5, 2.25, -1.875, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] >>> nprint(taylor(lambda x: hyp2f0(-4,0.5,x), 0, 10)) [1.0, -2.0, 4.5, -7.5, 6.5625, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] [1] http://people.math.sfu.ca/~cbm/aands/page_504.htm """ gammainc = r""" ``gammainc(z, a=0, b=inf)`` computes the (generalized) incomplete gamma function with integration limits `[a, b]`: .. math :: \Gamma(z,a,b) = \int_a^b t^{z-1} e^{-t} \, dt The generalized incomplete gamma function reduces to the following special cases when one or both endpoints are fixed: * `\Gamma(z,0,\infty)` is the standard ("complete") gamma function, `\Gamma(z)` (available directly as the mpmath function :func:`~mpmath.gamma`) * `\Gamma(z,a,\infty)` is the "upper" incomplete gamma function, `\Gamma(z,a)` * `\Gamma(z,0,b)` is the "lower" incomplete gamma function, `\gamma(z,b)`. Of course, we have `\Gamma(z,0,x) + \Gamma(z,x,\infty) = \Gamma(z)` for all `z` and `x`. Note however that some authors reverse the order of the arguments when defining the lower and upper incomplete gamma function, so one should be careful to get the correct definition. If also given the keyword argument ``regularized=True``, :func:`~mpmath.gammainc` computes the "regularized" incomplete gamma function .. math :: P(z,a,b) = \frac{\Gamma(z,a,b)}{\Gamma(z)}. **Examples** We can compare with numerical quadrature to verify that :func:`~mpmath.gammainc` computes the integral in the definition:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> gammainc(2+3j, 4, 10) (0.00977212668627705160602312 - 0.0770637306312989892451977j) >>> quad(lambda t: t**(2+3j-1) * exp(-t), [4, 10]) (0.00977212668627705160602312 - 0.0770637306312989892451977j) Argument symmetries follow directly from the integral definition:: >>> gammainc(3, 4, 5) + gammainc(3, 5, 4) 0.0 >>> gammainc(3,0,2) + gammainc(3,2,4); gammainc(3,0,4) 1.523793388892911312363331 1.523793388892911312363331 >>> findroot(lambda z: gammainc(2,z,3), 1) 3.0 Evaluation for arbitrarily large arguments:: >>> gammainc(10, 100) 4.083660630910611272288592e-26 >>> gammainc(10, 10000000000000000) 5.290402449901174752972486e-4342944819032375 >>> gammainc(3+4j, 1000000+1000000j) (-1.257913707524362408877881e-434284 + 2.556691003883483531962095e-434284j) Evaluation of a generalized incomplete gamma function automatically chooses the representation that gives a more accurate result, depending on which parameter is larger:: >>> gammainc(10000000, 3) - gammainc(10000000, 2) # Bad 0.0 >>> gammainc(10000000, 2, 3) # Good 1.755146243738946045873491e+4771204 >>> gammainc(2, 0, 100000001) - gammainc(2, 0, 100000000) # Bad 0.0 >>> gammainc(2, 100000000, 100000001) # Good 4.078258353474186729184421e-43429441 The incomplete gamma functions satisfy simple recurrence relations:: >>> mp.dps = 25 >>> z, a = mpf(3.5), mpf(2) >>> gammainc(z+1, a); z*gammainc(z,a) + a**z*exp(-a) 10.60130296933533459267329 10.60130296933533459267329 >>> gammainc(z+1,0,a); z*gammainc(z,0,a) - a**z*exp(-a) 1.030425427232114336470932 1.030425427232114336470932 Evaluation at integers and poles:: >>> gammainc(-3, -4, -5) (-0.2214577048967798566234192 + 0.0j) >>> gammainc(-3, 0, 5) +inf If `z` is an integer, the recurrence reduces the incomplete gamma function to `P(a) \exp(-a) + Q(b) \exp(-b)` where `P` and `Q` are polynomials:: >>> gammainc(1, 2); exp(-2) 0.1353352832366126918939995 0.1353352832366126918939995 >>> mp.dps = 50 >>> identify(gammainc(6, 1, 2), ['exp(-1)', 'exp(-2)']) '(326*exp(-1) + (-872)*exp(-2))' The incomplete gamma functions reduce to functions such as the exponential integral Ei and the error function for special arguments:: >>> mp.dps = 25 >>> gammainc(0, 4); -ei(-4) 0.00377935240984890647887486 0.00377935240984890647887486 >>> gammainc(0.5, 0, 2); sqrt(pi)*erf(sqrt(2)) 1.691806732945198336509541 1.691806732945198336509541 """ erf = r""" Computes the error function, `\mathrm{erf}(x)`. The error function is the normalized antiderivative of the Gaussian function `\exp(-t^2)`. More precisely, .. math:: \mathrm{erf}(x) = \frac{2}{\sqrt \pi} \int_0^x \exp(-t^2) \,dt **Basic examples** Simple values and limits include:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> erf(0) 0.0 >>> erf(1) 0.842700792949715 >>> erf(-1) -0.842700792949715 >>> erf(inf) 1.0 >>> erf(-inf) -1.0 For large real `x`, `\mathrm{erf}(x)` approaches 1 very rapidly:: >>> erf(3) 0.999977909503001 >>> erf(5) 0.999999999998463 The error function is an odd function:: >>> nprint(chop(taylor(erf, 0, 5))) [0.0, 1.12838, 0.0, -0.376126, 0.0, 0.112838] :func:`~mpmath.erf` implements arbitrary-precision evaluation and supports complex numbers:: >>> mp.dps = 50 >>> erf(0.5) 0.52049987781304653768274665389196452873645157575796 >>> mp.dps = 25 >>> erf(1+j) (1.316151281697947644880271 + 0.1904534692378346862841089j) Evaluation is supported for large arguments:: >>> mp.dps = 25 >>> erf('1e1000') 1.0 >>> erf('-1e1000') -1.0 >>> erf('1e-1000') 1.128379167095512573896159e-1000 >>> erf('1e7j') (0.0 + 8.593897639029319267398803e+43429448190317j) >>> erf('1e7+1e7j') (0.9999999858172446172631323 + 3.728805278735270407053139e-8j) **Related functions** See also :func:`~mpmath.erfc`, which is more accurate for large `x`, and :func:`~mpmath.erfi` which gives the antiderivative of `\exp(t^2)`. The Fresnel integrals :func:`~mpmath.fresnels` and :func:`~mpmath.fresnelc` are also related to the error function. """ erfc = r""" Computes the complementary error function, `\mathrm{erfc}(x) = 1-\mathrm{erf}(x)`. This function avoids cancellation that occurs when naively computing the complementary error function as ``1-erf(x)``:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> 1 - erf(10) 0.0 >>> erfc(10) 2.08848758376254e-45 :func:`~mpmath.erfc` works accurately even for ludicrously large arguments:: >>> erfc(10**10) 4.3504398860243e-43429448190325182776 Complex arguments are supported:: >>> erfc(500+50j) (1.19739830969552e-107492 + 1.46072418957528e-107491j) """ erfi = r""" Computes the imaginary error function, `\mathrm{erfi}(x)`. The imaginary error function is defined in analogy with the error function, but with a positive sign in the integrand: .. math :: \mathrm{erfi}(x) = \frac{2}{\sqrt \pi} \int_0^x \exp(t^2) \,dt Whereas the error function rapidly converges to 1 as `x` grows, the imaginary error function rapidly diverges to infinity. The functions are related as `\mathrm{erfi}(x) = -i\,\mathrm{erf}(ix)` for all complex numbers `x`. **Examples** Basic values and limits:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> erfi(0) 0.0 >>> erfi(1) 1.65042575879754 >>> erfi(-1) -1.65042575879754 >>> erfi(inf) +inf >>> erfi(-inf) -inf Note the symmetry between erf and erfi:: >>> erfi(3j) (0.0 + 0.999977909503001j) >>> erf(3) 0.999977909503001 >>> erf(1+2j) (-0.536643565778565 - 5.04914370344703j) >>> erfi(2+1j) (-5.04914370344703 - 0.536643565778565j) Large arguments are supported:: >>> erfi(1000) 1.71130938718796e+434291 >>> erfi(10**10) 7.3167287567024e+43429448190325182754 >>> erfi(-10**10) -7.3167287567024e+43429448190325182754 >>> erfi(1000-500j) (2.49895233563961e+325717 + 2.6846779342253e+325717j) >>> erfi(100000j) (0.0 + 1.0j) >>> erfi(-100000j) (0.0 - 1.0j) """ erfinv = r""" Computes the inverse error function, satisfying .. math :: \mathrm{erf}(\mathrm{erfinv}(x)) = \mathrm{erfinv}(\mathrm{erf}(x)) = x. This function is defined only for `-1 \le x \le 1`. **Examples** Special values include:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> erfinv(0) 0.0 >>> erfinv(1) +inf >>> erfinv(-1) -inf The domain is limited to the standard interval:: >>> erfinv(2) Traceback (most recent call last): ... ValueError: erfinv(x) is defined only for -1 <= x <= 1 It is simple to check that :func:`~mpmath.erfinv` computes inverse values of :func:`~mpmath.erf` as promised:: >>> erf(erfinv(0.75)) 0.75 >>> erf(erfinv(-0.995)) -0.995 :func:`~mpmath.erfinv` supports arbitrary-precision evaluation:: >>> mp.dps = 50 >>> x = erf(2) >>> x 0.99532226501895273416206925636725292861089179704006 >>> erfinv(x) 2.0 A definite integral involving the inverse error function:: >>> mp.dps = 15 >>> quad(erfinv, [0, 1]) 0.564189583547756 >>> 1/sqrt(pi) 0.564189583547756 The inverse error function can be used to generate random numbers with a Gaussian distribution (although this is a relatively inefficient algorithm):: >>> nprint([erfinv(2*rand()-1) for n in range(6)]) # doctest: +SKIP [-0.586747, 1.10233, -0.376796, 0.926037, -0.708142, -0.732012] """ npdf = r""" ``npdf(x, mu=0, sigma=1)`` evaluates the probability density function of a normal distribution with mean value `\mu` and variance `\sigma^2`. Elementary properties of the probability distribution can be verified using numerical integration:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> quad(npdf, [-inf, inf]) 1.0 >>> quad(lambda x: npdf(x, 3), [3, inf]) 0.5 >>> quad(lambda x: npdf(x, 3, 2), [3, inf]) 0.5 See also :func:`~mpmath.ncdf`, which gives the cumulative distribution. """ ncdf = r""" ``ncdf(x, mu=0, sigma=1)`` evaluates the cumulative distribution function of a normal distribution with mean value `\mu` and variance `\sigma^2`. See also :func:`~mpmath.npdf`, which gives the probability density. Elementary properties include:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> ncdf(pi, mu=pi) 0.5 >>> ncdf(-inf) 0.0 >>> ncdf(+inf) 1.0 The cumulative distribution is the integral of the density function having identical mu and sigma:: >>> mp.dps = 15 >>> diff(ncdf, 2) 0.053990966513188 >>> npdf(2) 0.053990966513188 >>> diff(lambda x: ncdf(x, 1, 0.5), 0) 0.107981933026376 >>> npdf(0, 1, 0.5) 0.107981933026376 """ expint = r""" :func:`~mpmath.expint(n,z)` gives the generalized exponential integral or En-function, .. math :: \mathrm{E}_n(z) = \int_1^{\infty} \frac{e^{-zt}}{t^n} dt, where `n` and `z` may both be complex numbers. The case with `n = 1` is also given by :func:`~mpmath.e1`. **Examples** Evaluation at real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> expint(1, 6.25) 0.0002704758872637179088496194 >>> expint(-3, 2+3j) (0.00299658467335472929656159 + 0.06100816202125885450319632j) >>> expint(2+3j, 4-5j) (0.001803529474663565056945248 - 0.002235061547756185403349091j) At negative integer values of `n`, `E_n(z)` reduces to a rational-exponential function:: >>> f = lambda n, z: fac(n)*sum(z**k/fac(k-1) for k in range(1,n+2))/\ ... exp(z)/z**(n+2) >>> n = 3 >>> z = 1/pi >>> expint(-n,z) 584.2604820613019908668219 >>> f(n,z) 584.2604820613019908668219 >>> n = 5 >>> expint(-n,z) 115366.5762594725451811138 >>> f(n,z) 115366.5762594725451811138 """ e1 = r""" Computes the exponential integral `\mathrm{E}_1(z)`, given by .. math :: \mathrm{E}_1(z) = \int_z^{\infty} \frac{e^{-t}}{t} dt. This is equivalent to :func:`~mpmath.expint` with `n = 1`. **Examples** Two ways to evaluate this function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> e1(6.25) 0.0002704758872637179088496194 >>> expint(1,6.25) 0.0002704758872637179088496194 The E1-function is essentially the same as the Ei-function (:func:`~mpmath.ei`) with negated argument, except for an imaginary branch cut term:: >>> e1(2.5) 0.02491491787026973549562801 >>> -ei(-2.5) 0.02491491787026973549562801 >>> e1(-2.5) (-7.073765894578600711923552 - 3.141592653589793238462643j) >>> -ei(2.5) -7.073765894578600711923552 """ ei = r""" Computes the exponential integral or Ei-function, `\mathrm{Ei}(x)`. The exponential integral is defined as .. math :: \mathrm{Ei}(x) = \int_{-\infty\,}^x \frac{e^t}{t} \, dt. When the integration range includes `t = 0`, the exponential integral is interpreted as providing the Cauchy principal value. For real `x`, the Ei-function behaves roughly like `\mathrm{Ei}(x) \approx \exp(x) + \log(|x|)`. The Ei-function is related to the more general family of exponential integral functions denoted by `E_n`, which are available as :func:`~mpmath.expint`. **Basic examples** Some basic values and limits are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> ei(0) -inf >>> ei(1) 1.89511781635594 >>> ei(inf) +inf >>> ei(-inf) 0.0 For `x < 0`, the defining integral can be evaluated numerically as a reference:: >>> ei(-4) -0.00377935240984891 >>> quad(lambda t: exp(t)/t, [-inf, -4]) -0.00377935240984891 :func:`~mpmath.ei` supports complex arguments and arbitrary precision evaluation:: >>> mp.dps = 50 >>> ei(pi) 10.928374389331410348638445906907535171566338835056 >>> mp.dps = 25 >>> ei(3+4j) (-4.154091651642689822535359 + 4.294418620024357476985535j) **Related functions** The exponential integral is closely related to the logarithmic integral. See :func:`~mpmath.li` for additional information. The exponential integral is related to the hyperbolic and trigonometric integrals (see :func:`~mpmath.chi`, :func:`~mpmath.shi`, :func:`~mpmath.ci`, :func:`~mpmath.si`) similarly to how the ordinary exponential function is related to the hyperbolic and trigonometric functions:: >>> mp.dps = 15 >>> ei(3) 9.93383257062542 >>> chi(3) + shi(3) 9.93383257062542 >>> chop(ci(3j) - j*si(3j) - pi*j/2) 9.93383257062542 Beware that logarithmic corrections, as in the last example above, are required to obtain the correct branch in general. For details, see [1]. The exponential integral is also a special case of the hypergeometric function `\,_2F_2`:: >>> z = 0.6 >>> z*hyper([1,1],[2,2],z) + (ln(z)-ln(1/z))/2 + euler 0.769881289937359 >>> ei(z) 0.769881289937359 **References** 1. Relations between Ei and other functions: http://functions.wolfram.com/GammaBetaErf/ExpIntegralEi/27/01/ 2. Abramowitz & Stegun, section 5: http://people.math.sfu.ca/~cbm/aands/page_228.htm 3. Asymptotic expansion for Ei: http://mathworld.wolfram.com/En-Function.html """ li = r""" Computes the logarithmic integral or li-function `\mathrm{li}(x)`, defined by .. math :: \mathrm{li}(x) = \int_0^x \frac{1}{\log t} \, dt The logarithmic integral has a singularity at `x = 1`. Alternatively, ``li(x, offset=True)`` computes the offset logarithmic integral (used in number theory) .. math :: \mathrm{Li}(x) = \int_2^x \frac{1}{\log t} \, dt. These two functions are related via the simple identity `\mathrm{Li}(x) = \mathrm{li}(x) - \mathrm{li}(2)`. The logarithmic integral should also not be confused with the polylogarithm (also denoted by Li), which is implemented as :func:`~mpmath.polylog`. **Examples** Some basic values and limits:: >>> from mpmath import * >>> mp.dps = 30; mp.pretty = True >>> li(0) 0.0 >>> li(1) -inf >>> li(1) -inf >>> li(2) 1.04516378011749278484458888919 >>> findroot(li, 2) 1.45136923488338105028396848589 >>> li(inf) +inf >>> li(2, offset=True) 0.0 >>> li(1, offset=True) -inf >>> li(0, offset=True) -1.04516378011749278484458888919 >>> li(10, offset=True) 5.12043572466980515267839286347 The logarithmic integral can be evaluated for arbitrary complex arguments:: >>> mp.dps = 20 >>> li(3+4j) (3.1343755504645775265 + 2.6769247817778742392j) The logarithmic integral is related to the exponential integral:: >>> ei(log(3)) 2.1635885946671919729 >>> li(3) 2.1635885946671919729 The logarithmic integral grows like `O(x/\log(x))`:: >>> mp.dps = 15 >>> x = 10**100 >>> x/log(x) 4.34294481903252e+97 >>> li(x) 4.3619719871407e+97 The prime number theorem states that the number of primes less than `x` is asymptotic to `\mathrm{Li}(x)` (equivalently `\mathrm{li}(x)`). For example, it is known that there are exactly 1,925,320,391,606,803,968,923 prime numbers less than `10^{23}` [1]. The logarithmic integral provides a very accurate estimate:: >>> li(10**23, offset=True) 1.92532039161405e+21 A definite integral is:: >>> quad(li, [0, 1]) -0.693147180559945 >>> -ln(2) -0.693147180559945 **References** 1. http://mathworld.wolfram.com/PrimeCountingFunction.html 2. http://mathworld.wolfram.com/LogarithmicIntegral.html """ ci = r""" Computes the cosine integral, .. math :: \mathrm{Ci}(x) = -\int_x^{\infty} \frac{\cos t}{t}\,dt = \gamma + \log x + \int_0^x \frac{\cos t - 1}{t}\,dt **Examples** Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> ci(0) -inf >>> ci(1) 0.3374039229009681346626462 >>> ci(pi) 0.07366791204642548599010096 >>> ci(inf) 0.0 >>> ci(-inf) (0.0 + 3.141592653589793238462643j) >>> ci(2+3j) (1.408292501520849518759125 - 2.983617742029605093121118j) The cosine integral behaves roughly like the sinc function (see :func:`~mpmath.sinc`) for large real `x`:: >>> ci(10**10) -4.875060251748226537857298e-11 >>> sinc(10**10) -4.875060250875106915277943e-11 >>> chop(limit(ci, inf)) 0.0 It has infinitely many roots on the positive real axis:: >>> findroot(ci, 1) 0.6165054856207162337971104 >>> findroot(ci, 2) 3.384180422551186426397851 Evaluation is supported for `z` anywhere in the complex plane:: >>> ci(10**6*(1+j)) (4.449410587611035724984376e+434287 + 9.75744874290013526417059e+434287j) We can evaluate the defining integral as a reference:: >>> mp.dps = 15 >>> -quadosc(lambda t: cos(t)/t, [5, inf], omega=1) -0.190029749656644 >>> ci(5) -0.190029749656644 Some infinite series can be evaluated using the cosine integral:: >>> nsum(lambda k: (-1)**k/(fac(2*k)*(2*k)), [1,inf]) -0.239811742000565 >>> ci(1) - euler -0.239811742000565 """ si = r""" Computes the sine integral, .. math :: \mathrm{Si}(x) = \int_0^x \frac{\sin t}{t}\,dt. The sine integral is thus the antiderivative of the sinc function (see :func:`~mpmath.sinc`). **Examples** Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> si(0) 0.0 >>> si(1) 0.9460830703671830149413533 >>> si(-1) -0.9460830703671830149413533 >>> si(pi) 1.851937051982466170361053 >>> si(inf) 1.570796326794896619231322 >>> si(-inf) -1.570796326794896619231322 >>> si(2+3j) (4.547513889562289219853204 + 1.399196580646054789459839j) The sine integral approaches `\pi/2` for large real `x`:: >>> si(10**10) 1.570796326707584656968511 >>> pi/2 1.570796326794896619231322 Evaluation is supported for `z` anywhere in the complex plane:: >>> si(10**6*(1+j)) (-9.75744874290013526417059e+434287 + 4.449410587611035724984376e+434287j) We can evaluate the defining integral as a reference:: >>> mp.dps = 15 >>> quad(sinc, [0, 5]) 1.54993124494467 >>> si(5) 1.54993124494467 Some infinite series can be evaluated using the sine integral:: >>> nsum(lambda k: (-1)**k/(fac(2*k+1)*(2*k+1)), [0,inf]) 0.946083070367183 >>> si(1) 0.946083070367183 """ chi = r""" Computes the hyperbolic cosine integral, defined in analogy with the cosine integral (see :func:`~mpmath.ci`) as .. math :: \mathrm{Chi}(x) = -\int_x^{\infty} \frac{\cosh t}{t}\,dt = \gamma + \log x + \int_0^x \frac{\cosh t - 1}{t}\,dt Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> chi(0) -inf >>> chi(1) 0.8378669409802082408946786 >>> chi(inf) +inf >>> findroot(chi, 0.5) 0.5238225713898644064509583 >>> chi(2+3j) (-0.1683628683277204662429321 + 2.625115880451325002151688j) Evaluation is supported for `z` anywhere in the complex plane:: >>> chi(10**6*(1+j)) (4.449410587611035724984376e+434287 - 9.75744874290013526417059e+434287j) """ shi = r""" Computes the hyperbolic sine integral, defined in analogy with the sine integral (see :func:`~mpmath.si`) as .. math :: \mathrm{Shi}(x) = \int_0^x \frac{\sinh t}{t}\,dt. Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> shi(0) 0.0 >>> shi(1) 1.057250875375728514571842 >>> shi(-1) -1.057250875375728514571842 >>> shi(inf) +inf >>> shi(2+3j) (-0.1931890762719198291678095 + 2.645432555362369624818525j) Evaluation is supported for `z` anywhere in the complex plane:: >>> shi(10**6*(1+j)) (4.449410587611035724984376e+434287 - 9.75744874290013526417059e+434287j) """ fresnels = r""" Computes the Fresnel sine integral .. math :: S(x) = \int_0^x \sin\left(\frac{\pi t^2}{2}\right) \,dt Note that some sources define this function without the normalization factor `\pi/2`. **Examples** Some basic values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> fresnels(0) 0.0 >>> fresnels(inf) 0.5 >>> fresnels(-inf) -0.5 >>> fresnels(1) 0.4382591473903547660767567 >>> fresnels(1+2j) (36.72546488399143842838788 + 15.58775110440458732748279j) Comparing with the definition:: >>> fresnels(3) 0.4963129989673750360976123 >>> quad(lambda t: sin(pi*t**2/2), [0,3]) 0.4963129989673750360976123 """ fresnelc = r""" Computes the Fresnel cosine integral .. math :: C(x) = \int_0^x \cos\left(\frac{\pi t^2}{2}\right) \,dt Note that some sources define this function without the normalization factor `\pi/2`. **Examples** Some basic values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> fresnelc(0) 0.0 >>> fresnelc(inf) 0.5 >>> fresnelc(-inf) -0.5 >>> fresnelc(1) 0.7798934003768228294742064 >>> fresnelc(1+2j) (16.08787137412548041729489 - 36.22568799288165021578758j) Comparing with the definition:: >>> fresnelc(3) 0.6057207892976856295561611 >>> quad(lambda t: cos(pi*t**2/2), [0,3]) 0.6057207892976856295561611 """ airyai = r""" Computes the Airy function `\operatorname{Ai}(z)`, which is the solution of the Airy differential equation `f''(z) - z f(z) = 0` with initial conditions .. math :: \operatorname{Ai}(0) = \frac{1}{3^{2/3}\Gamma\left(\frac{2}{3}\right)} \operatorname{Ai}'(0) = -\frac{1}{3^{1/3}\Gamma\left(\frac{1}{3}\right)}. Other common ways of defining the Ai-function include integrals such as .. math :: \operatorname{Ai}(x) = \frac{1}{\pi} \int_0^{\infty} \cos\left(\frac{1}{3}t^3+xt\right) dt \qquad x \in \mathbb{R} \operatorname{Ai}(z) = \frac{\sqrt{3}}{2\pi} \int_0^{\infty} \exp\left(-\frac{t^3}{3}-\frac{z^3}{3t^3}\right) dt. The Ai-function is an entire function with a turning point, behaving roughly like a slowly decaying sine wave for `z < 0` and like a rapidly decreasing exponential for `z > 0`. A second solution of the Airy differential equation is given by `\operatorname{Bi}(z)` (see :func:`~mpmath.airybi`). Optionally, with *derivative=alpha*, :func:`airyai` can compute the `\alpha`-th order fractional derivative with respect to `z`. For `\alpha = n = 1,2,3,\ldots` this gives the derivative `\operatorname{Ai}^{(n)}(z)`, and for `\alpha = -n = -1,-2,-3,\ldots` this gives the `n`-fold iterated integral .. math :: f_0(z) = \operatorname{Ai}(z) f_n(z) = \int_0^z f_{n-1}(t) dt. The Ai-function has infinitely many zeros, all located along the negative half of the real axis. They can be computed with :func:`~mpmath.airyaizero`. **Plots** .. literalinclude :: /plots/ai.py .. image :: /plots/ai.png .. literalinclude :: /plots/ai_c.py .. image :: /plots/ai_c.png **Basic examples** Limits and values include:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> airyai(0); 1/(power(3,'2/3')*gamma('2/3')) 0.3550280538878172392600632 0.3550280538878172392600632 >>> airyai(1) 0.1352924163128814155241474 >>> airyai(-1) 0.5355608832923521187995166 >>> airyai(inf); airyai(-inf) 0.0 0.0 Evaluation is supported for large magnitudes of the argument:: >>> airyai(-100) 0.1767533932395528780908311 >>> airyai(100) 2.634482152088184489550553e-291 >>> airyai(50+50j) (-5.31790195707456404099817e-68 - 1.163588003770709748720107e-67j) >>> airyai(-50+50j) (1.041242537363167632587245e+158 + 3.347525544923600321838281e+157j) Huge arguments are also fine:: >>> airyai(10**10) 1.162235978298741779953693e-289529654602171 >>> airyai(-10**10) 0.0001736206448152818510510181 >>> w = airyai(10**10*(1+j)) >>> w.real 5.711508683721355528322567e-186339621747698 >>> w.imag 1.867245506962312577848166e-186339621747697 The first root of the Ai-function is:: >>> findroot(airyai, -2) -2.338107410459767038489197 >>> airyaizero(1) -2.338107410459767038489197 **Properties and relations** Verifying the Airy differential equation:: >>> for z in [-3.4, 0, 2.5, 1+2j]: ... chop(airyai(z,2) - z*airyai(z)) ... 0.0 0.0 0.0 0.0 The first few terms of the Taylor series expansion around `z = 0` (every third term is zero):: >>> nprint(taylor(airyai, 0, 5)) [0.355028, -0.258819, 0.0, 0.0591713, -0.0215683, 0.0] The Airy functions satisfy the Wronskian relation `\operatorname{Ai}(z) \operatorname{Bi}'(z) - \operatorname{Ai}'(z) \operatorname{Bi}(z) = 1/\pi`:: >>> z = -0.5 >>> airyai(z)*airybi(z,1) - airyai(z,1)*airybi(z) 0.3183098861837906715377675 >>> 1/pi 0.3183098861837906715377675 The Airy functions can be expressed in terms of Bessel functions of order `\pm 1/3`. For `\Re[z] \le 0`, we have:: >>> z = -3 >>> airyai(z) -0.3788142936776580743472439 >>> y = 2*power(-z,'3/2')/3 >>> (sqrt(-z) * (besselj('1/3',y) + besselj('-1/3',y)))/3 -0.3788142936776580743472439 **Derivatives and integrals** Derivatives of the Ai-function (directly and using :func:`~mpmath.diff`):: >>> airyai(-3,1); diff(airyai,-3) 0.3145837692165988136507873 0.3145837692165988136507873 >>> airyai(-3,2); diff(airyai,-3,2) 1.136442881032974223041732 1.136442881032974223041732 >>> airyai(1000,1); diff(airyai,1000) -2.943133917910336090459748e-9156 -2.943133917910336090459748e-9156 Several derivatives at `z = 0`:: >>> airyai(0,0); airyai(0,1); airyai(0,2) 0.3550280538878172392600632 -0.2588194037928067984051836 0.0 >>> airyai(0,3); airyai(0,4); airyai(0,5) 0.3550280538878172392600632 -0.5176388075856135968103671 0.0 >>> airyai(0,15); airyai(0,16); airyai(0,17) 1292.30211615165475090663 -3188.655054727379756351861 0.0 The integral of the Ai-function:: >>> airyai(3,-1); quad(airyai, [0,3]) 0.3299203760070217725002701 0.3299203760070217725002701 >>> airyai(-10,-1); quad(airyai, [0,-10]) -0.765698403134212917425148 -0.765698403134212917425148 Integrals of high or fractional order:: >>> airyai(-2,0.5); differint(airyai,-2,0.5,0) (0.0 + 0.2453596101351438273844725j) (0.0 + 0.2453596101351438273844725j) >>> airyai(-2,-4); differint(airyai,-2,-4,0) 0.2939176441636809580339365 0.2939176441636809580339365 >>> airyai(0,-1); airyai(0,-2); airyai(0,-3) 0.0 0.0 0.0 Integrals of the Ai-function can be evaluated at limit points:: >>> airyai(-1000000,-1); airyai(-inf,-1) -0.6666843728311539978751512 -0.6666666666666666666666667 >>> airyai(10,-1); airyai(+inf,-1) 0.3333333332991690159427932 0.3333333333333333333333333 >>> airyai(+inf,-2); airyai(+inf,-3) +inf +inf >>> airyai(-1000000,-2); airyai(-inf,-2) 666666.4078472650651209742 +inf >>> airyai(-1000000,-3); airyai(-inf,-3) -333333074513.7520264995733 -inf **References** 1. [DLMF]_ Chapter 9: Airy and Related Functions 2. [WolframFunctions]_ section: Bessel-Type Functions """ airybi = r""" Computes the Airy function `\operatorname{Bi}(z)`, which is the solution of the Airy differential equation `f''(z) - z f(z) = 0` with initial conditions .. math :: \operatorname{Bi}(0) = \frac{1}{3^{1/6}\Gamma\left(\frac{2}{3}\right)} \operatorname{Bi}'(0) = \frac{3^{1/6}}{\Gamma\left(\frac{1}{3}\right)}. Like the Ai-function (see :func:`~mpmath.airyai`), the Bi-function is oscillatory for `z < 0`, but it grows rather than decreases for `z > 0`. Optionally, as for :func:`~mpmath.airyai`, derivatives, integrals and fractional derivatives can be computed with the *derivative* parameter. The Bi-function has infinitely many zeros along the negative half-axis, as well as complex zeros, which can all be computed with :func:`~mpmath.airybizero`. **Plots** .. literalinclude :: /plots/bi.py .. image :: /plots/bi.png .. literalinclude :: /plots/bi_c.py .. image :: /plots/bi_c.png **Basic examples** Limits and values include:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> airybi(0); 1/(power(3,'1/6')*gamma('2/3')) 0.6149266274460007351509224 0.6149266274460007351509224 >>> airybi(1) 1.207423594952871259436379 >>> airybi(-1) 0.10399738949694461188869 >>> airybi(inf); airybi(-inf) +inf 0.0 Evaluation is supported for large magnitudes of the argument:: >>> airybi(-100) 0.02427388768016013160566747 >>> airybi(100) 6.041223996670201399005265e+288 >>> airybi(50+50j) (-5.322076267321435669290334e+63 + 1.478450291165243789749427e+65j) >>> airybi(-50+50j) (-3.347525544923600321838281e+157 + 1.041242537363167632587245e+158j) Huge arguments:: >>> airybi(10**10) 1.369385787943539818688433e+289529654602165 >>> airybi(-10**10) 0.001775656141692932747610973 >>> w = airybi(10**10*(1+j)) >>> w.real -6.559955931096196875845858e+186339621747689 >>> w.imag -6.822462726981357180929024e+186339621747690 The first real root of the Bi-function is:: >>> findroot(airybi, -1); airybizero(1) -1.17371322270912792491998 -1.17371322270912792491998 **Properties and relations** Verifying the Airy differential equation:: >>> for z in [-3.4, 0, 2.5, 1+2j]: ... chop(airybi(z,2) - z*airybi(z)) ... 0.0 0.0 0.0 0.0 The first few terms of the Taylor series expansion around `z = 0` (every third term is zero):: >>> nprint(taylor(airybi, 0, 5)) [0.614927, 0.448288, 0.0, 0.102488, 0.0373574, 0.0] The Airy functions can be expressed in terms of Bessel functions of order `\pm 1/3`. For `\Re[z] \le 0`, we have:: >>> z = -3 >>> airybi(z) -0.1982896263749265432206449 >>> p = 2*power(-z,'3/2')/3 >>> sqrt(-mpf(z)/3)*(besselj('-1/3',p) - besselj('1/3',p)) -0.1982896263749265432206449 **Derivatives and integrals** Derivatives of the Bi-function (directly and using :func:`~mpmath.diff`):: >>> airybi(-3,1); diff(airybi,-3) -0.675611222685258537668032 -0.675611222685258537668032 >>> airybi(-3,2); diff(airybi,-3,2) 0.5948688791247796296619346 0.5948688791247796296619346 >>> airybi(1000,1); diff(airybi,1000) 1.710055114624614989262335e+9156 1.710055114624614989262335e+9156 Several derivatives at `z = 0`:: >>> airybi(0,0); airybi(0,1); airybi(0,2) 0.6149266274460007351509224 0.4482883573538263579148237 0.0 >>> airybi(0,3); airybi(0,4); airybi(0,5) 0.6149266274460007351509224 0.8965767147076527158296474 0.0 >>> airybi(0,15); airybi(0,16); airybi(0,17) 2238.332923903442675949357 5522.912562599140729510628 0.0 The integral of the Bi-function:: >>> airybi(3,-1); quad(airybi, [0,3]) 10.06200303130620056316655 10.06200303130620056316655 >>> airybi(-10,-1); quad(airybi, [0,-10]) -0.01504042480614002045135483 -0.01504042480614002045135483 Integrals of high or fractional order:: >>> airybi(-2,0.5); differint(airybi, -2, 0.5, 0) (0.0 + 0.5019859055341699223453257j) (0.0 + 0.5019859055341699223453257j) >>> airybi(-2,-4); differint(airybi,-2,-4,0) 0.2809314599922447252139092 0.2809314599922447252139092 >>> airybi(0,-1); airybi(0,-2); airybi(0,-3) 0.0 0.0 0.0 Integrals of the Bi-function can be evaluated at limit points:: >>> airybi(-1000000,-1); airybi(-inf,-1) 0.000002191261128063434047966873 0.0 >>> airybi(10,-1); airybi(+inf,-1) 147809803.1074067161675853 +inf >>> airybi(+inf,-2); airybi(+inf,-3) +inf +inf >>> airybi(-1000000,-2); airybi(-inf,-2) 0.4482883750599908479851085 0.4482883573538263579148237 >>> gamma('2/3')*power(3,'2/3')/(2*pi) 0.4482883573538263579148237 >>> airybi(-100000,-3); airybi(-inf,-3) -44828.52827206932872493133 -inf >>> airybi(-100000,-4); airybi(-inf,-4) 2241411040.437759489540248 +inf """ airyaizero = r""" Gives the `k`-th zero of the Airy Ai-function, i.e. the `k`-th number `a_k` ordered by magnitude for which `\operatorname{Ai}(a_k) = 0`. Optionally, with *derivative=1*, the corresponding zero `a'_k` of the derivative function, i.e. `\operatorname{Ai}'(a'_k) = 0`, is computed. **Examples** Some values of `a_k`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> airyaizero(1) -2.338107410459767038489197 >>> airyaizero(2) -4.087949444130970616636989 >>> airyaizero(3) -5.520559828095551059129856 >>> airyaizero(1000) -281.0315196125215528353364 Some values of `a'_k`:: >>> airyaizero(1,1) -1.018792971647471089017325 >>> airyaizero(2,1) -3.248197582179836537875424 >>> airyaizero(3,1) -4.820099211178735639400616 >>> airyaizero(1000,1) -280.9378080358935070607097 Verification:: >>> chop(airyai(airyaizero(1))) 0.0 >>> chop(airyai(airyaizero(1,1),1)) 0.0 """ airybizero = r""" With *complex=False*, gives the `k`-th real zero of the Airy Bi-function, i.e. the `k`-th number `b_k` ordered by magnitude for which `\operatorname{Bi}(b_k) = 0`. With *complex=True*, gives the `k`-th complex zero in the upper half plane `\beta_k`. Also the conjugate `\overline{\beta_k}` is a zero. Optionally, with *derivative=1*, the corresponding zero `b'_k` or `\beta'_k` of the derivative function, i.e. `\operatorname{Bi}'(b'_k) = 0` or `\operatorname{Bi}'(\beta'_k) = 0`, is computed. **Examples** Some values of `b_k`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> airybizero(1) -1.17371322270912792491998 >>> airybizero(2) -3.271093302836352715680228 >>> airybizero(3) -4.830737841662015932667709 >>> airybizero(1000) -280.9378112034152401578834 Some values of `b_k`:: >>> airybizero(1,1) -2.294439682614123246622459 >>> airybizero(2,1) -4.073155089071828215552369 >>> airybizero(3,1) -5.512395729663599496259593 >>> airybizero(1000,1) -281.0315164471118527161362 Some values of `\beta_k`:: >>> airybizero(1,complex=True) (0.9775448867316206859469927 + 2.141290706038744575749139j) >>> airybizero(2,complex=True) (1.896775013895336346627217 + 3.627291764358919410440499j) >>> airybizero(3,complex=True) (2.633157739354946595708019 + 4.855468179979844983174628j) >>> airybizero(1000,complex=True) (140.4978560578493018899793 + 243.3907724215792121244867j) Some values of `\beta'_k`:: >>> airybizero(1,1,complex=True) (0.2149470745374305676088329 + 1.100600143302797880647194j) >>> airybizero(2,1,complex=True) (1.458168309223507392028211 + 2.912249367458445419235083j) >>> airybizero(3,1,complex=True) (2.273760763013482299792362 + 4.254528549217097862167015j) >>> airybizero(1000,1,complex=True) (140.4509972835270559730423 + 243.3096175398562811896208j) Verification:: >>> chop(airybi(airybizero(1))) 0.0 >>> chop(airybi(airybizero(1,1),1)) 0.0 >>> u = airybizero(1,complex=True) >>> chop(airybi(u)) 0.0 >>> chop(airybi(conj(u))) 0.0 The complex zeros (in the upper and lower half-planes respectively) asymptotically approach the rays `z = R \exp(\pm i \pi /3)`:: >>> arg(airybizero(1,complex=True)) 1.142532510286334022305364 >>> arg(airybizero(1000,complex=True)) 1.047271114786212061583917 >>> arg(airybizero(1000000,complex=True)) 1.047197624741816183341355 >>> pi/3 1.047197551196597746154214 """ ellipk = r""" Evaluates the complete elliptic integral of the first kind, `K(m)`, defined by .. math :: K(m) = \int_0^{\pi/2} \frac{dt}{\sqrt{1-m \sin^2 t}} \, = \, \frac{\pi}{2} \,_2F_1\left(\frac{1}{2}, \frac{1}{2}, 1, m\right). Note that the argument is the parameter `m = k^2`, not the modulus `k` which is sometimes used. **Plots** .. literalinclude :: /plots/ellipk.py .. image :: /plots/ellipk.png **Examples** Values and limits include:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> ellipk(0) 1.570796326794896619231322 >>> ellipk(inf) (0.0 + 0.0j) >>> ellipk(-inf) 0.0 >>> ellipk(1) +inf >>> ellipk(-1) 1.31102877714605990523242 >>> ellipk(2) (1.31102877714605990523242 - 1.31102877714605990523242j) Verifying the defining integral and hypergeometric representation:: >>> ellipk(0.5) 1.85407467730137191843385 >>> quad(lambda t: (1-0.5*sin(t)**2)**-0.5, [0, pi/2]) 1.85407467730137191843385 >>> pi/2*hyp2f1(0.5,0.5,1,0.5) 1.85407467730137191843385 Evaluation is supported for arbitrary complex `m`:: >>> ellipk(3+4j) (0.9111955638049650086562171 + 0.6313342832413452438845091j) A definite integral:: >>> quad(ellipk, [0, 1]) 2.0 """ agm = r""" ``agm(a, b)`` computes the arithmetic-geometric mean of `a` and `b`, defined as the limit of the following iteration: .. math :: a_0 = a b_0 = b a_{n+1} = \frac{a_n+b_n}{2} b_{n+1} = \sqrt{a_n b_n} This function can be called with a single argument, computing `\mathrm{agm}(a,1) = \mathrm{agm}(1,a)`. **Examples** It is a well-known theorem that the geometric mean of two distinct positive numbers is less than the arithmetic mean. It follows that the arithmetic-geometric mean lies between the two means:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> a = mpf(3) >>> b = mpf(4) >>> sqrt(a*b) 3.46410161513775 >>> agm(a,b) 3.48202767635957 >>> (a+b)/2 3.5 The arithmetic-geometric mean is scale-invariant:: >>> agm(10*e, 10*pi) 29.261085515723 >>> 10*agm(e, pi) 29.261085515723 As an order-of-magnitude estimate, `\mathrm{agm}(1,x) \approx x` for large `x`:: >>> agm(10**10) 643448704.760133 >>> agm(10**50) 1.34814309345871e+48 For tiny `x`, `\mathrm{agm}(1,x) \approx -\pi/(2 \log(x/4))`:: >>> agm('0.01') 0.262166887202249 >>> -pi/2/log('0.0025') 0.262172347753122 The arithmetic-geometric mean can also be computed for complex numbers:: >>> agm(3, 2+j) (2.51055133276184 + 0.547394054060638j) The AGM iteration converges very quickly (each step doubles the number of correct digits), so :func:`~mpmath.agm` supports efficient high-precision evaluation:: >>> mp.dps = 10000 >>> a = agm(1,2) >>> str(a)[-10:] '1679581912' **Mathematical relations** The arithmetic-geometric mean may be used to evaluate the following two parametric definite integrals: .. math :: I_1 = \int_0^{\infty} \frac{1}{\sqrt{(x^2+a^2)(x^2+b^2)}} \,dx I_2 = \int_0^{\pi/2} \frac{1}{\sqrt{a^2 \cos^2(x) + b^2 \sin^2(x)}} \,dx We have:: >>> mp.dps = 15 >>> a = 3 >>> b = 4 >>> f1 = lambda x: ((x**2+a**2)*(x**2+b**2))**-0.5 >>> f2 = lambda x: ((a*cos(x))**2 + (b*sin(x))**2)**-0.5 >>> quad(f1, [0, inf]) 0.451115405388492 >>> quad(f2, [0, pi/2]) 0.451115405388492 >>> pi/(2*agm(a,b)) 0.451115405388492 A formula for `\Gamma(1/4)`:: >>> gamma(0.25) 3.62560990822191 >>> sqrt(2*sqrt(2*pi**3)/agm(1,sqrt(2))) 3.62560990822191 **Possible issues** The branch cut chosen for complex `a` and `b` is somewhat arbitrary. """ gegenbauer = r""" Evaluates the Gegenbauer polynomial, or ultraspherical polynomial, .. math :: C_n^{(a)}(z) = {n+2a-1 \choose n} \,_2F_1\left(-n, n+2a; a+\frac{1}{2}; \frac{1}{2}(1-z)\right). When `n` is a nonnegative integer, this formula gives a polynomial in `z` of degree `n`, but all parameters are permitted to be complex numbers. With `a = 1/2`, the Gegenbauer polynomial reduces to a Legendre polynomial. **Examples** Evaluation for arbitrary arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> gegenbauer(3, 0.5, -10) -2485.0 >>> gegenbauer(1000, 10, 100) 3.012757178975667428359374e+2322 >>> gegenbauer(2+3j, -0.75, -1000j) (-5038991.358609026523401901 + 9414549.285447104177860806j) Evaluation at negative integer orders:: >>> gegenbauer(-4, 2, 1.75) -1.0 >>> gegenbauer(-4, 3, 1.75) 0.0 >>> gegenbauer(-4, 2j, 1.75) 0.0 >>> gegenbauer(-7, 0.5, 3) 8989.0 The Gegenbauer polynomials solve the differential equation:: >>> n, a = 4.5, 1+2j >>> f = lambda z: gegenbauer(n, a, z) >>> for z in [0, 0.75, -0.5j]: ... chop((1-z**2)*diff(f,z,2) - (2*a+1)*z*diff(f,z) + n*(n+2*a)*f(z)) ... 0.0 0.0 0.0 The Gegenbauer polynomials have generating function `(1-2zt+t^2)^{-a}`:: >>> a, z = 2.5, 1 >>> taylor(lambda t: (1-2*z*t+t**2)**(-a), 0, 3) [1.0, 5.0, 15.0, 35.0] >>> [gegenbauer(n,a,z) for n in range(4)] [1.0, 5.0, 15.0, 35.0] The Gegenbauer polynomials are orthogonal on `[-1, 1]` with respect to the weight `(1-z^2)^{a-\frac{1}{2}}`:: >>> a, n, m = 2.5, 4, 5 >>> Cn = lambda z: gegenbauer(n, a, z, zeroprec=1000) >>> Cm = lambda z: gegenbauer(m, a, z, zeroprec=1000) >>> chop(quad(lambda z: Cn(z)*Cm(z)*(1-z**2)*(a-0.5), [-1, 1])) 0.0 """ laguerre = r""" Gives the generalized (associated) Laguerre polynomial, defined by .. math :: L_n^a(z) = \frac{\Gamma(n+b+1)}{\Gamma(b+1) \Gamma(n+1)} \,_1F_1(-n, a+1, z). With `a = 0` and `n` a nonnegative integer, this reduces to an ordinary Laguerre polynomial, the sequence of which begins `L_0(z) = 1, L_1(z) = 1-z, L_2(z) = z^2-2z+1, \ldots`. The Laguerre polynomials are orthogonal with respect to the weight `z^a e^{-z}` on `[0, \infty)`. **Plots** .. literalinclude :: /plots/laguerre.py .. image :: /plots/laguerre.png **Examples** Evaluation for arbitrary arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> laguerre(5, 0, 0.25) 0.03726399739583333333333333 >>> laguerre(1+j, 0.5, 2+3j) (4.474921610704496808379097 - 11.02058050372068958069241j) >>> laguerre(2, 0, 10000) 49980001.0 >>> laguerre(2.5, 0, 10000) -9.327764910194842158583189e+4328 The first few Laguerre polynomials, normalized to have integer coefficients:: >>> for n in range(7): ... chop(taylor(lambda z: fac(n)*laguerre(n, 0, z), 0, n)) ... [1.0] [1.0, -1.0] [2.0, -4.0, 1.0] [6.0, -18.0, 9.0, -1.0] [24.0, -96.0, 72.0, -16.0, 1.0] [120.0, -600.0, 600.0, -200.0, 25.0, -1.0] [720.0, -4320.0, 5400.0, -2400.0, 450.0, -36.0, 1.0] Verifying orthogonality:: >>> Lm = lambda t: laguerre(m,a,t) >>> Ln = lambda t: laguerre(n,a,t) >>> a, n, m = 2.5, 2, 3 >>> chop(quad(lambda t: exp(-t)*t**a*Lm(t)*Ln(t), [0,inf])) 0.0 """ hermite = r""" Evaluates the Hermite polynomial `H_n(z)`, which may be defined using the recurrence .. math :: H_0(z) = 1 H_1(z) = 2z H_{n+1} = 2z H_n(z) - 2n H_{n-1}(z). The Hermite polynomials are orthogonal on `(-\infty, \infty)` with respect to the weight `e^{-z^2}`. More generally, allowing arbitrary complex values of `n`, the Hermite function `H_n(z)` is defined as .. math :: H_n(z) = (2z)^n \,_2F_0\left(-\frac{n}{2}, \frac{1-n}{2}, -\frac{1}{z^2}\right) for `\Re{z} > 0`, or generally .. math :: H_n(z) = 2^n \sqrt{\pi} \left( \frac{1}{\Gamma\left(\frac{1-n}{2}\right)} \,_1F_1\left(-\frac{n}{2}, \frac{1}{2}, z^2\right) - \frac{2z}{\Gamma\left(-\frac{n}{2}\right)} \,_1F_1\left(\frac{1-n}{2}, \frac{3}{2}, z^2\right) \right). **Plots** .. literalinclude :: /plots/hermite.py .. image :: /plots/hermite.png **Examples** Evaluation for arbitrary arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hermite(0, 10) 1.0 >>> hermite(1, 10); hermite(2, 10) 20.0 398.0 >>> hermite(10000, 2) 4.950440066552087387515653e+19334 >>> hermite(3, -10**8) -7999999999999998800000000.0 >>> hermite(-3, -10**8) 1.675159751729877682920301e+4342944819032534 >>> hermite(2+3j, -1+2j) (-0.07652130602993513389421901 - 0.1084662449961914580276007j) Coefficients of the first few Hermite polynomials are:: >>> for n in range(7): ... chop(taylor(lambda z: hermite(n, z), 0, n)) ... [1.0] [0.0, 2.0] [-2.0, 0.0, 4.0] [0.0, -12.0, 0.0, 8.0] [12.0, 0.0, -48.0, 0.0, 16.0] [0.0, 120.0, 0.0, -160.0, 0.0, 32.0] [-120.0, 0.0, 720.0, 0.0, -480.0, 0.0, 64.0] Values at `z = 0`:: >>> for n in range(-5, 9): ... hermite(n, 0) ... 0.02769459142039868792653387 0.08333333333333333333333333 0.2215567313631895034122709 0.5 0.8862269254527580136490837 1.0 0.0 -2.0 0.0 12.0 0.0 -120.0 0.0 1680.0 Hermite functions satisfy the differential equation:: >>> n = 4 >>> f = lambda z: hermite(n, z) >>> z = 1.5 >>> chop(diff(f,z,2) - 2*z*diff(f,z) + 2*n*f(z)) 0.0 Verifying orthogonality:: >>> chop(quad(lambda t: hermite(2,t)*hermite(4,t)*exp(-t**2), [-inf,inf])) 0.0 """ jacobi = r""" ``jacobi(n, a, b, x)`` evaluates the Jacobi polynomial `P_n^{(a,b)}(x)`. The Jacobi polynomials are a special case of the hypergeometric function `\,_2F_1` given by: .. math :: P_n^{(a,b)}(x) = {n+a \choose n} \,_2F_1\left(-n,1+a+b+n,a+1,\frac{1-x}{2}\right). Note that this definition generalizes to nonintegral values of `n`. When `n` is an integer, the hypergeometric series terminates after a finite number of terms, giving a polynomial in `x`. **Evaluation of Jacobi polynomials** A special evaluation is `P_n^{(a,b)}(1) = {n+a \choose n}`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> jacobi(4, 0.5, 0.25, 1) 2.4609375 >>> binomial(4+0.5, 4) 2.4609375 A Jacobi polynomial of degree `n` is equal to its Taylor polynomial of degree `n`. The explicit coefficients of Jacobi polynomials can therefore be recovered easily using :func:`~mpmath.taylor`:: >>> for n in range(5): ... nprint(taylor(lambda x: jacobi(n,1,2,x), 0, n)) ... [1.0] [-0.5, 2.5] [-0.75, -1.5, 5.25] [0.5, -3.5, -3.5, 10.5] [0.625, 2.5, -11.25, -7.5, 20.625] For nonintegral `n`, the Jacobi "polynomial" is no longer a polynomial:: >>> nprint(taylor(lambda x: jacobi(0.5,1,2,x), 0, 4)) [0.309983, 1.84119, -1.26933, 1.26699, -1.34808] **Orthogonality** The Jacobi polynomials are orthogonal on the interval `[-1, 1]` with respect to the weight function `w(x) = (1-x)^a (1+x)^b`. That is, `w(x) P_n^{(a,b)}(x) P_m^{(a,b)}(x)` integrates to zero if `m \ne n` and to a nonzero number if `m = n`. The orthogonality is easy to verify using numerical quadrature:: >>> P = jacobi >>> f = lambda x: (1-x)**a * (1+x)**b * P(m,a,b,x) * P(n,a,b,x) >>> a = 2 >>> b = 3 >>> m, n = 3, 4 >>> chop(quad(f, [-1, 1]), 1) 0.0 >>> m, n = 4, 4 >>> quad(f, [-1, 1]) 1.9047619047619 **Differential equation** The Jacobi polynomials are solutions of the differential equation .. math :: (1-x^2) y'' + (b-a-(a+b+2)x) y' + n (n+a+b+1) y = 0. We can verify that :func:`~mpmath.jacobi` approximately satisfies this equation:: >>> from mpmath import * >>> mp.dps = 15 >>> a = 2.5 >>> b = 4 >>> n = 3 >>> y = lambda x: jacobi(n,a,b,x) >>> x = pi >>> A0 = n*(n+a+b+1)*y(x) >>> A1 = (b-a-(a+b+2)*x)*diff(y,x) >>> A2 = (1-x**2)*diff(y,x,2) >>> nprint(A2 + A1 + A0, 1) 4.0e-12 The difference of order `10^{-12}` is as close to zero as it could be at 15-digit working precision, since the terms are large:: >>> A0, A1, A2 (26560.2328981879, -21503.7641037294, -5056.46879445852) """ legendre = r""" ``legendre(n, x)`` evaluates the Legendre polynomial `P_n(x)`. The Legendre polynomials are given by the formula .. math :: P_n(x) = \frac{1}{2^n n!} \frac{d^n}{dx^n} (x^2 -1)^n. Alternatively, they can be computed recursively using .. math :: P_0(x) = 1 P_1(x) = x (n+1) P_{n+1}(x) = (2n+1) x P_n(x) - n P_{n-1}(x). A third definition is in terms of the hypergeometric function `\,_2F_1`, whereby they can be generalized to arbitrary `n`: .. math :: P_n(x) = \,_2F_1\left(-n, n+1, 1, \frac{1-x}{2}\right) **Plots** .. literalinclude :: /plots/legendre.py .. image :: /plots/legendre.png **Basic evaluation** The Legendre polynomials assume fixed values at the points `x = -1` and `x = 1`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nprint([legendre(n, 1) for n in range(6)]) [1.0, 1.0, 1.0, 1.0, 1.0, 1.0] >>> nprint([legendre(n, -1) for n in range(6)]) [1.0, -1.0, 1.0, -1.0, 1.0, -1.0] The coefficients of Legendre polynomials can be recovered using degree-`n` Taylor expansion:: >>> for n in range(5): ... nprint(chop(taylor(lambda x: legendre(n, x), 0, n))) ... [1.0] [0.0, 1.0] [-0.5, 0.0, 1.5] [0.0, -1.5, 0.0, 2.5] [0.375, 0.0, -3.75, 0.0, 4.375] The roots of Legendre polynomials are located symmetrically on the interval `[-1, 1]`:: >>> for n in range(5): ... nprint(polyroots(taylor(lambda x: legendre(n, x), 0, n)[::-1])) ... [] [0.0] [-0.57735, 0.57735] [-0.774597, 0.0, 0.774597] [-0.861136, -0.339981, 0.339981, 0.861136] An example of an evaluation for arbitrary `n`:: >>> legendre(0.75, 2+4j) (1.94952805264875 + 2.1071073099422j) **Orthogonality** The Legendre polynomials are orthogonal on `[-1, 1]` with respect to the trivial weight `w(x) = 1`. That is, `P_m(x) P_n(x)` integrates to zero if `m \ne n` and to `2/(2n+1)` if `m = n`:: >>> m, n = 3, 4 >>> quad(lambda x: legendre(m,x)*legendre(n,x), [-1, 1]) 0.0 >>> m, n = 4, 4 >>> quad(lambda x: legendre(m,x)*legendre(n,x), [-1, 1]) 0.222222222222222 **Differential equation** The Legendre polynomials satisfy the differential equation .. math :: ((1-x^2) y')' + n(n+1) y' = 0. We can verify this numerically:: >>> n = 3.6 >>> x = 0.73 >>> P = legendre >>> A = diff(lambda t: (1-t**2)*diff(lambda u: P(n,u), t), x) >>> B = n*(n+1)*P(n,x) >>> nprint(A+B,1) 9.0e-16 """ legenp = r""" Calculates the (associated) Legendre function of the first kind of degree *n* and order *m*, `P_n^m(z)`. Taking `m = 0` gives the ordinary Legendre function of the first kind, `P_n(z)`. The parameters may be complex numbers. In terms of the Gauss hypergeometric function, the (associated) Legendre function is defined as .. math :: P_n^m(z) = \frac{1}{\Gamma(1-m)} \frac{(1+z)^{m/2}}{(1-z)^{m/2}} \,_2F_1\left(-n, n+1, 1-m, \frac{1-z}{2}\right). With *type=3* instead of *type=2*, the alternative definition .. math :: \hat{P}_n^m(z) = \frac{1}{\Gamma(1-m)} \frac{(z+1)^{m/2}}{(z-1)^{m/2}} \,_2F_1\left(-n, n+1, 1-m, \frac{1-z}{2}\right). is used. These functions correspond respectively to ``LegendreP[n,m,2,z]`` and ``LegendreP[n,m,3,z]`` in Mathematica. The general solution of the (associated) Legendre differential equation .. math :: (1-z^2) f''(z) - 2zf'(z) + \left(n(n+1)-\frac{m^2}{1-z^2}\right)f(z) = 0 is given by `C_1 P_n^m(z) + C_2 Q_n^m(z)` for arbitrary constants `C_1`, `C_2`, where `Q_n^m(z)` is a Legendre function of the second kind as implemented by :func:`~mpmath.legenq`. **Examples** Evaluation for arbitrary parameters and arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> legenp(2, 0, 10); legendre(2, 10) 149.5 149.5 >>> legenp(-2, 0.5, 2.5) (1.972260393822275434196053 - 1.972260393822275434196053j) >>> legenp(2+3j, 1-j, -0.5+4j) (-3.335677248386698208736542 - 5.663270217461022307645625j) >>> chop(legenp(3, 2, -1.5, type=2)) 28.125 >>> chop(legenp(3, 2, -1.5, type=3)) -28.125 Verifying the associated Legendre differential equation:: >>> n, m = 2, -0.5 >>> C1, C2 = 1, -3 >>> f = lambda z: C1*legenp(n,m,z) + C2*legenq(n,m,z) >>> deq = lambda z: (1-z**2)*diff(f,z,2) - 2*z*diff(f,z) + \ ... (n*(n+1)-m**2/(1-z**2))*f(z) >>> for z in [0, 2, -1.5, 0.5+2j]: ... chop(deq(mpmathify(z))) ... 0.0 0.0 0.0 0.0 """ legenq = r""" Calculates the (associated) Legendre function of the second kind of degree *n* and order *m*, `Q_n^m(z)`. Taking `m = 0` gives the ordinary Legendre function of the second kind, `Q_n(z)`. The parameters may be complex numbers. The Legendre functions of the second kind give a second set of solutions to the (associated) Legendre differential equation. (See :func:`~mpmath.legenp`.) Unlike the Legendre functions of the first kind, they are not polynomials of `z` for integer `n`, `m` but rational or logarithmic functions with poles at `z = \pm 1`. There are various ways to define Legendre functions of the second kind, giving rise to different complex structure. A version can be selected using the *type* keyword argument. The *type=2* and *type=3* functions are given respectively by .. math :: Q_n^m(z) = \frac{\pi}{2 \sin(\pi m)} \left( \cos(\pi m) P_n^m(z) - \frac{\Gamma(1+m+n)}{\Gamma(1-m+n)} P_n^{-m}(z)\right) \hat{Q}_n^m(z) = \frac{\pi}{2 \sin(\pi m)} e^{\pi i m} \left( \hat{P}_n^m(z) - \frac{\Gamma(1+m+n)}{\Gamma(1-m+n)} \hat{P}_n^{-m}(z)\right) where `P` and `\hat{P}` are the *type=2* and *type=3* Legendre functions of the first kind. The formulas above should be understood as limits when `m` is an integer. These functions correspond to ``LegendreQ[n,m,2,z]`` (or ``LegendreQ[n,m,z]``) and ``LegendreQ[n,m,3,z]`` in Mathematica. The *type=3* function is essentially the same as the function defined in Abramowitz & Stegun (eq. 8.1.3) but with `(z+1)^{m/2}(z-1)^{m/2}` instead of `(z^2-1)^{m/2}`, giving slightly different branches. **Examples** Evaluation for arbitrary parameters and arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> legenq(2, 0, 0.5) -0.8186632680417568557122028 >>> legenq(-1.5, -2, 2.5) (0.6655964618250228714288277 + 0.3937692045497259717762649j) >>> legenq(2-j, 3+4j, -6+5j) (-10001.95256487468541686564 - 6011.691337610097577791134j) Different versions of the function:: >>> legenq(2, 1, 0.5) 0.7298060598018049369381857 >>> legenq(2, 1, 1.5) (-7.902916572420817192300921 + 0.1998650072605976600724502j) >>> legenq(2, 1, 0.5, type=3) (2.040524284763495081918338 - 0.7298060598018049369381857j) >>> chop(legenq(2, 1, 1.5, type=3)) -0.1998650072605976600724502 """ chebyt = r""" ``chebyt(n, x)`` evaluates the Chebyshev polynomial of the first kind `T_n(x)`, defined by the identity .. math :: T_n(\cos x) = \cos(n x). The Chebyshev polynomials of the first kind are a special case of the Jacobi polynomials, and by extension of the hypergeometric function `\,_2F_1`. They can thus also be evaluated for nonintegral `n`. **Plots** .. literalinclude :: /plots/chebyt.py .. image :: /plots/chebyt.png **Basic evaluation** The coefficients of the `n`-th polynomial can be recovered using using degree-`n` Taylor expansion:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(5): ... nprint(chop(taylor(lambda x: chebyt(n, x), 0, n))) ... [1.0] [0.0, 1.0] [-1.0, 0.0, 2.0] [0.0, -3.0, 0.0, 4.0] [1.0, 0.0, -8.0, 0.0, 8.0] **Orthogonality** The Chebyshev polynomials of the first kind are orthogonal on the interval `[-1, 1]` with respect to the weight function `w(x) = 1/\sqrt{1-x^2}`:: >>> f = lambda x: chebyt(m,x)*chebyt(n,x)/sqrt(1-x**2) >>> m, n = 3, 4 >>> nprint(quad(f, [-1, 1]),1) 0.0 >>> m, n = 4, 4 >>> quad(f, [-1, 1]) 1.57079632596448 """ chebyu = r""" ``chebyu(n, x)`` evaluates the Chebyshev polynomial of the second kind `U_n(x)`, defined by the identity .. math :: U_n(\cos x) = \frac{\sin((n+1)x)}{\sin(x)}. The Chebyshev polynomials of the second kind are a special case of the Jacobi polynomials, and by extension of the hypergeometric function `\,_2F_1`. They can thus also be evaluated for nonintegral `n`. **Plots** .. literalinclude :: /plots/chebyu.py .. image :: /plots/chebyu.png **Basic evaluation** The coefficients of the `n`-th polynomial can be recovered using using degree-`n` Taylor expansion:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(5): ... nprint(chop(taylor(lambda x: chebyu(n, x), 0, n))) ... [1.0] [0.0, 2.0] [-1.0, 0.0, 4.0] [0.0, -4.0, 0.0, 8.0] [1.0, 0.0, -12.0, 0.0, 16.0] **Orthogonality** The Chebyshev polynomials of the second kind are orthogonal on the interval `[-1, 1]` with respect to the weight function `w(x) = \sqrt{1-x^2}`:: >>> f = lambda x: chebyu(m,x)*chebyu(n,x)*sqrt(1-x**2) >>> m, n = 3, 4 >>> quad(f, [-1, 1]) 0.0 >>> m, n = 4, 4 >>> quad(f, [-1, 1]) 1.5707963267949 """ besselj = r""" ``besselj(n, x, derivative=0)`` gives the Bessel function of the first kind `J_n(x)`. Bessel functions of the first kind are defined as solutions of the differential equation .. math :: x^2 y'' + x y' + (x^2 - n^2) y = 0 which appears, among other things, when solving the radial part of Laplace's equation in cylindrical coordinates. This equation has two solutions for given `n`, where the `J_n`-function is the solution that is nonsingular at `x = 0`. For positive integer `n`, `J_n(x)` behaves roughly like a sine (odd `n`) or cosine (even `n`) multiplied by a magnitude factor that decays slowly as `x \to \pm\infty`. Generally, `J_n` is a special case of the hypergeometric function `\,_0F_1`: .. math :: J_n(x) = \frac{x^n}{2^n \Gamma(n+1)} \,_0F_1\left(n+1,-\frac{x^2}{4}\right) With *derivative* = `m \ne 0`, the `m`-th derivative .. math :: \frac{d^m}{dx^m} J_n(x) is computed. **Plots** .. literalinclude :: /plots/besselj.py .. image :: /plots/besselj.png .. literalinclude :: /plots/besselj_c.py .. image :: /plots/besselj_c.png **Examples** Evaluation is supported for arbitrary arguments, and at arbitrary precision:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> besselj(2, 1000) -0.024777229528606 >>> besselj(4, 0.75) 0.000801070086542314 >>> besselj(2, 1000j) (-2.48071721019185e+432 + 6.41567059811949e-437j) >>> mp.dps = 25 >>> besselj(0.75j, 3+4j) (-2.778118364828153309919653 - 1.5863603889018621585533j) >>> mp.dps = 50 >>> besselj(1, pi) 0.28461534317975275734531059968613140570981118184947 Arguments may be large:: >>> mp.dps = 25 >>> besselj(0, 10000) -0.007096160353388801477265164 >>> besselj(0, 10**10) 0.000002175591750246891726859055 >>> besselj(2, 10**100) 7.337048736538615712436929e-51 >>> besselj(2, 10**5*j) (-3.540725411970948860173735e+43426 + 4.4949812409615803110051e-43433j) The Bessel functions of the first kind satisfy simple symmetries around `x = 0`:: >>> mp.dps = 15 >>> nprint([besselj(n,0) for n in range(5)]) [1.0, 0.0, 0.0, 0.0, 0.0] >>> nprint([besselj(n,pi) for n in range(5)]) [-0.304242, 0.284615, 0.485434, 0.333458, 0.151425] >>> nprint([besselj(n,-pi) for n in range(5)]) [-0.304242, -0.284615, 0.485434, -0.333458, 0.151425] Roots of Bessel functions are often used:: >>> nprint([findroot(j0, k) for k in [2, 5, 8, 11, 14]]) [2.40483, 5.52008, 8.65373, 11.7915, 14.9309] >>> nprint([findroot(j1, k) for k in [3, 7, 10, 13, 16]]) [3.83171, 7.01559, 10.1735, 13.3237, 16.4706] The roots are not periodic, but the distance between successive roots asymptotically approaches `2 \pi`. Bessel functions of the first kind have the following normalization:: >>> quadosc(j0, [0, inf], period=2*pi) 1.0 >>> quadosc(j1, [0, inf], period=2*pi) 1.0 For `n = 1/2` or `n = -1/2`, the Bessel function reduces to a trigonometric function:: >>> x = 10 >>> besselj(0.5, x), sqrt(2/(pi*x))*sin(x) (-0.13726373575505, -0.13726373575505) >>> besselj(-0.5, x), sqrt(2/(pi*x))*cos(x) (-0.211708866331398, -0.211708866331398) Derivatives of any order can be computed (negative orders correspond to integration):: >>> mp.dps = 25 >>> besselj(0, 7.5, 1) -0.1352484275797055051822405 >>> diff(lambda x: besselj(0,x), 7.5) -0.1352484275797055051822405 >>> besselj(0, 7.5, 10) -0.1377811164763244890135677 >>> diff(lambda x: besselj(0,x), 7.5, 10) -0.1377811164763244890135677 >>> besselj(0,7.5,-1) - besselj(0,3.5,-1) -0.1241343240399987693521378 >>> quad(j0, [3.5, 7.5]) -0.1241343240399987693521378 Differentiation with a noninteger order gives the fractional derivative in the sense of the Riemann-Liouville differintegral, as computed by :func:`~mpmath.differint`:: >>> mp.dps = 15 >>> besselj(1, 3.5, 0.75) -0.385977722939384 >>> differint(lambda x: besselj(1, x), 3.5, 0.75) -0.385977722939384 """ besseli = r""" ``besseli(n, x, derivative=0)`` gives the modified Bessel function of the first kind, .. math :: I_n(x) = i^{-n} J_n(ix). With *derivative* = `m \ne 0`, the `m`-th derivative .. math :: \frac{d^m}{dx^m} I_n(x) is computed. **Plots** .. literalinclude :: /plots/besseli.py .. image :: /plots/besseli.png .. literalinclude :: /plots/besseli_c.py .. image :: /plots/besseli_c.png **Examples** Some values of `I_n(x)`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> besseli(0,0) 1.0 >>> besseli(1,0) 0.0 >>> besseli(0,1) 1.266065877752008335598245 >>> besseli(3.5, 2+3j) (-0.2904369752642538144289025 - 0.4469098397654815837307006j) Arguments may be large:: >>> besseli(2, 1000) 2.480717210191852440616782e+432 >>> besseli(2, 10**10) 4.299602851624027900335391e+4342944813 >>> besseli(2, 6000+10000j) (-2.114650753239580827144204e+2603 + 4.385040221241629041351886e+2602j) For integers `n`, the following integral representation holds:: >>> mp.dps = 15 >>> n = 3 >>> x = 2.3 >>> quad(lambda t: exp(x*cos(t))*cos(n*t), [0,pi])/pi 0.349223221159309 >>> besseli(n,x) 0.349223221159309 Derivatives and antiderivatives of any order can be computed:: >>> mp.dps = 25 >>> besseli(2, 7.5, 1) 195.8229038931399062565883 >>> diff(lambda x: besseli(2,x), 7.5) 195.8229038931399062565883 >>> besseli(2, 7.5, 10) 153.3296508971734525525176 >>> diff(lambda x: besseli(2,x), 7.5, 10) 153.3296508971734525525176 >>> besseli(2,7.5,-1) - besseli(2,3.5,-1) 202.5043900051930141956876 >>> quad(lambda x: besseli(2,x), [3.5, 7.5]) 202.5043900051930141956876 """ bessely = r""" ``bessely(n, x, derivative=0)`` gives the Bessel function of the second kind, .. math :: Y_n(x) = \frac{J_n(x) \cos(\pi n) - J_{-n}(x)}{\sin(\pi n)}. For `n` an integer, this formula should be understood as a limit. With *derivative* = `m \ne 0`, the `m`-th derivative .. math :: \frac{d^m}{dx^m} Y_n(x) is computed. **Plots** .. literalinclude :: /plots/bessely.py .. image :: /plots/bessely.png .. literalinclude :: /plots/bessely_c.py .. image :: /plots/bessely_c.png **Examples** Some values of `Y_n(x)`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> bessely(0,0), bessely(1,0), bessely(2,0) (-inf, -inf, -inf) >>> bessely(1, pi) 0.3588729167767189594679827 >>> bessely(0.5, 3+4j) (9.242861436961450520325216 - 3.085042824915332562522402j) Arguments may be large:: >>> bessely(0, 10000) 0.00364780555898660588668872 >>> bessely(2.5, 10**50) -4.8952500412050989295774e-26 >>> bessely(2.5, -10**50) (0.0 + 4.8952500412050989295774e-26j) Derivatives and antiderivatives of any order can be computed:: >>> bessely(2, 3.5, 1) 0.3842618820422660066089231 >>> diff(lambda x: bessely(2, x), 3.5) 0.3842618820422660066089231 >>> bessely(0.5, 3.5, 1) -0.2066598304156764337900417 >>> diff(lambda x: bessely(0.5, x), 3.5) -0.2066598304156764337900417 >>> diff(lambda x: bessely(2, x), 0.5, 10) -208173867409.5547350101511 >>> bessely(2, 0.5, 10) -208173867409.5547350101511 >>> bessely(2, 100.5, 100) 0.02668487547301372334849043 >>> quad(lambda x: bessely(2,x), [1,3]) -1.377046859093181969213262 >>> bessely(2,3,-1) - bessely(2,1,-1) -1.377046859093181969213262 """ besselk = r""" ``besselk(n, x)`` gives the modified Bessel function of the second kind, .. math :: K_n(x) = \frac{\pi}{2} \frac{I_{-n}(x)-I_{n}(x)}{\sin(\pi n)} For `n` an integer, this formula should be understood as a limit. **Plots** .. literalinclude :: /plots/besselk.py .. image :: /plots/besselk.png .. literalinclude :: /plots/besselk_c.py .. image :: /plots/besselk_c.png **Examples** Evaluation is supported for arbitrary complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> besselk(0,1) 0.4210244382407083333356274 >>> besselk(0, -1) (0.4210244382407083333356274 - 3.97746326050642263725661j) >>> besselk(3.5, 2+3j) (-0.02090732889633760668464128 + 0.2464022641351420167819697j) >>> besselk(2+3j, 0.5) (0.9615816021726349402626083 + 0.1918250181801757416908224j) Arguments may be large:: >>> besselk(0, 100) 4.656628229175902018939005e-45 >>> besselk(1, 10**6) 4.131967049321725588398296e-434298 >>> besselk(1, 10**6*j) (0.001140348428252385844876706 - 0.0005200017201681152909000961j) >>> besselk(4.5, fmul(10**50, j, exact=True)) (1.561034538142413947789221e-26 + 1.243554598118700063281496e-25j) The point `x = 0` is a singularity (logarithmic if `n = 0`):: >>> besselk(0,0) +inf >>> besselk(1,0) +inf >>> for n in range(-4, 5): ... print(besselk(n, '1e-1000')) ... 4.8e+4001 8.0e+3000 2.0e+2000 1.0e+1000 2302.701024509704096466802 1.0e+1000 2.0e+2000 8.0e+3000 4.8e+4001 """ hankel1 = r""" ``hankel1(n,x)`` computes the Hankel function of the first kind, which is the complex combination of Bessel functions given by .. math :: H_n^{(1)}(x) = J_n(x) + i Y_n(x). **Plots** .. literalinclude :: /plots/hankel1.py .. image :: /plots/hankel1.png .. literalinclude :: /plots/hankel1_c.py .. image :: /plots/hankel1_c.png **Examples** The Hankel function is generally complex-valued:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hankel1(2, pi) (0.4854339326315091097054957 - 0.0999007139290278787734903j) >>> hankel1(3.5, pi) (0.2340002029630507922628888 - 0.6419643823412927142424049j) """ hankel2 = r""" ``hankel2(n,x)`` computes the Hankel function of the second kind, which is the complex combination of Bessel functions given by .. math :: H_n^{(2)}(x) = J_n(x) - i Y_n(x). **Plots** .. literalinclude :: /plots/hankel2.py .. image :: /plots/hankel2.png .. literalinclude :: /plots/hankel2_c.py .. image :: /plots/hankel2_c.png **Examples** The Hankel function is generally complex-valued:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> hankel2(2, pi) (0.4854339326315091097054957 + 0.0999007139290278787734903j) >>> hankel2(3.5, pi) (0.2340002029630507922628888 + 0.6419643823412927142424049j) """ lambertw = r""" The Lambert W function `W(z)` is defined as the inverse function of `w \exp(w)`. In other words, the value of `W(z)` is such that `z = W(z) \exp(W(z))` for any complex number `z`. The Lambert W function is a multivalued function with infinitely many branches `W_k(z)`, indexed by `k \in \mathbb{Z}`. Each branch gives a different solution `w` of the equation `z = w \exp(w)`. All branches are supported by :func:`~mpmath.lambertw`: * ``lambertw(z)`` gives the principal solution (branch 0) * ``lambertw(z, k)`` gives the solution on branch `k` The Lambert W function has two partially real branches: the principal branch (`k = 0`) is real for real `z > -1/e`, and the `k = -1` branch is real for `-1/e < z < 0`. All branches except `k = 0` have a logarithmic singularity at `z = 0`. The definition, implementation and choice of branches is based on [Corless]_. **Plots** .. literalinclude :: /plots/lambertw.py .. image :: /plots/lambertw.png .. literalinclude :: /plots/lambertw_c.py .. image :: /plots/lambertw_c.png **Basic examples** The Lambert W function is the inverse of `w \exp(w)`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> w = lambertw(1) >>> w 0.5671432904097838729999687 >>> w*exp(w) 1.0 Any branch gives a valid inverse:: >>> w = lambertw(1, k=3) >>> w (-2.853581755409037807206819 + 17.11353553941214591260783j) >>> w = lambertw(1, k=25) >>> w (-5.047020464221569709378686 + 155.4763860949415867162066j) >>> chop(w*exp(w)) 1.0 **Applications to equation-solving** The Lambert W function may be used to solve various kinds of equations, such as finding the value of the infinite power tower `z^{z^{z^{\ldots}}}`:: >>> def tower(z, n): ... if n == 0: ... return z ... return z ** tower(z, n-1) ... >>> tower(mpf(0.5), 100) 0.6411857445049859844862005 >>> -lambertw(-log(0.5))/log(0.5) 0.6411857445049859844862005 **Properties** The Lambert W function grows roughly like the natural logarithm for large arguments:: >>> lambertw(1000); log(1000) 5.249602852401596227126056 6.907755278982137052053974 >>> lambertw(10**100); log(10**100) 224.8431064451185015393731 230.2585092994045684017991 The principal branch of the Lambert W function has a rational Taylor series expansion around `z = 0`:: >>> nprint(taylor(lambertw, 0, 6), 10) [0.0, 1.0, -1.0, 1.5, -2.666666667, 5.208333333, -10.8] Some special values and limits are:: >>> lambertw(0) 0.0 >>> lambertw(1) 0.5671432904097838729999687 >>> lambertw(e) 1.0 >>> lambertw(inf) +inf >>> lambertw(0, k=-1) -inf >>> lambertw(0, k=3) -inf >>> lambertw(inf, k=2) (+inf + 12.56637061435917295385057j) >>> lambertw(inf, k=3) (+inf + 18.84955592153875943077586j) >>> lambertw(-inf, k=3) (+inf + 21.9911485751285526692385j) The `k = 0` and `k = -1` branches join at `z = -1/e` where `W(z) = -1` for both branches. Since `-1/e` can only be represented approximately with binary floating-point numbers, evaluating the Lambert W function at this point only gives `-1` approximately:: >>> lambertw(-1/e, 0) -0.9999999999998371330228251 >>> lambertw(-1/e, -1) -1.000000000000162866977175 If `-1/e` happens to round in the negative direction, there might be a small imaginary part:: >>> mp.dps = 15 >>> lambertw(-1/e) (-1.0 + 8.22007971483662e-9j) >>> lambertw(-1/e+eps) -0.999999966242188 **References** 1. [Corless]_ """ barnesg = r""" Evaluates the Barnes G-function, which generalizes the superfactorial (:func:`~mpmath.superfac`) and by extension also the hyperfactorial (:func:`~mpmath.hyperfac`) to the complex numbers in an analogous way to how the gamma function generalizes the ordinary factorial. The Barnes G-function may be defined in terms of a Weierstrass product: .. math :: G(z+1) = (2\pi)^{z/2} e^{-[z(z+1)+\gamma z^2]/2} \prod_{n=1}^\infty \left[\left(1+\frac{z}{n}\right)^ne^{-z+z^2/(2n)}\right] For positive integers `n`, we have have relation to superfactorials `G(n) = \mathrm{sf}(n-2) = 0! \cdot 1! \cdots (n-2)!`. **Examples** Some elementary values and limits of the Barnes G-function:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> barnesg(1), barnesg(2), barnesg(3) (1.0, 1.0, 1.0) >>> barnesg(4) 2.0 >>> barnesg(5) 12.0 >>> barnesg(6) 288.0 >>> barnesg(7) 34560.0 >>> barnesg(8) 24883200.0 >>> barnesg(inf) +inf >>> barnesg(0), barnesg(-1), barnesg(-2) (0.0, 0.0, 0.0) Closed-form values are known for some rational arguments:: >>> barnesg('1/2') 0.603244281209446 >>> sqrt(exp(0.25+log(2)/12)/sqrt(pi)/glaisher**3) 0.603244281209446 >>> barnesg('1/4') 0.29375596533861 >>> nthroot(exp('3/8')/exp(catalan/pi)/ ... gamma(0.25)**3/sqrt(glaisher)**9, 4) 0.29375596533861 The Barnes G-function satisfies the functional equation `G(z+1) = \Gamma(z) G(z)`:: >>> z = pi >>> barnesg(z+1) 2.39292119327948 >>> gamma(z)*barnesg(z) 2.39292119327948 The asymptotic growth rate of the Barnes G-function is related to the Glaisher-Kinkelin constant:: >>> limit(lambda n: barnesg(n+1)/(n**(n**2/2-mpf(1)/12)* ... (2*pi)**(n/2)*exp(-3*n**2/4)), inf) 0.847536694177301 >>> exp('1/12')/glaisher 0.847536694177301 The Barnes G-function can be differentiated in closed form:: >>> z = 3 >>> diff(barnesg, z) 0.264507203401607 >>> barnesg(z)*((z-1)*psi(0,z)-z+(log(2*pi)+1)/2) 0.264507203401607 Evaluation is supported for arbitrary arguments and at arbitrary precision:: >>> barnesg(6.5) 2548.7457695685 >>> barnesg(-pi) 0.00535976768353037 >>> barnesg(3+4j) (-0.000676375932234244 - 4.42236140124728e-5j) >>> mp.dps = 50 >>> barnesg(1/sqrt(2)) 0.81305501090451340843586085064413533788206204124732 >>> q = barnesg(10j) >>> q.real 0.000000000021852360840356557241543036724799812371995850552234 >>> q.imag -0.00000000000070035335320062304849020654215545839053210041457588 >>> mp.dps = 15 >>> barnesg(100) 3.10361006263698e+6626 >>> barnesg(-101) 0.0 >>> barnesg(-10.5) 5.94463017605008e+25 >>> barnesg(-10000.5) -6.14322868174828e+167480422 >>> barnesg(1000j) (5.21133054865546e-1173597 + 4.27461836811016e-1173597j) >>> barnesg(-1000+1000j) (2.43114569750291e+1026623 + 2.24851410674842e+1026623j) **References** 1. Whittaker & Watson, *A Course of Modern Analysis*, Cambridge University Press, 4th edition (1927), p.264 2. http://en.wikipedia.org/wiki/Barnes_G-function 3. http://mathworld.wolfram.com/BarnesG-Function.html """ superfac = r""" Computes the superfactorial, defined as the product of consecutive factorials .. math :: \mathrm{sf}(n) = \prod_{k=1}^n k! For general complex `z`, `\mathrm{sf}(z)` is defined in terms of the Barnes G-function (see :func:`~mpmath.barnesg`). **Examples** The first few superfactorials are (OEIS A000178):: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(10): ... print("%s %s" % (n, superfac(n))) ... 0 1.0 1 1.0 2 2.0 3 12.0 4 288.0 5 34560.0 6 24883200.0 7 125411328000.0 8 5.05658474496e+15 9 1.83493347225108e+21 Superfactorials grow very rapidly:: >>> superfac(1000) 3.24570818422368e+1177245 >>> superfac(10**10) 2.61398543581249e+467427913956904067453 Evaluation is supported for arbitrary arguments:: >>> mp.dps = 25 >>> superfac(pi) 17.20051550121297985285333 >>> superfac(2+3j) (-0.005915485633199789627466468 + 0.008156449464604044948738263j) >>> diff(superfac, 1) 0.2645072034016070205673056 **References** 1. http://oeis.org/A000178 """ hyperfac = r""" Computes the hyperfactorial, defined for integers as the product .. math :: H(n) = \prod_{k=1}^n k^k. The hyperfactorial satisfies the recurrence formula `H(z) = z^z H(z-1)`. It can be defined more generally in terms of the Barnes G-function (see :func:`~mpmath.barnesg`) and the gamma function by the formula .. math :: H(z) = \frac{\Gamma(z+1)^z}{G(z)}. The extension to complex numbers can also be done via the integral representation .. math :: H(z) = (2\pi)^{-z/2} \exp \left[ {z+1 \choose 2} + \int_0^z \log(t!)\,dt \right]. **Examples** The rapidly-growing sequence of hyperfactorials begins (OEIS A002109):: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(10): ... print("%s %s" % (n, hyperfac(n))) ... 0 1.0 1 1.0 2 4.0 3 108.0 4 27648.0 5 86400000.0 6 4031078400000.0 7 3.3197663987712e+18 8 5.56964379417266e+25 9 2.15779412229419e+34 Some even larger hyperfactorials are:: >>> hyperfac(1000) 5.46458120882585e+1392926 >>> hyperfac(10**10) 4.60408207642219e+489142638002418704309 The hyperfactorial can be evaluated for arbitrary arguments:: >>> hyperfac(0.5) 0.880449235173423 >>> diff(hyperfac, 1) 0.581061466795327 >>> hyperfac(pi) 205.211134637462 >>> hyperfac(-10+1j) (3.01144471378225e+46 - 2.45285242480185e+46j) The recurrence property of the hyperfactorial holds generally:: >>> z = 3-4*j >>> hyperfac(z) (-4.49795891462086e-7 - 6.33262283196162e-7j) >>> z**z * hyperfac(z-1) (-4.49795891462086e-7 - 6.33262283196162e-7j) >>> z = mpf(-0.6) >>> chop(z**z * hyperfac(z-1)) 1.28170142849352 >>> hyperfac(z) 1.28170142849352 The hyperfactorial may also be computed using the integral definition:: >>> z = 2.5 >>> hyperfac(z) 15.9842119922237 >>> (2*pi)**(-z/2)*exp(binomial(z+1,2) + ... quad(lambda t: loggamma(t+1), [0, z])) 15.9842119922237 :func:`~mpmath.hyperfac` supports arbitrary-precision evaluation:: >>> mp.dps = 50 >>> hyperfac(10) 215779412229418562091680268288000000000000000.0 >>> hyperfac(1/sqrt(2)) 0.89404818005227001975423476035729076375705084390942 **References** 1. http://oeis.org/A002109 2. http://mathworld.wolfram.com/Hyperfactorial.html """ rgamma = r""" Computes the reciprocal of the gamma function, `1/\Gamma(z)`. This function evaluates to zero at the poles of the gamma function, `z = 0, -1, -2, \ldots`. **Examples** Basic examples:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> rgamma(1) 1.0 >>> rgamma(4) 0.1666666666666666666666667 >>> rgamma(0); rgamma(-1) 0.0 0.0 >>> rgamma(1000) 2.485168143266784862783596e-2565 >>> rgamma(inf) 0.0 A definite integral that can be evaluated in terms of elementary integrals:: >>> quad(rgamma, [0,inf]) 2.807770242028519365221501 >>> e + quad(lambda t: exp(-t)/(pi**2+log(t)**2), [0,inf]) 2.807770242028519365221501 """ loggamma = r""" Computes the principal branch of the log-gamma function, `\ln \Gamma(z)`. Unlike `\ln(\Gamma(z))`, which has infinitely many complex branch cuts, the principal log-gamma function only has a single branch cut along the negative half-axis. The principal branch continuously matches the asymptotic Stirling expansion .. math :: \ln \Gamma(z) \sim \frac{\ln(2 \pi)}{2} + \left(z-\frac{1}{2}\right) \ln(z) - z + O(z^{-1}). The real parts of both functions agree, but their imaginary parts generally differ by `2 n \pi` for some `n \in \mathbb{Z}`. They coincide for `z \in \mathbb{R}, z > 0`. Computationally, it is advantageous to use :func:`~mpmath.loggamma` instead of :func:`~mpmath.gamma` for extremely large arguments. **Examples** Comparing with `\ln(\Gamma(z))`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> loggamma('13.2'); log(gamma('13.2')) 20.49400419456603678498394 20.49400419456603678498394 >>> loggamma(3+4j) (-1.756626784603784110530604 + 4.742664438034657928194889j) >>> log(gamma(3+4j)) (-1.756626784603784110530604 - 1.540520869144928548730397j) >>> log(gamma(3+4j)) + 2*pi*j (-1.756626784603784110530604 + 4.742664438034657928194889j) Note the imaginary parts for negative arguments:: >>> loggamma(-0.5); loggamma(-1.5); loggamma(-2.5) (1.265512123484645396488946 - 3.141592653589793238462643j) (0.8600470153764810145109327 - 6.283185307179586476925287j) (-0.05624371649767405067259453 - 9.42477796076937971538793j) Some special values:: >>> loggamma(1); loggamma(2) 0.0 0.0 >>> loggamma(3); +ln2 0.6931471805599453094172321 0.6931471805599453094172321 >>> loggamma(3.5); log(15*sqrt(pi)/8) 1.200973602347074224816022 1.200973602347074224816022 >>> loggamma(inf) +inf Huge arguments are permitted:: >>> loggamma('1e30') 6.807755278982137052053974e+31 >>> loggamma('1e300') 6.897755278982137052053974e+302 >>> loggamma('1e3000') 6.906755278982137052053974e+3003 >>> loggamma('1e100000000000000000000') 2.302585092994045684007991e+100000000000000000020 >>> loggamma('1e30j') (-1.570796326794896619231322e+30 + 6.807755278982137052053974e+31j) >>> loggamma('1e300j') (-1.570796326794896619231322e+300 + 6.897755278982137052053974e+302j) >>> loggamma('1e3000j') (-1.570796326794896619231322e+3000 + 6.906755278982137052053974e+3003j) The log-gamma function can be integrated analytically on any interval of unit length:: >>> z = 0 >>> quad(loggamma, [z,z+1]); log(2*pi)/2 0.9189385332046727417803297 0.9189385332046727417803297 >>> z = 3+4j >>> quad(loggamma, [z,z+1]); (log(z)-1)*z + log(2*pi)/2 (-0.9619286014994750641314421 + 5.219637303741238195688575j) (-0.9619286014994750641314421 + 5.219637303741238195688575j) The derivatives of the log-gamma function are given by the polygamma function (:func:`~mpmath.psi`):: >>> diff(loggamma, -4+3j); psi(0, -4+3j) (1.688493531222971393607153 + 2.554898911356806978892748j) (1.688493531222971393607153 + 2.554898911356806978892748j) >>> diff(loggamma, -4+3j, 2); psi(1, -4+3j) (-0.1539414829219882371561038 - 0.1020485197430267719746479j) (-0.1539414829219882371561038 - 0.1020485197430267719746479j) The log-gamma function satisfies an additive form of the recurrence relation for the ordinary gamma function:: >>> z = 2+3j >>> loggamma(z); loggamma(z+1) - log(z) (-2.092851753092733349564189 + 2.302396543466867626153708j) (-2.092851753092733349564189 + 2.302396543466867626153708j) """ siegeltheta = r""" Computes the Riemann-Siegel theta function, .. math :: \theta(t) = \frac{ \log\Gamma\left(\frac{1+2it}{4}\right) - \log\Gamma\left(\frac{1-2it}{4}\right) }{2i} - \frac{\log \pi}{2} t. The Riemann-Siegel theta function is important in providing the phase factor for the Z-function (see :func:`~mpmath.siegelz`). Evaluation is supported for real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> siegeltheta(0) 0.0 >>> siegeltheta(inf) +inf >>> siegeltheta(-inf) -inf >>> siegeltheta(1) -1.767547952812290388302216 >>> siegeltheta(10+0.25j) (-3.068638039426838572528867 + 0.05804937947429712998395177j) Arbitrary derivatives may be computed with derivative = k >>> siegeltheta(1234, derivative=2) 0.0004051864079114053109473741 >>> diff(siegeltheta, 1234, n=2) 0.0004051864079114053109473741 The Riemann-Siegel theta function has odd symmetry around `t = 0`, two local extreme points and three real roots including 0 (located symmetrically):: >>> nprint(chop(taylor(siegeltheta, 0, 5))) [0.0, -2.68609, 0.0, 2.69433, 0.0, -6.40218] >>> findroot(diffun(siegeltheta), 7) 6.28983598883690277966509 >>> findroot(siegeltheta, 20) 17.84559954041086081682634 For large `t`, there is a famous asymptotic formula for `\theta(t)`, to first order given by:: >>> t = mpf(10**6) >>> siegeltheta(t) 5488816.353078403444882823 >>> -t*log(2*pi/t)/2-t/2 5488816.745777464310273645 """ grampoint = r""" Gives the `n`-th Gram point `g_n`, defined as the solution to the equation `\theta(g_n) = \pi n` where `\theta(t)` is the Riemann-Siegel theta function (:func:`~mpmath.siegeltheta`). The first few Gram points are:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> grampoint(0) 17.84559954041086081682634 >>> grampoint(1) 23.17028270124630927899664 >>> grampoint(2) 27.67018221781633796093849 >>> grampoint(3) 31.71797995476405317955149 Checking the definition:: >>> siegeltheta(grampoint(3)) 9.42477796076937971538793 >>> 3*pi 9.42477796076937971538793 A large Gram point:: >>> grampoint(10**10) 3293531632.728335454561153 Gram points are useful when studying the Z-function (:func:`~mpmath.siegelz`). See the documentation of that function for additional examples. :func:`~mpmath.grampoint` can solve the defining equation for nonintegral `n`. There is a fixed point where `g(x) = x`:: >>> findroot(lambda x: grampoint(x) - x, 10000) 9146.698193171459265866198 **References** 1. http://mathworld.wolfram.com/GramPoint.html """ siegelz = r""" Computes the Z-function, also known as the Riemann-Siegel Z function, .. math :: Z(t) = e^{i \theta(t)} \zeta(1/2+it) where `\zeta(s)` is the Riemann zeta function (:func:`~mpmath.zeta`) and where `\theta(t)` denotes the Riemann-Siegel theta function (see :func:`~mpmath.siegeltheta`). Evaluation is supported for real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> siegelz(1) -0.7363054628673177346778998 >>> siegelz(3+4j) (-0.1852895764366314976003936 - 0.2773099198055652246992479j) The first four derivatives are supported, using the optional *derivative* keyword argument:: >>> siegelz(1234567, derivative=3) 56.89689348495089294249178 >>> diff(siegelz, 1234567, n=3) 56.89689348495089294249178 The Z-function has a Maclaurin expansion:: >>> nprint(chop(taylor(siegelz, 0, 4))) [-1.46035, 0.0, 2.73588, 0.0, -8.39357] The Z-function `Z(t)` is equal to `\pm |\zeta(s)|` on the critical line `s = 1/2+it` (i.e. for real arguments `t` to `Z`). Its zeros coincide with those of the Riemann zeta function:: >>> findroot(siegelz, 14) 14.13472514173469379045725 >>> findroot(siegelz, 20) 21.02203963877155499262848 >>> findroot(zeta, 0.5+14j) (0.5 + 14.13472514173469379045725j) >>> findroot(zeta, 0.5+20j) (0.5 + 21.02203963877155499262848j) Since the Z-function is real-valued on the critical line (and unlike `|\zeta(s)|` analytic), it is useful for investigating the zeros of the Riemann zeta function. For example, one can use a root-finding algorithm based on sign changes:: >>> findroot(siegelz, [100, 200], solver='bisect') 176.4414342977104188888926 To locate roots, Gram points `g_n` which can be computed by :func:`~mpmath.grampoint` are useful. If `(-1)^n Z(g_n)` is positive for two consecutive `n`, then `Z(t)` must have a zero between those points:: >>> g10 = grampoint(10) >>> g11 = grampoint(11) >>> (-1)**10 * siegelz(g10) > 0 True >>> (-1)**11 * siegelz(g11) > 0 True >>> findroot(siegelz, [g10, g11], solver='bisect') 56.44624769706339480436776 >>> g10, g11 (54.67523744685325626632663, 57.54516517954725443703014) """ riemannr = r""" Evaluates the Riemann R function, a smooth approximation of the prime counting function `\pi(x)` (see :func:`~mpmath.primepi`). The Riemann R function gives a fast numerical approximation useful e.g. to roughly estimate the number of primes in a given interval. The Riemann R function is computed using the rapidly convergent Gram series, .. math :: R(x) = 1 + \sum_{k=1}^{\infty} \frac{\log^k x}{k k! \zeta(k+1)}. From the Gram series, one sees that the Riemann R function is a well-defined analytic function (except for a branch cut along the negative real half-axis); it can be evaluated for arbitrary real or complex arguments. The Riemann R function gives a very accurate approximation of the prime counting function. For example, it is wrong by at most 2 for `x < 1000`, and for `x = 10^9` differs from the exact value of `\pi(x)` by 79, or less than two parts in a million. It is about 10 times more accurate than the logarithmic integral estimate (see :func:`~mpmath.li`), which however is even faster to evaluate. It is orders of magnitude more accurate than the extremely fast `x/\log x` estimate. **Examples** For small arguments, the Riemann R function almost exactly gives the prime counting function if rounded to the nearest integer:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> primepi(50), riemannr(50) (15, 14.9757023241462) >>> max(abs(primepi(n)-int(round(riemannr(n)))) for n in range(100)) 1 >>> max(abs(primepi(n)-int(round(riemannr(n)))) for n in range(300)) 2 The Riemann R function can be evaluated for arguments far too large for exact determination of `\pi(x)` to be computationally feasible with any presently known algorithm:: >>> riemannr(10**30) 1.46923988977204e+28 >>> riemannr(10**100) 4.3619719871407e+97 >>> riemannr(10**1000) 4.3448325764012e+996 A comparison of the Riemann R function and logarithmic integral estimates for `\pi(x)` using exact values of `\pi(10^n)` up to `n = 9`. The fractional error is shown in parentheses:: >>> exact = [4,25,168,1229,9592,78498,664579,5761455,50847534] >>> for n, p in enumerate(exact): ... n += 1 ... r, l = riemannr(10**n), li(10**n) ... rerr, lerr = nstr((r-p)/p,3), nstr((l-p)/p,3) ... print("%i %i %s(%s) %s(%s)" % (n, p, r, rerr, l, lerr)) ... 1 4 4.56458314100509(0.141) 6.1655995047873(0.541) 2 25 25.6616332669242(0.0265) 30.1261415840796(0.205) 3 168 168.359446281167(0.00214) 177.609657990152(0.0572) 4 1229 1226.93121834343(-0.00168) 1246.13721589939(0.0139) 5 9592 9587.43173884197(-0.000476) 9629.8090010508(0.00394) 6 78498 78527.3994291277(0.000375) 78627.5491594622(0.00165) 7 664579 664667.447564748(0.000133) 664918.405048569(0.000511) 8 5761455 5761551.86732017(1.68e-5) 5762209.37544803(0.000131) 9 50847534 50847455.4277214(-1.55e-6) 50849234.9570018(3.35e-5) The derivative of the Riemann R function gives the approximate probability for a number of magnitude `x` to be prime:: >>> diff(riemannr, 1000) 0.141903028110784 >>> mpf(primepi(1050) - primepi(950)) / 100 0.15 Evaluation is supported for arbitrary arguments and at arbitrary precision:: >>> mp.dps = 30 >>> riemannr(7.5) 3.72934743264966261918857135136 >>> riemannr(-4+2j) (-0.551002208155486427591793957644 + 2.16966398138119450043195899746j) """ primepi = r""" Evaluates the prime counting function, `\pi(x)`, which gives the number of primes less than or equal to `x`. The argument `x` may be fractional. The prime counting function is very expensive to evaluate precisely for large `x`, and the present implementation is not optimized in any way. For numerical approximation of the prime counting function, it is better to use :func:`~mpmath.primepi2` or :func:`~mpmath.riemannr`. Some values of the prime counting function:: >>> from mpmath import * >>> [primepi(k) for k in range(20)] [0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8] >>> primepi(3.5) 2 >>> primepi(100000) 9592 """ primepi2 = r""" Returns an interval (as an ``mpi`` instance) providing bounds for the value of the prime counting function `\pi(x)`. For small `x`, :func:`~mpmath.primepi2` returns an exact interval based on the output of :func:`~mpmath.primepi`. For `x > 2656`, a loose interval based on Schoenfeld's inequality .. math :: |\pi(x) - \mathrm{li}(x)| < \frac{\sqrt x \log x}{8 \pi} is returned. This estimate is rigorous assuming the truth of the Riemann hypothesis, and can be computed very quickly. **Examples** Exact values of the prime counting function for small `x`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> iv.dps = 15; iv.pretty = True >>> primepi2(10) [4.0, 4.0] >>> primepi2(100) [25.0, 25.0] >>> primepi2(1000) [168.0, 168.0] Loose intervals are generated for moderately large `x`: >>> primepi2(10000), primepi(10000) ([1209.0, 1283.0], 1229) >>> primepi2(50000), primepi(50000) ([5070.0, 5263.0], 5133) As `x` increases, the absolute error gets worse while the relative error improves. The exact value of `\pi(10^{23})` is 1925320391606803968923, and :func:`~mpmath.primepi2` gives 9 significant digits:: >>> p = primepi2(10**23) >>> p [1.9253203909477020467e+21, 1.925320392280406229e+21] >>> mpf(p.delta) / mpf(p.a) 6.9219865355293e-10 A more precise, nonrigorous estimate for `\pi(x)` can be obtained using the Riemann R function (:func:`~mpmath.riemannr`). For large enough `x`, the value returned by :func:`~mpmath.primepi2` essentially amounts to a small perturbation of the value returned by :func:`~mpmath.riemannr`:: >>> primepi2(10**100) [4.3619719871407024816e+97, 4.3619719871407032404e+97] >>> riemannr(10**100) 4.3619719871407e+97 """ primezeta = r""" Computes the prime zeta function, which is defined in analogy with the Riemann zeta function (:func:`~mpmath.zeta`) as .. math :: P(s) = \sum_p \frac{1}{p^s} where the sum is taken over all prime numbers `p`. Although this sum only converges for `\mathrm{Re}(s) > 1`, the function is defined by analytic continuation in the half-plane `\mathrm{Re}(s) > 0`. **Examples** Arbitrary-precision evaluation for real and complex arguments is supported:: >>> from mpmath import * >>> mp.dps = 30; mp.pretty = True >>> primezeta(2) 0.452247420041065498506543364832 >>> primezeta(pi) 0.15483752698840284272036497397 >>> mp.dps = 50 >>> primezeta(3) 0.17476263929944353642311331466570670097541212192615 >>> mp.dps = 20 >>> primezeta(3+4j) (-0.12085382601645763295 - 0.013370403397787023602j) The prime zeta function has a logarithmic pole at `s = 1`, with residue equal to the difference of the Mertens and Euler constants:: >>> primezeta(1) +inf >>> extradps(25)(lambda x: primezeta(1+x)+log(x))(+eps) -0.31571845205389007685 >>> mertens-euler -0.31571845205389007685 The analytic continuation to `0 < \mathrm{Re}(s) \le 1` is implemented. In this strip the function exhibits very complex behavior; on the unit interval, it has poles at `1/n` for every squarefree integer `n`:: >>> primezeta(0.5) # Pole at s = 1/2 (-inf + 3.1415926535897932385j) >>> primezeta(0.25) (-1.0416106801757269036 + 0.52359877559829887308j) >>> primezeta(0.5+10j) (0.54892423556409790529 + 0.45626803423487934264j) Although evaluation works in principle for any `\mathrm{Re}(s) > 0`, it should be noted that the evaluation time increases exponentially as `s` approaches the imaginary axis. For large `\mathrm{Re}(s)`, `P(s)` is asymptotic to `2^{-s}`:: >>> primezeta(inf) 0.0 >>> primezeta(10), mpf(2)**-10 (0.00099360357443698021786, 0.0009765625) >>> primezeta(1000) 9.3326361850321887899e-302 >>> primezeta(1000+1000j) (-3.8565440833654995949e-302 - 8.4985390447553234305e-302j) **References** Carl-Erik Froberg, "On the prime zeta function", BIT 8 (1968), pp. 187-202. """ bernpoly = r""" Evaluates the Bernoulli polynomial `B_n(z)`. The first few Bernoulli polynomials are:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(6): ... nprint(chop(taylor(lambda x: bernpoly(n,x), 0, n))) ... [1.0] [-0.5, 1.0] [0.166667, -1.0, 1.0] [0.0, 0.5, -1.5, 1.0] [-0.0333333, 0.0, 1.0, -2.0, 1.0] [0.0, -0.166667, 0.0, 1.66667, -2.5, 1.0] At `z = 0`, the Bernoulli polynomial evaluates to a Bernoulli number (see :func:`~mpmath.bernoulli`):: >>> bernpoly(12, 0), bernoulli(12) (-0.253113553113553, -0.253113553113553) >>> bernpoly(13, 0), bernoulli(13) (0.0, 0.0) Evaluation is accurate for large `n` and small `z`:: >>> mp.dps = 25 >>> bernpoly(100, 0.5) 2.838224957069370695926416e+78 >>> bernpoly(1000, 10.5) 5.318704469415522036482914e+1769 """ polylog = r""" Computes the polylogarithm, defined by the sum .. math :: \mathrm{Li}_s(z) = \sum_{k=1}^{\infty} \frac{z^k}{k^s}. This series is convergent only for `|z| < 1`, so elsewhere the analytic continuation is implied. The polylogarithm should not be confused with the logarithmic integral (also denoted by Li or li), which is implemented as :func:`~mpmath.li`. **Examples** The polylogarithm satisfies a huge number of functional identities. A sample of polylogarithm evaluations is shown below:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> polylog(1,0.5), log(2) (0.693147180559945, 0.693147180559945) >>> polylog(2,0.5), (pi**2-6*log(2)**2)/12 (0.582240526465012, 0.582240526465012) >>> polylog(2,-phi), -log(phi)**2-pi**2/10 (-1.21852526068613, -1.21852526068613) >>> polylog(3,0.5), 7*zeta(3)/8-pi**2*log(2)/12+log(2)**3/6 (0.53721319360804, 0.53721319360804) :func:`~mpmath.polylog` can evaluate the analytic continuation of the polylogarithm when `s` is an integer:: >>> polylog(2, 10) (0.536301287357863 - 7.23378441241546j) >>> polylog(2, -10) -4.1982778868581 >>> polylog(2, 10j) (-3.05968879432873 + 3.71678149306807j) >>> polylog(-2, 10) -0.150891632373114 >>> polylog(-2, -10) 0.067618332081142 >>> polylog(-2, 10j) (0.0384353698579347 + 0.0912451798066779j) Some more examples, with arguments on the unit circle (note that the series definition cannot be used for computation here):: >>> polylog(2,j) (-0.205616758356028 + 0.915965594177219j) >>> j*catalan-pi**2/48 (-0.205616758356028 + 0.915965594177219j) >>> polylog(3,exp(2*pi*j/3)) (-0.534247512515375 + 0.765587078525922j) >>> -4*zeta(3)/9 + 2*j*pi**3/81 (-0.534247512515375 + 0.765587078525921j) Polylogarithms of different order are related by integration and differentiation:: >>> s, z = 3, 0.5 >>> polylog(s+1, z) 0.517479061673899 >>> quad(lambda t: polylog(s,t)/t, [0, z]) 0.517479061673899 >>> z*diff(lambda t: polylog(s+2,t), z) 0.517479061673899 Taylor series expansions around `z = 0` are:: >>> for n in range(-3, 4): ... nprint(taylor(lambda x: polylog(n,x), 0, 5)) ... [0.0, 1.0, 8.0, 27.0, 64.0, 125.0] [0.0, 1.0, 4.0, 9.0, 16.0, 25.0] [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] [0.0, 1.0, 1.0, 1.0, 1.0, 1.0] [0.0, 1.0, 0.5, 0.333333, 0.25, 0.2] [0.0, 1.0, 0.25, 0.111111, 0.0625, 0.04] [0.0, 1.0, 0.125, 0.037037, 0.015625, 0.008] The series defining the polylogarithm is simultaneously a Taylor series and an L-series. For certain values of `z`, the polylogarithm reduces to a pure zeta function:: >>> polylog(pi, 1), zeta(pi) (1.17624173838258, 1.17624173838258) >>> polylog(pi, -1), -altzeta(pi) (-0.909670702980385, -0.909670702980385) Evaluation for arbitrary, nonintegral `s` is supported for `z` within the unit circle: >>> polylog(3+4j, 0.25) (0.24258605789446 - 0.00222938275488344j) >>> nsum(lambda k: 0.25**k / k**(3+4j), [1,inf]) (0.24258605789446 - 0.00222938275488344j) It is also supported outside of the unit circle:: >>> polylog(1+j, 20+40j) (-7.1421172179728 - 3.92726697721369j) >>> polylog(1+j, 200+400j) (-5.41934747194626 - 9.94037752563927j) **References** 1. Richard Crandall, "Note on fast polylogarithm computation" http://people.reed.edu/~crandall/papers/Polylog.pdf 2. http://en.wikipedia.org/wiki/Polylogarithm 3. http://mathworld.wolfram.com/Polylogarithm.html """ bell = r""" For `n` a nonnegative integer, ``bell(n,x)`` evaluates the Bell polynomial `B_n(x)`, the first few of which are .. math :: B_0(x) = 1 B_1(x) = x B_2(x) = x^2+x B_3(x) = x^3+3x^2+x If `x = 1` or :func:`~mpmath.bell` is called with only one argument, it gives the `n`-th Bell number `B_n`, which is the number of partitions of a set with `n` elements. By setting the precision to at least `\log_{10} B_n` digits, :func:`~mpmath.bell` provides fast calculation of exact Bell numbers. In general, :func:`~mpmath.bell` computes .. math :: B_n(x) = e^{-x} \left(\mathrm{sinc}(\pi n) + E_n(x)\right) where `E_n(x)` is the generalized exponential function implemented by :func:`~mpmath.polyexp`. This is an extension of Dobinski's formula [1], where the modification is the sinc term ensuring that `B_n(x)` is continuous in `n`; :func:`~mpmath.bell` can thus be evaluated, differentiated, etc for arbitrary complex arguments. **Examples** Simple evaluations:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> bell(0, 2.5) 1.0 >>> bell(1, 2.5) 2.5 >>> bell(2, 2.5) 8.75 Evaluation for arbitrary complex arguments:: >>> bell(5.75+1j, 2-3j) (-10767.71345136587098445143 - 15449.55065599872579097221j) The first few Bell polynomials:: >>> for k in range(7): ... nprint(taylor(lambda x: bell(k,x), 0, k)) ... [1.0] [0.0, 1.0] [0.0, 1.0, 1.0] [0.0, 1.0, 3.0, 1.0] [0.0, 1.0, 7.0, 6.0, 1.0] [0.0, 1.0, 15.0, 25.0, 10.0, 1.0] [0.0, 1.0, 31.0, 90.0, 65.0, 15.0, 1.0] The first few Bell numbers and complementary Bell numbers:: >>> [int(bell(k)) for k in range(10)] [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147] >>> [int(bell(k,-1)) for k in range(10)] [1, -1, 0, 1, 1, -2, -9, -9, 50, 267] Large Bell numbers:: >>> mp.dps = 50 >>> bell(50) 185724268771078270438257767181908917499221852770.0 >>> bell(50,-1) -29113173035759403920216141265491160286912.0 Some even larger values:: >>> mp.dps = 25 >>> bell(1000,-1) -1.237132026969293954162816e+1869 >>> bell(1000) 2.989901335682408421480422e+1927 >>> bell(1000,2) 6.591553486811969380442171e+1987 >>> bell(1000,100.5) 9.101014101401543575679639e+2529 A determinant identity satisfied by Bell numbers:: >>> mp.dps = 15 >>> N = 8 >>> det([[bell(k+j) for j in range(N)] for k in range(N)]) 125411328000.0 >>> superfac(N-1) 125411328000.0 **References** 1. http://mathworld.wolfram.com/DobinskisFormula.html """ polyexp = r""" Evaluates the polyexponential function, defined for arbitrary complex `s`, `z` by the series .. math :: E_s(z) = \sum_{k=1}^{\infty} \frac{k^s}{k!} z^k. `E_s(z)` is constructed from the exponential function analogously to how the polylogarithm is constructed from the ordinary logarithm; as a function of `s` (with `z` fixed), `E_s` is an L-series It is an entire function of both `s` and `z`. The polyexponential function provides a generalization of the Bell polynomials `B_n(x)` (see :func:`~mpmath.bell`) to noninteger orders `n`. In terms of the Bell polynomials, .. math :: E_s(z) = e^z B_s(z) - \mathrm{sinc}(\pi s). Note that `B_n(x)` and `e^{-x} E_n(x)` are identical if `n` is a nonzero integer, but not otherwise. In particular, they differ at `n = 0`. **Examples** Evaluating a series:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> nsum(lambda k: sqrt(k)/fac(k), [1,inf]) 2.101755547733791780315904 >>> polyexp(0.5,1) 2.101755547733791780315904 Evaluation for arbitrary arguments:: >>> polyexp(-3-4j, 2.5+2j) (2.351660261190434618268706 + 1.202966666673054671364215j) Evaluation is accurate for tiny function values:: >>> polyexp(4, -100) 3.499471750566824369520223e-36 If `n` is a nonpositive integer, `E_n` reduces to a special instance of the hypergeometric function `\,_pF_q`:: >>> n = 3 >>> x = pi >>> polyexp(-n,x) 4.042192318847986561771779 >>> x*hyper([1]*(n+1), [2]*(n+1), x) 4.042192318847986561771779 """ cyclotomic = r""" Evaluates the cyclotomic polynomial `\Phi_n(x)`, defined by .. math :: \Phi_n(x) = \prod_{\zeta} (x - \zeta) where `\zeta` ranges over all primitive `n`-th roots of unity (see :func:`~mpmath.unitroots`). An equivalent representation, used for computation, is .. math :: \Phi_n(x) = \prod_{d\mid n}(x^d-1)^{\mu(n/d)} = \Phi_n(x) where `\mu(m)` denotes the Moebius function. The cyclotomic polynomials are integer polynomials, the first of which can be written explicitly as .. math :: \Phi_0(x) = 1 \Phi_1(x) = x - 1 \Phi_2(x) = x + 1 \Phi_3(x) = x^3 + x^2 + 1 \Phi_4(x) = x^2 + 1 \Phi_5(x) = x^4 + x^3 + x^2 + x + 1 \Phi_6(x) = x^2 - x + 1 **Examples** The coefficients of low-order cyclotomic polynomials can be recovered using Taylor expansion:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> for n in range(9): ... p = chop(taylor(lambda x: cyclotomic(n,x), 0, 10)) ... print("%s %s" % (n, nstr(p[:10+1-p[::-1].index(1)]))) ... 0 [1.0] 1 [-1.0, 1.0] 2 [1.0, 1.0] 3 [1.0, 1.0, 1.0] 4 [1.0, 0.0, 1.0] 5 [1.0, 1.0, 1.0, 1.0, 1.0] 6 [1.0, -1.0, 1.0] 7 [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] 8 [1.0, 0.0, 0.0, 0.0, 1.0] The definition as a product over primitive roots may be checked by computing the product explicitly (for a real argument, this method will generally introduce numerical noise in the imaginary part):: >>> mp.dps = 25 >>> z = 3+4j >>> cyclotomic(10, z) (-419.0 - 360.0j) >>> fprod(z-r for r in unitroots(10, primitive=True)) (-419.0 - 360.0j) >>> z = 3 >>> cyclotomic(10, z) 61.0 >>> fprod(z-r for r in unitroots(10, primitive=True)) (61.0 - 3.146045605088568607055454e-25j) Up to permutation, the roots of a given cyclotomic polynomial can be checked to agree with the list of primitive roots:: >>> p = taylor(lambda x: cyclotomic(6,x), 0, 6)[:3] >>> for r in polyroots(p[::-1]): ... print(r) ... (0.5 - 0.8660254037844386467637232j) (0.5 + 0.8660254037844386467637232j) >>> >>> for r in unitroots(6, primitive=True): ... print(r) ... (0.5 + 0.8660254037844386467637232j) (0.5 - 0.8660254037844386467637232j) """ meijerg = r""" Evaluates the Meijer G-function, defined as .. math :: G^{m,n}_{p,q} \left( \left. \begin{matrix} a_1, \dots, a_n ; a_{n+1} \dots a_p \\ b_1, \dots, b_m ; b_{m+1} \dots b_q \end{matrix}\; \right| \; z ; r \right) = \frac{1}{2 \pi i} \int_L \frac{\prod_{j=1}^m \Gamma(b_j+s) \prod_{j=1}^n\Gamma(1-a_j-s)} {\prod_{j=n+1}^{p}\Gamma(a_j+s) \prod_{j=m+1}^q \Gamma(1-b_j-s)} z^{-s/r} ds for an appropriate choice of the contour `L` (see references). There are `p` elements `a_j`. The argument *a_s* should be a pair of lists, the first containing the `n` elements `a_1, \ldots, a_n` and the second containing the `p-n` elements `a_{n+1}, \ldots a_p`. There are `q` elements `b_j`. The argument *b_s* should be a pair of lists, the first containing the `m` elements `b_1, \ldots, b_m` and the second containing the `q-m` elements `b_{m+1}, \ldots b_q`. The implicit tuple `(m, n, p, q)` constitutes the order or degree of the Meijer G-function, and is determined by the lengths of the coefficient vectors. Confusingly, the indices in this tuple appear in a different order from the coefficients, but this notation is standard. The many examples given below should hopefully clear up any potential confusion. **Algorithm** The Meijer G-function is evaluated as a combination of hypergeometric series. There are two versions of the function, which can be selected with the optional *series* argument. *series=1* uses a sum of `m` `\,_pF_{q-1}` functions of `z` *series=2* uses a sum of `n` `\,_qF_{p-1}` functions of `1/z` The default series is chosen based on the degree and `|z|` in order to be consistent with Mathematica's. This definition of the Meijer G-function has a discontinuity at `|z| = 1` for some orders, which can be avoided by explicitly specifying a series. Keyword arguments are forwarded to :func:`~mpmath.hypercomb`. **Examples** Many standard functions are special cases of the Meijer G-function (possibly rescaled and/or with branch cut corrections). We define some test parameters:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a = mpf(0.75) >>> b = mpf(1.5) >>> z = mpf(2.25) The exponential function: `e^z = G^{1,0}_{0,1} \left( \left. \begin{matrix} - \\ 0 \end{matrix} \; \right| \; -z \right)` >>> meijerg([[],[]], [[0],[]], -z) 9.487735836358525720550369 >>> exp(z) 9.487735836358525720550369 The natural logarithm: `\log(1+z) = G^{1,2}_{2,2} \left( \left. \begin{matrix} 1, 1 \\ 1, 0 \end{matrix} \; \right| \; -z \right)` >>> meijerg([[1,1],[]], [[1],[0]], z) 1.178654996341646117219023 >>> log(1+z) 1.178654996341646117219023 A rational function: `\frac{z}{z+1} = G^{1,2}_{2,2} \left( \left. \begin{matrix} 1, 1 \\ 1, 1 \end{matrix} \; \right| \; z \right)` >>> meijerg([[1,1],[]], [[1],[1]], z) 0.6923076923076923076923077 >>> z/(z+1) 0.6923076923076923076923077 The sine and cosine functions: `\frac{1}{\sqrt \pi} \sin(2 \sqrt z) = G^{1,0}_{0,2} \left( \left. \begin{matrix} - \\ \frac{1}{2}, 0 \end{matrix} \; \right| \; z \right)` `\frac{1}{\sqrt \pi} \cos(2 \sqrt z) = G^{1,0}_{0,2} \left( \left. \begin{matrix} - \\ 0, \frac{1}{2} \end{matrix} \; \right| \; z \right)` >>> meijerg([[],[]], [[0.5],[0]], (z/2)**2) 0.4389807929218676682296453 >>> sin(z)/sqrt(pi) 0.4389807929218676682296453 >>> meijerg([[],[]], [[0],[0.5]], (z/2)**2) -0.3544090145996275423331762 >>> cos(z)/sqrt(pi) -0.3544090145996275423331762 Bessel functions: `J_a(2 \sqrt z) = G^{1,0}_{0,2} \left( \left. \begin{matrix} - \\ \frac{a}{2}, -\frac{a}{2} \end{matrix} \; \right| \; z \right)` `Y_a(2 \sqrt z) = G^{2,0}_{1,3} \left( \left. \begin{matrix} \frac{-a-1}{2} \\ \frac{a}{2}, -\frac{a}{2}, \frac{-a-1}{2} \end{matrix} \; \right| \; z \right)` `(-z)^{a/2} z^{-a/2} I_a(2 \sqrt z) = G^{1,0}_{0,2} \left( \left. \begin{matrix} - \\ \frac{a}{2}, -\frac{a}{2} \end{matrix} \; \right| \; -z \right)` `2 K_a(2 \sqrt z) = G^{2,0}_{0,2} \left( \left. \begin{matrix} - \\ \frac{a}{2}, -\frac{a}{2} \end{matrix} \; \right| \; z \right)` As the example with the Bessel *I* function shows, a branch factor is required for some arguments when inverting the square root. >>> meijerg([[],[]], [[a/2],[-a/2]], (z/2)**2) 0.5059425789597154858527264 >>> besselj(a,z) 0.5059425789597154858527264 >>> meijerg([[],[(-a-1)/2]], [[a/2,-a/2],[(-a-1)/2]], (z/2)**2) 0.1853868950066556941442559 >>> bessely(a, z) 0.1853868950066556941442559 >>> meijerg([[],[]], [[a/2],[-a/2]], -(z/2)**2) (0.8685913322427653875717476 + 2.096964974460199200551738j) >>> (-z)**(a/2) / z**(a/2) * besseli(a, z) (0.8685913322427653875717476 + 2.096964974460199200551738j) >>> 0.5*meijerg([[],[]], [[a/2,-a/2],[]], (z/2)**2) 0.09334163695597828403796071 >>> besselk(a,z) 0.09334163695597828403796071 Error functions: `\sqrt{\pi} z^{2(a-1)} \mathrm{erfc}(z) = G^{2,0}_{1,2} \left( \left. \begin{matrix} a \\ a-1, a-\frac{1}{2} \end{matrix} \; \right| \; z, \frac{1}{2} \right)` >>> meijerg([[],[a]], [[a-1,a-0.5],[]], z, 0.5) 0.00172839843123091957468712 >>> sqrt(pi) * z**(2*a-2) * erfc(z) 0.00172839843123091957468712 A Meijer G-function of higher degree, (1,1,2,3): >>> meijerg([[a],[b]], [[a],[b,a-1]], z) 1.55984467443050210115617 >>> sin((b-a)*pi)/pi*(exp(z)-1)*z**(a-1) 1.55984467443050210115617 A Meijer G-function of still higher degree, (4,1,2,4), that can be expanded as a messy combination of exponential integrals: >>> meijerg([[a],[2*b-a]], [[b,a,b-0.5,-1-a+2*b],[]], z) 0.3323667133658557271898061 >>> chop(4**(a-b+1)*sqrt(pi)*gamma(2*b-2*a)*z**a*\ ... expint(2*b-2*a, -2*sqrt(-z))*expint(2*b-2*a, 2*sqrt(-z))) 0.3323667133658557271898061 In the following case, different series give different values:: >>> chop(meijerg([[1],[0.25]],[[3],[0.5]],-2)) -0.06417628097442437076207337 >>> meijerg([[1],[0.25]],[[3],[0.5]],-2,series=1) 0.1428699426155117511873047 >>> chop(meijerg([[1],[0.25]],[[3],[0.5]],-2,series=2)) -0.06417628097442437076207337 **References** 1. http://en.wikipedia.org/wiki/Meijer_G-function 2. http://mathworld.wolfram.com/MeijerG-Function.html 3. http://functions.wolfram.com/HypergeometricFunctions/MeijerG/ 4. http://functions.wolfram.com/HypergeometricFunctions/MeijerG1/ """ clsin = r""" Computes the Clausen sine function, defined formally by the series .. math :: \mathrm{Cl}_s(z) = \sum_{k=1}^{\infty} \frac{\sin(kz)}{k^s}. The special case `\mathrm{Cl}_2(z)` (i.e. ``clsin(2,z)``) is the classical "Clausen function". More generally, the Clausen function is defined for complex `s` and `z`, even when the series does not converge. The Clausen function is related to the polylogarithm (:func:`~mpmath.polylog`) as .. math :: \mathrm{Cl}_s(z) = \frac{1}{2i}\left(\mathrm{Li}_s\left(e^{iz}\right) - \mathrm{Li}_s\left(e^{-iz}\right)\right) = \mathrm{Im}\left[\mathrm{Li}_s(e^{iz})\right] \quad (s, z \in \mathbb{R}), and this representation can be taken to provide the analytic continuation of the series. The complementary function :func:`~mpmath.clcos` gives the corresponding cosine sum. **Examples** Evaluation for arbitrarily chosen `s` and `z`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> s, z = 3, 4 >>> clsin(s, z); nsum(lambda k: sin(z*k)/k**s, [1,inf]) -0.6533010136329338746275795 -0.6533010136329338746275795 Using `z + \pi` instead of `z` gives an alternating series:: >>> clsin(s, z+pi) 0.8860032351260589402871624 >>> nsum(lambda k: (-1)**k*sin(z*k)/k**s, [1,inf]) 0.8860032351260589402871624 With `s = 1`, the sum can be expressed in closed form using elementary functions:: >>> z = 1 + sqrt(3) >>> clsin(1, z) 0.2047709230104579724675985 >>> chop((log(1-exp(-j*z)) - log(1-exp(j*z)))/(2*j)) 0.2047709230104579724675985 >>> nsum(lambda k: sin(k*z)/k, [1,inf]) 0.2047709230104579724675985 The classical Clausen function `\mathrm{Cl}_2(\theta)` gives the value of the integral `\int_0^{\theta} -\ln(2\sin(x/2)) dx` for `0 < \theta < 2 \pi`:: >>> cl2 = lambda t: clsin(2, t) >>> cl2(3.5) -0.2465045302347694216534255 >>> -quad(lambda x: ln(2*sin(0.5*x)), [0, 3.5]) -0.2465045302347694216534255 This function is symmetric about `\theta = \pi` with zeros and extreme points:: >>> cl2(0); cl2(pi/3); chop(cl2(pi)); cl2(5*pi/3); chop(cl2(2*pi)) 0.0 1.014941606409653625021203 0.0 -1.014941606409653625021203 0.0 Catalan's constant is a special value:: >>> cl2(pi/2) 0.9159655941772190150546035 >>> +catalan 0.9159655941772190150546035 The Clausen sine function can be expressed in closed form when `s` is an odd integer (becoming zero when `s` < 0):: >>> z = 1 + sqrt(2) >>> clsin(1, z); (pi-z)/2 0.3636895456083490948304773 0.3636895456083490948304773 >>> clsin(3, z); pi**2/6*z - pi*z**2/4 + z**3/12 0.5661751584451144991707161 0.5661751584451144991707161 >>> clsin(-1, z) 0.0 >>> clsin(-3, z) 0.0 It can also be expressed in closed form for even integer `s \le 0`, providing a finite sum for series such as `\sin(z) + \sin(2z) + \sin(3z) + \ldots`:: >>> z = 1 + sqrt(2) >>> clsin(0, z) 0.1903105029507513881275865 >>> cot(z/2)/2 0.1903105029507513881275865 >>> clsin(-2, z) -0.1089406163841548817581392 >>> -cot(z/2)*csc(z/2)**2/4 -0.1089406163841548817581392 Call with ``pi=True`` to multiply `z` by `\pi` exactly:: >>> clsin(3, 3*pi) -8.892316224968072424732898e-26 >>> clsin(3, 3, pi=True) 0.0 Evaluation for complex `s`, `z` in a nonconvergent case:: >>> s, z = -1-j, 1+2j >>> clsin(s, z) (-0.593079480117379002516034 + 0.9038644233367868273362446j) >>> extraprec(20)(nsum)(lambda k: sin(k*z)/k**s, [1,inf]) (-0.593079480117379002516034 + 0.9038644233367868273362446j) """ clcos = r""" Computes the Clausen cosine function, defined formally by the series .. math :: \mathrm{\widetilde{Cl}}_s(z) = \sum_{k=1}^{\infty} \frac{\cos(kz)}{k^s}. This function is complementary to the Clausen sine function :func:`~mpmath.clsin`. In terms of the polylogarithm, .. math :: \mathrm{\widetilde{Cl}}_s(z) = \frac{1}{2}\left(\mathrm{Li}_s\left(e^{iz}\right) + \mathrm{Li}_s\left(e^{-iz}\right)\right) = \mathrm{Re}\left[\mathrm{Li}_s(e^{iz})\right] \quad (s, z \in \mathbb{R}). **Examples** Evaluation for arbitrarily chosen `s` and `z`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> s, z = 3, 4 >>> clcos(s, z); nsum(lambda k: cos(z*k)/k**s, [1,inf]) -0.6518926267198991308332759 -0.6518926267198991308332759 Using `z + \pi` instead of `z` gives an alternating series:: >>> s, z = 3, 0.5 >>> clcos(s, z+pi) -0.8155530586502260817855618 >>> nsum(lambda k: (-1)**k*cos(z*k)/k**s, [1,inf]) -0.8155530586502260817855618 With `s = 1`, the sum can be expressed in closed form using elementary functions:: >>> z = 1 + sqrt(3) >>> clcos(1, z) -0.6720334373369714849797918 >>> chop(-0.5*(log(1-exp(j*z))+log(1-exp(-j*z)))) -0.6720334373369714849797918 >>> -log(abs(2*sin(0.5*z))) # Equivalent to above when z is real -0.6720334373369714849797918 >>> nsum(lambda k: cos(k*z)/k, [1,inf]) -0.6720334373369714849797918 It can also be expressed in closed form when `s` is an even integer. For example, >>> clcos(2,z) -0.7805359025135583118863007 >>> pi**2/6 - pi*z/2 + z**2/4 -0.7805359025135583118863007 The case `s = 0` gives the renormalized sum of `\cos(z) + \cos(2z) + \cos(3z) + \ldots` (which happens to be the same for any value of `z`):: >>> clcos(0, z) -0.5 >>> nsum(lambda k: cos(k*z), [1,inf]) -0.5 Also the sums .. math :: \cos(z) + 2\cos(2z) + 3\cos(3z) + \ldots and .. math :: \cos(z) + 2^n \cos(2z) + 3^n \cos(3z) + \ldots for higher integer powers `n = -s` can be done in closed form. They are zero when `n` is positive and even (`s` negative and even):: >>> clcos(-1, z); 1/(2*cos(z)-2) -0.2607829375240542480694126 -0.2607829375240542480694126 >>> clcos(-3, z); (2+cos(z))*csc(z/2)**4/8 0.1472635054979944390848006 0.1472635054979944390848006 >>> clcos(-2, z); clcos(-4, z); clcos(-6, z) 0.0 0.0 0.0 With `z = \pi`, the series reduces to that of the Riemann zeta function (more generally, if `z = p \pi/q`, it is a finite sum over Hurwitz zeta function values):: >>> clcos(2.5, 0); zeta(2.5) 1.34148725725091717975677 1.34148725725091717975677 >>> clcos(2.5, pi); -altzeta(2.5) -0.8671998890121841381913472 -0.8671998890121841381913472 Call with ``pi=True`` to multiply `z` by `\pi` exactly:: >>> clcos(-3, 2*pi) 2.997921055881167659267063e+102 >>> clcos(-3, 2, pi=True) 0.008333333333333333333333333 Evaluation for complex `s`, `z` in a nonconvergent case:: >>> s, z = -1-j, 1+2j >>> clcos(s, z) (0.9407430121562251476136807 + 0.715826296033590204557054j) >>> extraprec(20)(nsum)(lambda k: cos(k*z)/k**s, [1,inf]) (0.9407430121562251476136807 + 0.715826296033590204557054j) """ whitm = r""" Evaluates the Whittaker function `M(k,m,z)`, which gives a solution to the Whittaker differential equation .. math :: \frac{d^2f}{dz^2} + \left(-\frac{1}{4}+\frac{k}{z}+ \frac{(\frac{1}{4}-m^2)}{z^2}\right) f = 0. A second solution is given by :func:`~mpmath.whitw`. The Whittaker functions are defined in Abramowitz & Stegun, section 13.1. They are alternate forms of the confluent hypergeometric functions `\,_1F_1` and `U`: .. math :: M(k,m,z) = e^{-\frac{1}{2}z} z^{\frac{1}{2}+m} \,_1F_1(\tfrac{1}{2}+m-k, 1+2m, z) W(k,m,z) = e^{-\frac{1}{2}z} z^{\frac{1}{2}+m} U(\tfrac{1}{2}+m-k, 1+2m, z). **Examples** Evaluation for arbitrary real and complex arguments is supported:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> whitm(1, 1, 1) 0.7302596799460411820509668 >>> whitm(1, 1, -1) (0.0 - 1.417977827655098025684246j) >>> whitm(j, j/2, 2+3j) (3.245477713363581112736478 - 0.822879187542699127327782j) >>> whitm(2, 3, 100000) 4.303985255686378497193063e+21707 Evaluation at zero:: >>> whitm(1,-1,0); whitm(1,-0.5,0); whitm(1,0,0) +inf nan 0.0 We can verify that :func:`~mpmath.whitm` numerically satisfies the differential equation for arbitrarily chosen values:: >>> k = mpf(0.25) >>> m = mpf(1.5) >>> f = lambda z: whitm(k,m,z) >>> for z in [-1, 2.5, 3, 1+2j]: ... chop(diff(f,z,2) + (-0.25 + k/z + (0.25-m**2)/z**2)*f(z)) ... 0.0 0.0 0.0 0.0 An integral involving both :func:`~mpmath.whitm` and :func:`~mpmath.whitw`, verifying evaluation along the real axis:: >>> quad(lambda x: exp(-x)*whitm(3,2,x)*whitw(1,-2,x), [0,inf]) 3.438869842576800225207341 >>> 128/(21*sqrt(pi)) 3.438869842576800225207341 """ whitw = r""" Evaluates the Whittaker function `W(k,m,z)`, which gives a second solution to the Whittaker differential equation. (See :func:`~mpmath.whitm`.) **Examples** Evaluation for arbitrary real and complex arguments is supported:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> whitw(1, 1, 1) 1.19532063107581155661012 >>> whitw(1, 1, -1) (-0.9424875979222187313924639 - 0.2607738054097702293308689j) >>> whitw(j, j/2, 2+3j) (0.1782899315111033879430369 - 0.01609578360403649340169406j) >>> whitw(2, 3, 100000) 1.887705114889527446891274e-21705 >>> whitw(-1, -1, 100) 1.905250692824046162462058e-24 Evaluation at zero:: >>> for m in [-1, -0.5, 0, 0.5, 1]: ... whitw(1, m, 0) ... +inf nan 0.0 nan +inf We can verify that :func:`~mpmath.whitw` numerically satisfies the differential equation for arbitrarily chosen values:: >>> k = mpf(0.25) >>> m = mpf(1.5) >>> f = lambda z: whitw(k,m,z) >>> for z in [-1, 2.5, 3, 1+2j]: ... chop(diff(f,z,2) + (-0.25 + k/z + (0.25-m**2)/z**2)*f(z)) ... 0.0 0.0 0.0 0.0 """ ber = r""" Computes the Kelvin function ber, which for real arguments gives the real part of the Bessel J function of a rotated argument .. math :: J_n\left(x e^{3\pi i/4}\right) = \mathrm{ber}_n(x) + i \mathrm{bei}_n(x). The imaginary part is given by :func:`~mpmath.bei`. **Plots** .. literalinclude :: /plots/ber.py .. image :: /plots/ber.png **Examples** Verifying the defining relation:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> n, x = 2, 3.5 >>> ber(n,x) 1.442338852571888752631129 >>> bei(n,x) -0.948359035324558320217678 >>> besselj(n, x*root(1,8,3)) (1.442338852571888752631129 - 0.948359035324558320217678j) The ber and bei functions are also defined by analytic continuation for complex arguments:: >>> ber(1+j, 2+3j) (4.675445984756614424069563 - 15.84901771719130765656316j) >>> bei(1+j, 2+3j) (15.83886679193707699364398 + 4.684053288183046528703611j) """ bei = r""" Computes the Kelvin function bei, which for real arguments gives the imaginary part of the Bessel J function of a rotated argument. See :func:`~mpmath.ber`. """ ker = r""" Computes the Kelvin function ker, which for real arguments gives the real part of the (rescaled) Bessel K function of a rotated argument .. math :: e^{-\pi i/2} K_n\left(x e^{3\pi i/4}\right) = \mathrm{ker}_n(x) + i \mathrm{kei}_n(x). The imaginary part is given by :func:`~mpmath.kei`. **Plots** .. literalinclude :: /plots/ker.py .. image :: /plots/ker.png **Examples** Verifying the defining relation:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> n, x = 2, 4.5 >>> ker(n,x) 0.02542895201906369640249801 >>> kei(n,x) -0.02074960467222823237055351 >>> exp(-n*pi*j/2) * besselk(n, x*root(1,8,1)) (0.02542895201906369640249801 - 0.02074960467222823237055351j) The ker and kei functions are also defined by analytic continuation for complex arguments:: >>> ker(1+j, 3+4j) (1.586084268115490421090533 - 2.939717517906339193598719j) >>> kei(1+j, 3+4j) (-2.940403256319453402690132 - 1.585621643835618941044855j) """ kei = r""" Computes the Kelvin function kei, which for real arguments gives the imaginary part of the (rescaled) Bessel K function of a rotated argument. See :func:`~mpmath.ker`. """ struveh = r""" Gives the Struve function .. math :: \,\mathbf{H}_n(z) = \sum_{k=0}^\infty \frac{(-1)^k}{\Gamma(k+\frac{3}{2}) \Gamma(k+n+\frac{3}{2})} {\left({\frac{z}{2}}\right)}^{2k+n+1} which is a solution to the Struve differential equation .. math :: z^2 f''(z) + z f'(z) + (z^2-n^2) f(z) = \frac{2 z^{n+1}}{\pi (2n-1)!!}. **Examples** Evaluation for arbitrary real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> struveh(0, 3.5) 0.3608207733778295024977797 >>> struveh(-1, 10) -0.255212719726956768034732 >>> struveh(1, -100.5) 0.5819566816797362287502246 >>> struveh(2.5, 10000000000000) 3153915652525200060.308937 >>> struveh(2.5, -10000000000000) (0.0 - 3153915652525200060.308937j) >>> struveh(1+j, 1000000+4000000j) (-3.066421087689197632388731e+1737173 - 1.596619701076529803290973e+1737173j) A Struve function of half-integer order is elementary; for example: >>> z = 3 >>> struveh(0.5, 3) 0.9167076867564138178671595 >>> sqrt(2/(pi*z))*(1-cos(z)) 0.9167076867564138178671595 Numerically verifying the differential equation:: >>> z = mpf(4.5) >>> n = 3 >>> f = lambda z: struveh(n,z) >>> lhs = z**2*diff(f,z,2) + z*diff(f,z) + (z**2-n**2)*f(z) >>> rhs = 2*z**(n+1)/fac2(2*n-1)/pi >>> lhs 17.40359302709875496632744 >>> rhs 17.40359302709875496632744 """ struvel = r""" Gives the modified Struve function .. math :: \,\mathbf{L}_n(z) = -i e^{-n\pi i/2} \mathbf{H}_n(i z) which solves to the modified Struve differential equation .. math :: z^2 f''(z) + z f'(z) - (z^2+n^2) f(z) = \frac{2 z^{n+1}}{\pi (2n-1)!!}. **Examples** Evaluation for arbitrary real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> struvel(0, 3.5) 7.180846515103737996249972 >>> struvel(-1, 10) 2670.994904980850550721511 >>> struvel(1, -100.5) 1.757089288053346261497686e+42 >>> struvel(2.5, 10000000000000) 4.160893281017115450519948e+4342944819025 >>> struvel(2.5, -10000000000000) (0.0 - 4.160893281017115450519948e+4342944819025j) >>> struvel(1+j, 700j) (-0.1721150049480079451246076 + 0.1240770953126831093464055j) >>> struvel(1+j, 1000000+4000000j) (-2.973341637511505389128708e+434290 - 5.164633059729968297147448e+434290j) Numerically verifying the differential equation:: >>> z = mpf(3.5) >>> n = 3 >>> f = lambda z: struvel(n,z) >>> lhs = z**2*diff(f,z,2) + z*diff(f,z) - (z**2+n**2)*f(z) >>> rhs = 2*z**(n+1)/fac2(2*n-1)/pi >>> lhs 6.368850306060678353018165 >>> rhs 6.368850306060678353018165 """ appellf1 = r""" Gives the Appell F1 hypergeometric function of two variables, .. math :: F_1(a,b_1,b_2,c,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{(a)_{m+n} (b_1)_m (b_2)_n}{(c)_{m+n}} \frac{x^m y^n}{m! n!}. This series is only generally convergent when `|x| < 1` and `|y| < 1`, although :func:`~mpmath.appellf1` can evaluate an analytic continuation with respecto to either variable, and sometimes both. **Examples** Evaluation is supported for real and complex parameters:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> appellf1(1,0,0.5,1,0.5,0.25) 1.154700538379251529018298 >>> appellf1(1,1+j,0.5,1,0.5,0.5j) (1.138403860350148085179415 + 1.510544741058517621110615j) For some integer parameters, the F1 series reduces to a polynomial:: >>> appellf1(2,-4,-3,1,2,5) -816.0 >>> appellf1(-5,1,2,1,4,5) -20528.0 The analytic continuation with respect to either `x` or `y`, and sometimes with respect to both, can be evaluated:: >>> appellf1(2,3,4,5,100,0.5) (0.0006231042714165329279738662 + 0.0000005769149277148425774499857j) >>> appellf1('1.1', '0.3', '0.2+2j', '0.4', '0.2', 1.5+3j) (-0.1782604566893954897128702 + 0.002472407104546216117161499j) >>> appellf1(1,2,3,4,10,12) -0.07122993830066776374929313 For certain arguments, F1 reduces to an ordinary hypergeometric function:: >>> appellf1(1,2,3,5,0.5,0.25) 1.547902270302684019335555 >>> 4*hyp2f1(1,2,5,'1/3')/3 1.547902270302684019335555 >>> appellf1(1,2,3,4,0,1.5) (-1.717202506168937502740238 - 2.792526803190927323077905j) >>> hyp2f1(1,3,4,1.5) (-1.717202506168937502740238 - 2.792526803190927323077905j) The F1 function satisfies a system of partial differential equations:: >>> a,b1,b2,c,x,y = map(mpf, [1,0.5,0.25,1.125,0.25,-0.25]) >>> F = lambda x,y: appellf1(a,b1,b2,c,x,y) >>> chop(x*(1-x)*diff(F,(x,y),(2,0)) + ... y*(1-x)*diff(F,(x,y),(1,1)) + ... (c-(a+b1+1)*x)*diff(F,(x,y),(1,0)) - ... b1*y*diff(F,(x,y),(0,1)) - ... a*b1*F(x,y)) 0.0 >>> >>> chop(y*(1-y)*diff(F,(x,y),(0,2)) + ... x*(1-y)*diff(F,(x,y),(1,1)) + ... (c-(a+b2+1)*y)*diff(F,(x,y),(0,1)) - ... b2*x*diff(F,(x,y),(1,0)) - ... a*b2*F(x,y)) 0.0 The Appell F1 function allows for closed-form evaluation of various integrals, such as any integral of the form `\int x^r (x+a)^p (x+b)^q dx`:: >>> def integral(a,b,p,q,r,x1,x2): ... a,b,p,q,r,x1,x2 = map(mpmathify, [a,b,p,q,r,x1,x2]) ... f = lambda x: x**r * (x+a)**p * (x+b)**q ... def F(x): ... v = x**(r+1)/(r+1) * (a+x)**p * (b+x)**q ... v *= (1+x/a)**(-p) ... v *= (1+x/b)**(-q) ... v *= appellf1(r+1,-p,-q,2+r,-x/a,-x/b) ... return v ... print("Num. quad: %s" % quad(f, [x1,x2])) ... print("Appell F1: %s" % (F(x2)-F(x1))) ... >>> integral('1/5','4/3','-2','3','1/2',0,1) Num. quad: 9.073335358785776206576981 Appell F1: 9.073335358785776206576981 >>> integral('3/2','4/3','-2','3','1/2',0,1) Num. quad: 1.092829171999626454344678 Appell F1: 1.092829171999626454344678 >>> integral('3/2','4/3','-2','3','1/2',12,25) Num. quad: 1106.323225040235116498927 Appell F1: 1106.323225040235116498927 Also incomplete elliptic integrals fall into this category [1]:: >>> def E(z, m): ... if (pi/2).ae(z): ... return ellipe(m) ... return 2*round(re(z)/pi)*ellipe(m) + mpf(-1)**round(re(z)/pi)*\ ... sin(z)*appellf1(0.5,0.5,-0.5,1.5,sin(z)**2,m*sin(z)**2) ... >>> z, m = 1, 0.5 >>> E(z,m); quad(lambda t: sqrt(1-m*sin(t)**2), [0,pi/4,3*pi/4,z]) 0.9273298836244400669659042 0.9273298836244400669659042 >>> z, m = 3, 2 >>> E(z,m); quad(lambda t: sqrt(1-m*sin(t)**2), [0,pi/4,3*pi/4,z]) (1.057495752337234229715836 + 1.198140234735592207439922j) (1.057495752337234229715836 + 1.198140234735592207439922j) **References** 1. [WolframFunctions]_ http://functions.wolfram.com/EllipticIntegrals/EllipticE2/26/01/ 2. [SrivastavaKarlsson]_ 3. [CabralRosetti]_ 4. [Vidunas]_ 5. [Slater]_ """ angerj = r""" Gives the Anger function .. math :: \mathbf{J}_{\nu}(z) = \frac{1}{\pi} \int_0^{\pi} \cos(\nu t - z \sin t) dt which is an entire function of both the parameter `\nu` and the argument `z`. It solves the inhomogeneous Bessel differential equation .. math :: f''(z) + \frac{1}{z}f'(z) + \left(1-\frac{\nu^2}{z^2}\right) f(z) = \frac{(z-\nu)}{\pi z^2} \sin(\pi \nu). **Examples** Evaluation for real and complex parameter and argument:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> angerj(2,3) 0.4860912605858910769078311 >>> angerj(-3+4j, 2+5j) (-5033.358320403384472395612 + 585.8011892476145118551756j) >>> angerj(3.25, 1e6j) (4.630743639715893346570743e+434290 - 1.117960409887505906848456e+434291j) >>> angerj(-1.5, 1e6) 0.0002795719747073879393087011 The Anger function coincides with the Bessel J-function when `\nu` is an integer:: >>> angerj(1,3); besselj(1,3) 0.3390589585259364589255146 0.3390589585259364589255146 >>> angerj(1.5,3); besselj(1.5,3) 0.4088969848691080859328847 0.4777182150870917715515015 Verifying the differential equation:: >>> v,z = mpf(2.25), 0.75 >>> f = lambda z: angerj(v,z) >>> diff(f,z,2) + diff(f,z)/z + (1-(v/z)**2)*f(z) -0.6002108774380707130367995 >>> (z-v)/(pi*z**2) * sinpi(v) -0.6002108774380707130367995 Verifying the integral representation:: >>> angerj(v,z) 0.1145380759919333180900501 >>> quad(lambda t: cos(v*t-z*sin(t))/pi, [0,pi]) 0.1145380759919333180900501 **References** 1. [DLMF]_ section 11.10: Anger-Weber Functions """ webere = r""" Gives the Weber function .. math :: \mathbf{E}_{\nu}(z) = \frac{1}{\pi} \int_0^{\pi} \sin(\nu t - z \sin t) dt which is an entire function of both the parameter `\nu` and the argument `z`. It solves the inhomogeneous Bessel differential equation .. math :: f''(z) + \frac{1}{z}f'(z) + \left(1-\frac{\nu^2}{z^2}\right) f(z) = -\frac{1}{\pi z^2} (z+\nu+(z-\nu)\cos(\pi \nu)). **Examples** Evaluation for real and complex parameter and argument:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> webere(2,3) -0.1057668973099018425662646 >>> webere(-3+4j, 2+5j) (-585.8081418209852019290498 - 5033.314488899926921597203j) >>> webere(3.25, 1e6j) (-1.117960409887505906848456e+434291 - 4.630743639715893346570743e+434290j) >>> webere(3.25, 1e6) -0.00002812518265894315604914453 Up to addition of a rational function of `z`, the Weber function coincides with the Struve H-function when `\nu` is an integer:: >>> webere(1,3); 2/pi-struveh(1,3) -0.3834897968188690177372881 -0.3834897968188690177372881 >>> webere(5,3); 26/(35*pi)-struveh(5,3) 0.2009680659308154011878075 0.2009680659308154011878075 Verifying the differential equation:: >>> v,z = mpf(2.25), 0.75 >>> f = lambda z: webere(v,z) >>> diff(f,z,2) + diff(f,z)/z + (1-(v/z)**2)*f(z) -1.097441848875479535164627 >>> -(z+v+(z-v)*cospi(v))/(pi*z**2) -1.097441848875479535164627 Verifying the integral representation:: >>> webere(v,z) 0.1486507351534283744485421 >>> quad(lambda t: sin(v*t-z*sin(t))/pi, [0,pi]) 0.1486507351534283744485421 **References** 1. [DLMF]_ section 11.10: Anger-Weber Functions """ lommels1 = r""" Gives the Lommel function `s_{\mu,\nu}` or `s^{(1)}_{\mu,\nu}` .. math :: s_{\mu,\nu}(z) = \frac{z^{\mu+1}}{(\mu-\nu+1)(\mu+\nu+1)} \,_1F_2\left(1; \frac{\mu-\nu+3}{2}, \frac{\mu+\nu+3}{2}; -\frac{z^2}{4} \right) which solves the inhomogeneous Bessel equation .. math :: z^2 f''(z) + z f'(z) + (z^2-\nu^2) f(z) = z^{\mu+1}. A second solution is given by :func:`~mpmath.lommels2`. **Plots** .. literalinclude :: /plots/lommels1.py .. image :: /plots/lommels1.png **Examples** An integral representation:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> u,v,z = 0.25, 0.125, mpf(0.75) >>> lommels1(u,v,z) 0.4276243877565150372999126 >>> (bessely(v,z)*quad(lambda t: t**u*besselj(v,t), [0,z]) - \ ... besselj(v,z)*quad(lambda t: t**u*bessely(v,t), [0,z]))*(pi/2) 0.4276243877565150372999126 A special value:: >>> lommels1(v,v,z) 0.5461221367746048054932553 >>> gamma(v+0.5)*sqrt(pi)*power(2,v-1)*struveh(v,z) 0.5461221367746048054932553 Verifying the differential equation:: >>> f = lambda z: lommels1(u,v,z) >>> z**2*diff(f,z,2) + z*diff(f,z) + (z**2-v**2)*f(z) 0.6979536443265746992059141 >>> z**(u+1) 0.6979536443265746992059141 **References** 1. [GradshteynRyzhik]_ 2. [Weisstein]_ http://mathworld.wolfram.com/LommelFunction.html """ lommels2 = r""" Gives the second Lommel function `S_{\mu,\nu}` or `s^{(2)}_{\mu,\nu}` .. math :: S_{\mu,\nu}(z) = s_{\mu,\nu}(z) + 2^{\mu-1} \Gamma\left(\tfrac{1}{2}(\mu-\nu+1)\right) \Gamma\left(\tfrac{1}{2}(\mu+\nu+1)\right) \times \left[\sin(\tfrac{1}{2}(\mu-\nu)\pi) J_{\nu}(z) - \cos(\tfrac{1}{2}(\mu-\nu)\pi) Y_{\nu}(z) \right] which solves the same differential equation as :func:`~mpmath.lommels1`. **Plots** .. literalinclude :: /plots/lommels2.py .. image :: /plots/lommels2.png **Examples** For large `|z|`, `S_{\mu,\nu} \sim z^{\mu-1}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> lommels2(10,2,30000) 1.968299831601008419949804e+40 >>> power(30000,9) 1.9683e+40 A special value:: >>> u,v,z = 0.5, 0.125, mpf(0.75) >>> lommels2(v,v,z) 0.9589683199624672099969765 >>> (struveh(v,z)-bessely(v,z))*power(2,v-1)*sqrt(pi)*gamma(v+0.5) 0.9589683199624672099969765 Verifying the differential equation:: >>> f = lambda z: lommels2(u,v,z) >>> z**2*diff(f,z,2) + z*diff(f,z) + (z**2-v**2)*f(z) 0.6495190528383289850727924 >>> z**(u+1) 0.6495190528383289850727924 **References** 1. [GradshteynRyzhik]_ 2. [Weisstein]_ http://mathworld.wolfram.com/LommelFunction.html """ appellf2 = r""" Gives the Appell F2 hypergeometric function of two variables .. math :: F_2(a,b_1,b_2,c_1,c_2,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{(a)_{m+n} (b_1)_m (b_2)_n}{(c_1)_m (c_2)_n} \frac{x^m y^n}{m! n!}. The series is generally absolutely convergent for `|x| + |y| < 1`. **Examples** Evaluation for real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> appellf2(1,2,3,4,5,0.25,0.125) 1.257417193533135344785602 >>> appellf2(1,-3,-4,2,3,2,3) -42.8 >>> appellf2(0.5,0.25,-0.25,2,3,0.25j,0.25) (0.9880539519421899867041719 + 0.01497616165031102661476978j) >>> chop(appellf2(1,1+j,1-j,3j,-3j,0.25,0.25)) 1.201311219287411337955192 >>> appellf2(1,1,1,4,6,0.125,16) (-0.09455532250274744282125152 - 0.7647282253046207836769297j) A transformation formula:: >>> a,b1,b2,c1,c2,x,y = map(mpf, [1,2,0.5,0.25,1.625,-0.125,0.125]) >>> appellf2(a,b1,b2,c1,c2,x,y) 0.2299211717841180783309688 >>> (1-x)**(-a)*appellf2(a,c1-b1,b2,c1,c2,x/(x-1),y/(1-x)) 0.2299211717841180783309688 A system of partial differential equations satisfied by F2:: >>> a,b1,b2,c1,c2,x,y = map(mpf, [1,0.5,0.25,1.125,1.5,0.0625,-0.0625]) >>> F = lambda x,y: appellf2(a,b1,b2,c1,c2,x,y) >>> chop(x*(1-x)*diff(F,(x,y),(2,0)) - ... x*y*diff(F,(x,y),(1,1)) + ... (c1-(a+b1+1)*x)*diff(F,(x,y),(1,0)) - ... b1*y*diff(F,(x,y),(0,1)) - ... a*b1*F(x,y)) 0.0 >>> chop(y*(1-y)*diff(F,(x,y),(0,2)) - ... x*y*diff(F,(x,y),(1,1)) + ... (c2-(a+b2+1)*y)*diff(F,(x,y),(0,1)) - ... b2*x*diff(F,(x,y),(1,0)) - ... a*b2*F(x,y)) 0.0 **References** See references for :func:`~mpmath.appellf1`. """ appellf3 = r""" Gives the Appell F3 hypergeometric function of two variables .. math :: F_3(a_1,a_2,b_1,b_2,c,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{(a_1)_m (a_2)_n (b_1)_m (b_2)_n}{(c)_{m+n}} \frac{x^m y^n}{m! n!}. The series is generally absolutely convergent for `|x| < 1, |y| < 1`. **Examples** Evaluation for various parameters and variables:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> appellf3(1,2,3,4,5,0.5,0.25) 2.221557778107438938158705 >>> appellf3(1,2,3,4,5,6,0); hyp2f1(1,3,5,6) (-0.5189554589089861284537389 - 0.1454441043328607980769742j) (-0.5189554589089861284537389 - 0.1454441043328607980769742j) >>> appellf3(1,-2,-3,1,1,4,6) -17.4 >>> appellf3(1,2,-3,1,1,4,6) (17.7876136773677356641825 + 19.54768762233649126154534j) >>> appellf3(1,2,-3,1,1,6,4) (85.02054175067929402953645 + 148.4402528821177305173599j) >>> chop(appellf3(1+j,2,1-j,2,3,0.25,0.25)) 1.719992169545200286696007 Many transformations and evaluations for special combinations of the parameters are possible, e.g.: >>> a,b,c,x,y = map(mpf, [0.5,0.25,0.125,0.125,-0.125]) >>> appellf3(a,c-a,b,c-b,c,x,y) 1.093432340896087107444363 >>> (1-y)**(a+b-c)*hyp2f1(a,b,c,x+y-x*y) 1.093432340896087107444363 >>> x**2*appellf3(1,1,1,1,3,x,-x) 0.01568646277445385390945083 >>> polylog(2,x**2) 0.01568646277445385390945083 >>> a1,a2,b1,b2,c,x = map(mpf, [0.5,0.25,0.125,0.5,4.25,0.125]) >>> appellf3(a1,a2,b1,b2,c,x,1) 1.03947361709111140096947 >>> gammaprod([c,c-a2-b2],[c-a2,c-b2])*hyp3f2(a1,b1,c-a2-b2,c-a2,c-b2,x) 1.03947361709111140096947 The Appell F3 function satisfies a pair of partial differential equations:: >>> a1,a2,b1,b2,c,x,y = map(mpf, [0.5,0.25,0.125,0.5,0.625,0.0625,-0.0625]) >>> F = lambda x,y: appellf3(a1,a2,b1,b2,c,x,y) >>> chop(x*(1-x)*diff(F,(x,y),(2,0)) + ... y*diff(F,(x,y),(1,1)) + ... (c-(a1+b1+1)*x)*diff(F,(x,y),(1,0)) - ... a1*b1*F(x,y)) 0.0 >>> chop(y*(1-y)*diff(F,(x,y),(0,2)) + ... x*diff(F,(x,y),(1,1)) + ... (c-(a2+b2+1)*y)*diff(F,(x,y),(0,1)) - ... a2*b2*F(x,y)) 0.0 **References** See references for :func:`~mpmath.appellf1`. """ appellf4 = r""" Gives the Appell F4 hypergeometric function of two variables .. math :: F_4(a,b,c_1,c_2,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{(a)_{m+n} (b)_{m+n}}{(c_1)_m (c_2)_n} \frac{x^m y^n}{m! n!}. The series is generally absolutely convergent for `\sqrt{|x|} + \sqrt{|y|} < 1`. **Examples** Evaluation for various parameters and arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> appellf4(1,1,2,2,0.25,0.125) 1.286182069079718313546608 >>> appellf4(-2,-3,4,5,4,5) 34.8 >>> appellf4(5,4,2,3,0.25j,-0.125j) (-0.2585967215437846642163352 + 2.436102233553582711818743j) Reduction to `\,_2F_1` in a special case:: >>> a,b,c,x,y = map(mpf, [0.5,0.25,0.125,0.125,-0.125]) >>> appellf4(a,b,c,a+b-c+1,x*(1-y),y*(1-x)) 1.129143488466850868248364 >>> hyp2f1(a,b,c,x)*hyp2f1(a,b,a+b-c+1,y) 1.129143488466850868248364 A system of partial differential equations satisfied by F4:: >>> a,b,c1,c2,x,y = map(mpf, [1,0.5,0.25,1.125,0.0625,-0.0625]) >>> F = lambda x,y: appellf4(a,b,c1,c2,x,y) >>> chop(x*(1-x)*diff(F,(x,y),(2,0)) - ... y**2*diff(F,(x,y),(0,2)) - ... 2*x*y*diff(F,(x,y),(1,1)) + ... (c1-(a+b+1)*x)*diff(F,(x,y),(1,0)) - ... ((a+b+1)*y)*diff(F,(x,y),(0,1)) - ... a*b*F(x,y)) 0.0 >>> chop(y*(1-y)*diff(F,(x,y),(0,2)) - ... x**2*diff(F,(x,y),(2,0)) - ... 2*x*y*diff(F,(x,y),(1,1)) + ... (c2-(a+b+1)*y)*diff(F,(x,y),(0,1)) - ... ((a+b+1)*x)*diff(F,(x,y),(1,0)) - ... a*b*F(x,y)) 0.0 **References** See references for :func:`~mpmath.appellf1`. """ zeta = r""" Computes the Riemann zeta function .. math :: \zeta(s) = 1+\frac{1}{2^s}+\frac{1}{3^s}+\frac{1}{4^s}+\ldots or, with `a \ne 1`, the more general Hurwitz zeta function .. math :: \zeta(s,a) = \sum_{k=0}^\infty \frac{1}{(a+k)^s}. Optionally, ``zeta(s, a, n)`` computes the `n`-th derivative with respect to `s`, .. math :: \zeta^{(n)}(s,a) = (-1)^n \sum_{k=0}^\infty \frac{\log^n(a+k)}{(a+k)^s}. Although these series only converge for `\Re(s) > 1`, the Riemann and Hurwitz zeta functions are defined through analytic continuation for arbitrary complex `s \ne 1` (`s = 1` is a pole). The implementation uses three algorithms: the Borwein algorithm for the Riemann zeta function when `s` is close to the real line; the Riemann-Siegel formula for the Riemann zeta function when `s` is large imaginary, and Euler-Maclaurin summation in all other cases. The reflection formula for `\Re(s) < 0` is implemented in some cases. The algorithm can be chosen with ``method = 'borwein'``, ``method='riemann-siegel'`` or ``method = 'euler-maclaurin'``. The parameter `a` is usually a rational number `a = p/q`, and may be specified as such by passing an integer tuple `(p, q)`. Evaluation is supported for arbitrary complex `a`, but may be slow and/or inaccurate when `\Re(s) < 0` for nonrational `a` or when computing derivatives. **Examples** Some values of the Riemann zeta function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> zeta(2); pi**2 / 6 1.644934066848226436472415 1.644934066848226436472415 >>> zeta(0) -0.5 >>> zeta(-1) -0.08333333333333333333333333 >>> zeta(-2) 0.0 For large positive `s`, `\zeta(s)` rapidly approaches 1:: >>> zeta(50) 1.000000000000000888178421 >>> zeta(100) 1.0 >>> zeta(inf) 1.0 >>> 1-sum((zeta(k)-1)/k for k in range(2,85)); +euler 0.5772156649015328606065121 0.5772156649015328606065121 >>> nsum(lambda k: zeta(k)-1, [2, inf]) 1.0 Evaluation is supported for complex `s` and `a`: >>> zeta(-3+4j) (-0.03373057338827757067584698 + 0.2774499251557093745297677j) >>> zeta(2+3j, -1+j) (389.6841230140842816370741 + 295.2674610150305334025962j) The Riemann zeta function has so-called nontrivial zeros on the critical line `s = 1/2 + it`:: >>> findroot(zeta, 0.5+14j); zetazero(1) (0.5 + 14.13472514173469379045725j) (0.5 + 14.13472514173469379045725j) >>> findroot(zeta, 0.5+21j); zetazero(2) (0.5 + 21.02203963877155499262848j) (0.5 + 21.02203963877155499262848j) >>> findroot(zeta, 0.5+25j); zetazero(3) (0.5 + 25.01085758014568876321379j) (0.5 + 25.01085758014568876321379j) >>> chop(zeta(zetazero(10))) 0.0 Evaluation on and near the critical line is supported for large heights `t` by means of the Riemann-Siegel formula (currently for `a = 1`, `n \le 4`):: >>> zeta(0.5+100000j) (1.073032014857753132114076 + 5.780848544363503984261041j) >>> zeta(0.75+1000000j) (0.9535316058375145020351559 + 0.9525945894834273060175651j) >>> zeta(0.5+10000000j) (11.45804061057709254500227 - 8.643437226836021723818215j) >>> zeta(0.5+100000000j, derivative=1) (51.12433106710194942681869 + 43.87221167872304520599418j) >>> zeta(0.5+100000000j, derivative=2) (-444.2760822795430400549229 - 896.3789978119185981665403j) >>> zeta(0.5+100000000j, derivative=3) (3230.72682687670422215339 + 14374.36950073615897616781j) >>> zeta(0.5+100000000j, derivative=4) (-11967.35573095046402130602 - 218945.7817789262839266148j) >>> zeta(1+10000000j) # off the line (2.859846483332530337008882 + 0.491808047480981808903986j) >>> zeta(1+10000000j, derivative=1) (-4.333835494679647915673205 - 0.08405337962602933636096103j) >>> zeta(1+10000000j, derivative=4) (453.2764822702057701894278 - 581.963625832768189140995j) For investigation of the zeta function zeros, the Riemann-Siegel Z-function is often more convenient than working with the Riemann zeta function directly (see :func:`~mpmath.siegelz`). Some values of the Hurwitz zeta function:: >>> zeta(2, 3); -5./4 + pi**2/6 0.3949340668482264364724152 0.3949340668482264364724152 >>> zeta(2, (3,4)); pi**2 - 8*catalan 2.541879647671606498397663 2.541879647671606498397663 For positive integer values of `s`, the Hurwitz zeta function is equivalent to a polygamma function (except for a normalizing factor):: >>> zeta(4, (1,5)); psi(3, '1/5')/6 625.5408324774542966919938 625.5408324774542966919938 Evaluation of derivatives:: >>> zeta(0, 3+4j, 1); loggamma(3+4j) - ln(2*pi)/2 (-2.675565317808456852310934 + 4.742664438034657928194889j) (-2.675565317808456852310934 + 4.742664438034657928194889j) >>> zeta(2, 1, 20) 2432902008176640000.000242 >>> zeta(3+4j, 5.5+2j, 4) (-0.140075548947797130681075 - 0.3109263360275413251313634j) >>> zeta(0.5+100000j, 1, 4) (-10407.16081931495861539236 + 13777.78669862804508537384j) >>> zeta(-100+0.5j, (1,3), derivative=4) (4.007180821099823942702249e+79 + 4.916117957092593868321778e+78j) Generating a Taylor series at `s = 2` using derivatives:: >>> for k in range(11): print("%s * (s-2)^%i" % (zeta(2,1,k)/fac(k), k)) ... 1.644934066848226436472415 * (s-2)^0 -0.9375482543158437537025741 * (s-2)^1 0.9946401171494505117104293 * (s-2)^2 -1.000024300473840810940657 * (s-2)^3 1.000061933072352565457512 * (s-2)^4 -1.000006869443931806408941 * (s-2)^5 1.000000173233769531820592 * (s-2)^6 -0.9999999569989868493432399 * (s-2)^7 0.9999999937218844508684206 * (s-2)^8 -0.9999999996355013916608284 * (s-2)^9 1.000000000004610645020747 * (s-2)^10 Evaluation at zero and for negative integer `s`:: >>> zeta(0, 10) -9.5 >>> zeta(-2, (2,3)); mpf(1)/81 0.01234567901234567901234568 0.01234567901234567901234568 >>> zeta(-3+4j, (5,4)) (0.2899236037682695182085988 + 0.06561206166091757973112783j) >>> zeta(-3.25, 1/pi) -0.0005117269627574430494396877 >>> zeta(-3.5, pi, 1) 11.156360390440003294709 >>> zeta(-100.5, (8,3)) -4.68162300487989766727122e+77 >>> zeta(-10.5, (-8,3)) (-0.01521913704446246609237979 + 29907.72510874248161608216j) >>> zeta(-1000.5, (-8,3)) (1.031911949062334538202567e+1770 + 1.519555750556794218804724e+426j) >>> zeta(-1+j, 3+4j) (-16.32988355630802510888631 - 22.17706465801374033261383j) >>> zeta(-1+j, 3+4j, 2) (32.48985276392056641594055 - 51.11604466157397267043655j) >>> diff(lambda s: zeta(s, 3+4j), -1+j, 2) (32.48985276392056641594055 - 51.11604466157397267043655j) **References** 1. http://mathworld.wolfram.com/RiemannZetaFunction.html 2. http://mathworld.wolfram.com/HurwitzZetaFunction.html 3. http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf """ dirichlet = r""" Evaluates the Dirichlet L-function .. math :: L(s,\chi) = \sum_{k=1}^\infty \frac{\chi(k)}{k^s}. where `\chi` is a periodic sequence of length `q` which should be supplied in the form of a list `[\chi(0), \chi(1), \ldots, \chi(q-1)]`. Strictly, `\chi` should be a Dirichlet character, but any periodic sequence will work. For example, ``dirichlet(s, [1])`` gives the ordinary Riemann zeta function and ``dirichlet(s, [-1,1])`` gives the alternating zeta function (Dirichlet eta function). Also the derivative with respect to `s` (currently only a first derivative) can be evaluated. **Examples** The ordinary Riemann zeta function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> dirichlet(3, [1]); zeta(3) 1.202056903159594285399738 1.202056903159594285399738 >>> dirichlet(1, [1]) +inf The alternating zeta function:: >>> dirichlet(1, [-1,1]); ln(2) 0.6931471805599453094172321 0.6931471805599453094172321 The following defines the Dirichlet beta function `\beta(s) = \sum_{k=0}^\infty \frac{(-1)^k}{(2k+1)^s}` and verifies several values of this function:: >>> B = lambda s, d=0: dirichlet(s, [0, 1, 0, -1], d) >>> B(0); 1./2 0.5 0.5 >>> B(1); pi/4 0.7853981633974483096156609 0.7853981633974483096156609 >>> B(2); +catalan 0.9159655941772190150546035 0.9159655941772190150546035 >>> B(2,1); diff(B, 2) 0.08158073611659279510291217 0.08158073611659279510291217 >>> B(-1,1); 2*catalan/pi 0.5831218080616375602767689 0.5831218080616375602767689 >>> B(0,1); log(gamma(0.25)**2/(2*pi*sqrt(2))) 0.3915943927068367764719453 0.3915943927068367764719454 >>> B(1,1); 0.25*pi*(euler+2*ln2+3*ln(pi)-4*ln(gamma(0.25))) 0.1929013167969124293631898 0.1929013167969124293631898 A custom L-series of period 3:: >>> dirichlet(2, [2,0,1]) 0.7059715047839078092146831 >>> 2*nsum(lambda k: (3*k)**-2, [1,inf]) + \ ... nsum(lambda k: (3*k+2)**-2, [0,inf]) 0.7059715047839078092146831 """ coulombf = r""" Calculates the regular Coulomb wave function .. math :: F_l(\eta,z) = C_l(\eta) z^{l+1} e^{-iz} \,_1F_1(l+1-i\eta, 2l+2, 2iz) where the normalization constant `C_l(\eta)` is as calculated by :func:`~mpmath.coulombc`. This function solves the differential equation .. math :: f''(z) + \left(1-\frac{2\eta}{z}-\frac{l(l+1)}{z^2}\right) f(z) = 0. A second linearly independent solution is given by the irregular Coulomb wave function `G_l(\eta,z)` (see :func:`~mpmath.coulombg`) and thus the general solution is `f(z) = C_1 F_l(\eta,z) + C_2 G_l(\eta,z)` for arbitrary constants `C_1`, `C_2`. Physically, the Coulomb wave functions give the radial solution to the Schrodinger equation for a point particle in a `1/z` potential; `z` is then the radius and `l`, `\eta` are quantum numbers. The Coulomb wave functions with real parameters are defined in Abramowitz & Stegun, section 14. However, all parameters are permitted to be complex in this implementation (see references). **Plots** .. literalinclude :: /plots/coulombf.py .. image :: /plots/coulombf.png .. literalinclude :: /plots/coulombf_c.py .. image :: /plots/coulombf_c.png **Examples** Evaluation is supported for arbitrary magnitudes of `z`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> coulombf(2, 1.5, 3.5) 0.4080998961088761187426445 >>> coulombf(-2, 1.5, 3.5) 0.7103040849492536747533465 >>> coulombf(2, 1.5, '1e-10') 4.143324917492256448770769e-33 >>> coulombf(2, 1.5, 1000) 0.4482623140325567050716179 >>> coulombf(2, 1.5, 10**10) -0.066804196437694360046619 Verifying the differential equation:: >>> l, eta, z = 2, 3, mpf(2.75) >>> A, B = 1, 2 >>> f = lambda z: A*coulombf(l,eta,z) + B*coulombg(l,eta,z) >>> chop(diff(f,z,2) + (1-2*eta/z - l*(l+1)/z**2)*f(z)) 0.0 A Wronskian relation satisfied by the Coulomb wave functions:: >>> l = 2 >>> eta = 1.5 >>> F = lambda z: coulombf(l,eta,z) >>> G = lambda z: coulombg(l,eta,z) >>> for z in [3.5, -1, 2+3j]: ... chop(diff(F,z)*G(z) - F(z)*diff(G,z)) ... 1.0 1.0 1.0 Another Wronskian relation:: >>> F = coulombf >>> G = coulombg >>> for z in [3.5, -1, 2+3j]: ... chop(F(l-1,eta,z)*G(l,eta,z)-F(l,eta,z)*G(l-1,eta,z) - l/sqrt(l**2+eta**2)) ... 0.0 0.0 0.0 An integral identity connecting the regular and irregular wave functions:: >>> l, eta, z = 4+j, 2-j, 5+2j >>> coulombf(l,eta,z) + j*coulombg(l,eta,z) (0.7997977752284033239714479 + 0.9294486669502295512503127j) >>> g = lambda t: exp(-t)*t**(l-j*eta)*(t+2*j*z)**(l+j*eta) >>> j*exp(-j*z)*z**(-l)/fac(2*l+1)/coulombc(l,eta)*quad(g, [0,inf]) (0.7997977752284033239714479 + 0.9294486669502295512503127j) Some test case with complex parameters, taken from Michel [2]:: >>> mp.dps = 15 >>> coulombf(1+0.1j, 50+50j, 100.156) (-1.02107292320897e+15 - 2.83675545731519e+15j) >>> coulombg(1+0.1j, 50+50j, 100.156) (2.83675545731519e+15 - 1.02107292320897e+15j) >>> coulombf(1e-5j, 10+1e-5j, 0.1+1e-6j) (4.30566371247811e-14 - 9.03347835361657e-19j) >>> coulombg(1e-5j, 10+1e-5j, 0.1+1e-6j) (778709182061.134 + 18418936.2660553j) The following reproduces a table in Abramowitz & Stegun, at twice the precision:: >>> mp.dps = 10 >>> eta = 2; z = 5 >>> for l in [5, 4, 3, 2, 1, 0]: ... print("%s %s %s" % (l, coulombf(l,eta,z), ... diff(lambda z: coulombf(l,eta,z), z))) ... 5 0.09079533488 0.1042553261 4 0.2148205331 0.2029591779 3 0.4313159311 0.320534053 2 0.7212774133 0.3952408216 1 0.9935056752 0.3708676452 0 1.143337392 0.2937960375 **References** 1. I.J. Thompson & A.R. Barnett, "Coulomb and Bessel Functions of Complex Arguments and Order", J. Comp. Phys., vol 64, no. 2, June 1986. 2. N. Michel, "Precise Coulomb wave functions for a wide range of complex `l`, `\eta` and `z`", http://arxiv.org/abs/physics/0702051v1 """ coulombg = r""" Calculates the irregular Coulomb wave function .. math :: G_l(\eta,z) = \frac{F_l(\eta,z) \cos(\chi) - F_{-l-1}(\eta,z)}{\sin(\chi)} where `\chi = \sigma_l - \sigma_{-l-1} - (l+1/2) \pi` and `\sigma_l(\eta) = (\ln \Gamma(1+l+i\eta)-\ln \Gamma(1+l-i\eta))/(2i)`. See :func:`~mpmath.coulombf` for additional information. **Plots** .. literalinclude :: /plots/coulombg.py .. image :: /plots/coulombg.png .. literalinclude :: /plots/coulombg_c.py .. image :: /plots/coulombg_c.png **Examples** Evaluation is supported for arbitrary magnitudes of `z`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> coulombg(-2, 1.5, 3.5) 1.380011900612186346255524 >>> coulombg(2, 1.5, 3.5) 1.919153700722748795245926 >>> coulombg(-2, 1.5, '1e-10') 201126715824.7329115106793 >>> coulombg(-2, 1.5, 1000) 0.1802071520691149410425512 >>> coulombg(-2, 1.5, 10**10) 0.652103020061678070929794 The following reproduces a table in Abramowitz & Stegun, at twice the precision:: >>> mp.dps = 10 >>> eta = 2; z = 5 >>> for l in [1, 2, 3, 4, 5]: ... print("%s %s %s" % (l, coulombg(l,eta,z), ... -diff(lambda z: coulombg(l,eta,z), z))) ... 1 1.08148276 0.6028279961 2 1.496877075 0.5661803178 3 2.048694714 0.7959909551 4 3.09408669 1.731802374 5 5.629840456 4.549343289 Evaluation close to the singularity at `z = 0`:: >>> mp.dps = 15 >>> coulombg(0,10,1) 3088184933.67358 >>> coulombg(0,10,'1e-10') 5554866000719.8 >>> coulombg(0,10,'1e-100') 5554866221524.1 Evaluation with a half-integer value for `l`:: >>> coulombg(1.5, 1, 10) 0.852320038297334 """ coulombc = r""" Gives the normalizing Gamow constant for Coulomb wave functions, .. math :: C_l(\eta) = 2^l \exp\left(-\pi \eta/2 + [\ln \Gamma(1+l+i\eta) + \ln \Gamma(1+l-i\eta)]/2 - \ln \Gamma(2l+2)\right), where the log gamma function with continuous imaginary part away from the negative half axis (see :func:`~mpmath.loggamma`) is implied. This function is used internally for the calculation of Coulomb wave functions, and automatically cached to make multiple evaluations with fixed `l`, `\eta` fast. """ ellipfun = r""" Computes any of the Jacobi elliptic functions, defined in terms of Jacobi theta functions as .. math :: \mathrm{sn}(u,m) = \frac{\vartheta_3(0,q)}{\vartheta_2(0,q)} \frac{\vartheta_1(t,q)}{\vartheta_4(t,q)} \mathrm{cn}(u,m) = \frac{\vartheta_4(0,q)}{\vartheta_2(0,q)} \frac{\vartheta_2(t,q)}{\vartheta_4(t,q)} \mathrm{dn}(u,m) = \frac{\vartheta_4(0,q)}{\vartheta_3(0,q)} \frac{\vartheta_3(t,q)}{\vartheta_4(t,q)}, or more generally computes a ratio of two such functions. Here `t = u/\vartheta_3(0,q)^2`, and `q = q(m)` denotes the nome (see :func:`~mpmath.nome`). Optionally, you can specify the nome directly instead of `m` by passing ``q=``, or you can directly specify the elliptic parameter `k` with ``k=``. The first argument should be a two-character string specifying the function using any combination of ``'s'``, ``'c'``, ``'d'``, ``'n'``. These letters respectively denote the basic functions `\mathrm{sn}(u,m)`, `\mathrm{cn}(u,m)`, `\mathrm{dn}(u,m)`, and `1`. The identifier specifies the ratio of two such functions. For example, ``'ns'`` identifies the function .. math :: \mathrm{ns}(u,m) = \frac{1}{\mathrm{sn}(u,m)} and ``'cd'`` identifies the function .. math :: \mathrm{cd}(u,m) = \frac{\mathrm{cn}(u,m)}{\mathrm{dn}(u,m)}. If called with only the first argument, a function object evaluating the chosen function for given arguments is returned. **Examples** Basic evaluation:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> ellipfun('cd', 3.5, 0.5) -0.9891101840595543931308394 >>> ellipfun('cd', 3.5, q=0.25) 0.07111979240214668158441418 The sn-function is doubly periodic in the complex plane with periods `4 K(m)` and `2 i K(1-m)` (see :func:`~mpmath.ellipk`):: >>> sn = ellipfun('sn') >>> sn(2, 0.25) 0.9628981775982774425751399 >>> sn(2+4*ellipk(0.25), 0.25) 0.9628981775982774425751399 >>> chop(sn(2+2*j*ellipk(1-0.25), 0.25)) 0.9628981775982774425751399 The cn-function is doubly periodic with periods `4 K(m)` and `4 i K(1-m)`:: >>> cn = ellipfun('cn') >>> cn(2, 0.25) -0.2698649654510865792581416 >>> cn(2+4*ellipk(0.25), 0.25) -0.2698649654510865792581416 >>> chop(cn(2+4*j*ellipk(1-0.25), 0.25)) -0.2698649654510865792581416 The dn-function is doubly periodic with periods `2 K(m)` and `4 i K(1-m)`:: >>> dn = ellipfun('dn') >>> dn(2, 0.25) 0.8764740583123262286931578 >>> dn(2+2*ellipk(0.25), 0.25) 0.8764740583123262286931578 >>> chop(dn(2+4*j*ellipk(1-0.25), 0.25)) 0.8764740583123262286931578 """ jtheta = r""" Computes the Jacobi theta function `\vartheta_n(z, q)`, where `n = 1, 2, 3, 4`, defined by the infinite series: .. math :: \vartheta_1(z,q) = 2 q^{1/4} \sum_{n=0}^{\infty} (-1)^n q^{n^2+n\,} \sin((2n+1)z) \vartheta_2(z,q) = 2 q^{1/4} \sum_{n=0}^{\infty} q^{n^{2\,} + n} \cos((2n+1)z) \vartheta_3(z,q) = 1 + 2 \sum_{n=1}^{\infty} q^{n^2\,} \cos(2 n z) \vartheta_4(z,q) = 1 + 2 \sum_{n=1}^{\infty} (-q)^{n^2\,} \cos(2 n z) The theta functions are functions of two variables: * `z` is the *argument*, an arbitrary real or complex number * `q` is the *nome*, which must be a real or complex number in the unit disk (i.e. `|q| < 1`). For `|q| \ll 1`, the series converge very quickly, so the Jacobi theta functions can efficiently be evaluated to high precision. The compact notations `\vartheta_n(q) = \vartheta_n(0,q)` and `\vartheta_n = \vartheta_n(0,q)` are also frequently encountered. Finally, Jacobi theta functions are frequently considered as functions of the half-period ratio `\tau` and then usually denoted by `\vartheta_n(z|\tau)`. Optionally, ``jtheta(n, z, q, derivative=d)`` with `d > 0` computes a `d`-th derivative with respect to `z`. **Examples and basic properties** Considered as functions of `z`, the Jacobi theta functions may be viewed as generalizations of the ordinary trigonometric functions cos and sin. They are periodic functions:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> jtheta(1, 0.25, '0.2') 0.2945120798627300045053104 >>> jtheta(1, 0.25 + 2*pi, '0.2') 0.2945120798627300045053104 Indeed, the series defining the theta functions are essentially trigonometric Fourier series. The coefficients can be retrieved using :func:`~mpmath.fourier`:: >>> mp.dps = 10 >>> nprint(fourier(lambda x: jtheta(2, x, 0.5), [-pi, pi], 4)) ([0.0, 1.68179, 0.0, 0.420448, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0]) The Jacobi theta functions are also so-called quasiperiodic functions of `z` and `\tau`, meaning that for fixed `\tau`, `\vartheta_n(z, q)` and `\vartheta_n(z+\pi \tau, q)` are the same except for an exponential factor:: >>> mp.dps = 25 >>> tau = 3*j/10 >>> q = exp(pi*j*tau) >>> z = 10 >>> jtheta(4, z+tau*pi, q) (-0.682420280786034687520568 + 1.526683999721399103332021j) >>> -exp(-2*j*z)/q * jtheta(4, z, q) (-0.682420280786034687520568 + 1.526683999721399103332021j) The Jacobi theta functions satisfy a huge number of other functional equations, such as the following identity (valid for any `q`):: >>> q = mpf(3)/10 >>> jtheta(3,0,q)**4 6.823744089352763305137427 >>> jtheta(2,0,q)**4 + jtheta(4,0,q)**4 6.823744089352763305137427 Extensive listings of identities satisfied by the Jacobi theta functions can be found in standard reference works. The Jacobi theta functions are related to the gamma function for special arguments:: >>> jtheta(3, 0, exp(-pi)) 1.086434811213308014575316 >>> pi**(1/4.) / gamma(3/4.) 1.086434811213308014575316 :func:`~mpmath.jtheta` supports arbitrary precision evaluation and complex arguments:: >>> mp.dps = 50 >>> jtheta(4, sqrt(2), 0.5) 2.0549510717571539127004115835148878097035750653737 >>> mp.dps = 25 >>> jtheta(4, 1+2j, (1+j)/5) (7.180331760146805926356634 - 1.634292858119162417301683j) Evaluation of derivatives:: >>> mp.dps = 25 >>> jtheta(1, 7, 0.25, 1); diff(lambda z: jtheta(1, z, 0.25), 7) 1.209857192844475388637236 1.209857192844475388637236 >>> jtheta(1, 7, 0.25, 2); diff(lambda z: jtheta(1, z, 0.25), 7, 2) -0.2598718791650217206533052 -0.2598718791650217206533052 >>> jtheta(2, 7, 0.25, 1); diff(lambda z: jtheta(2, z, 0.25), 7) -1.150231437070259644461474 -1.150231437070259644461474 >>> jtheta(2, 7, 0.25, 2); diff(lambda z: jtheta(2, z, 0.25), 7, 2) -0.6226636990043777445898114 -0.6226636990043777445898114 >>> jtheta(3, 7, 0.25, 1); diff(lambda z: jtheta(3, z, 0.25), 7) -0.9990312046096634316587882 -0.9990312046096634316587882 >>> jtheta(3, 7, 0.25, 2); diff(lambda z: jtheta(3, z, 0.25), 7, 2) -0.1530388693066334936151174 -0.1530388693066334936151174 >>> jtheta(4, 7, 0.25, 1); diff(lambda z: jtheta(4, z, 0.25), 7) 0.9820995967262793943571139 0.9820995967262793943571139 >>> jtheta(4, 7, 0.25, 2); diff(lambda z: jtheta(4, z, 0.25), 7, 2) 0.3936902850291437081667755 0.3936902850291437081667755 **Possible issues** For `|q| \ge 1` or `\Im(\tau) \le 0`, :func:`~mpmath.jtheta` raises ``ValueError``. This exception is also raised for `|q|` extremely close to 1 (or equivalently `\tau` very close to 0), since the series would converge too slowly:: >>> jtheta(1, 10, 0.99999999 * exp(0.5*j)) Traceback (most recent call last): ... ValueError: abs(q) > THETA_Q_LIM = 1.000000 """ eulernum = r""" Gives the `n`-th Euler number, defined as the `n`-th derivative of `\mathrm{sech}(t) = 1/\cosh(t)` evaluated at `t = 0`. Equivalently, the Euler numbers give the coefficients of the Taylor series .. math :: \mathrm{sech}(t) = \sum_{n=0}^{\infty} \frac{E_n}{n!} t^n. The Euler numbers are closely related to Bernoulli numbers and Bernoulli polynomials. They can also be evaluated in terms of Euler polynomials (see :func:`~mpmath.eulerpoly`) as `E_n = 2^n E_n(1/2)`. **Examples** Computing the first few Euler numbers and verifying that they agree with the Taylor series:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> [eulernum(n) for n in range(11)] [1.0, 0.0, -1.0, 0.0, 5.0, 0.0, -61.0, 0.0, 1385.0, 0.0, -50521.0] >>> chop(diffs(sech, 0, 10)) [1.0, 0.0, -1.0, 0.0, 5.0, 0.0, -61.0, 0.0, 1385.0, 0.0, -50521.0] Euler numbers grow very rapidly. :func:`~mpmath.eulernum` efficiently computes numerical approximations for large indices:: >>> eulernum(50) -6.053285248188621896314384e+54 >>> eulernum(1000) 3.887561841253070615257336e+2371 >>> eulernum(10**20) 4.346791453661149089338186e+1936958564106659551331 Comparing with an asymptotic formula for the Euler numbers:: >>> n = 10**5 >>> (-1)**(n//2) * 8 * sqrt(n/(2*pi)) * (2*n/(pi*e))**n 3.69919063017432362805663e+436961 >>> eulernum(n) 3.699193712834466537941283e+436961 Pass ``exact=True`` to obtain exact values of Euler numbers as integers:: >>> print(eulernum(50, exact=True)) -6053285248188621896314383785111649088103498225146815121 >>> print(eulernum(200, exact=True) % 10**10) 1925859625 >>> eulernum(1001, exact=True) 0 """ eulerpoly = r""" Evaluates the Euler polynomial `E_n(z)`, defined by the generating function representation .. math :: \frac{2e^{zt}}{e^t+1} = \sum_{n=0}^\infty E_n(z) \frac{t^n}{n!}. The Euler polynomials may also be represented in terms of Bernoulli polynomials (see :func:`~mpmath.bernpoly`) using various formulas, for example .. math :: E_n(z) = \frac{2}{n+1} \left( B_n(z)-2^{n+1}B_n\left(\frac{z}{2}\right) \right). Special values include the Euler numbers `E_n = 2^n E_n(1/2)` (see :func:`~mpmath.eulernum`). **Examples** Computing the coefficients of the first few Euler polynomials:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> for n in range(6): ... chop(taylor(lambda z: eulerpoly(n,z), 0, n)) ... [1.0] [-0.5, 1.0] [0.0, -1.0, 1.0] [0.25, 0.0, -1.5, 1.0] [0.0, 1.0, 0.0, -2.0, 1.0] [-0.5, 0.0, 2.5, 0.0, -2.5, 1.0] Evaluation for arbitrary `z`:: >>> eulerpoly(2,3) 6.0 >>> eulerpoly(5,4) 423.5 >>> eulerpoly(35, 11111111112) 3.994957561486776072734601e+351 >>> eulerpoly(4, 10+20j) (-47990.0 - 235980.0j) >>> eulerpoly(2, '-3.5e-5') 0.000035001225 >>> eulerpoly(3, 0.5) 0.0 >>> eulerpoly(55, -10**80) -1.0e+4400 >>> eulerpoly(5, -inf) -inf >>> eulerpoly(6, -inf) +inf Computing Euler numbers:: >>> 2**26 * eulerpoly(26,0.5) -4087072509293123892361.0 >>> eulernum(26) -4087072509293123892361.0 Evaluation is accurate for large `n` and small `z`:: >>> eulerpoly(100, 0.5) 2.29047999988194114177943e+108 >>> eulerpoly(1000, 10.5) 3.628120031122876847764566e+2070 >>> eulerpoly(10000, 10.5) 1.149364285543783412210773e+30688 """ spherharm = r""" Evaluates the spherical harmonic `Y_l^m(\theta,\phi)`, .. math :: Y_l^m(\theta,\phi) = \sqrt{\frac{2l+1}{4\pi}\frac{(l-m)!}{(l+m)!}} P_l^m(\cos \theta) e^{i m \phi} where `P_l^m` is an associated Legendre function (see :func:`~mpmath.legenp`). Here `\theta \in [0, \pi]` denotes the polar coordinate (ranging from the north pole to the south pole) and `\phi \in [0, 2 \pi]` denotes the azimuthal coordinate on a sphere. Care should be used since many different conventions for spherical coordinate variables are used. Usually spherical harmonics are considered for `l \in \mathbb{N}`, `m \in \mathbb{Z}`, `|m| \le l`. More generally, `l,m,\theta,\phi` are permitted to be complex numbers. .. note :: :func:`~mpmath.spherharm` returns a complex number, even if the value is purely real. **Plots** .. literalinclude :: /plots/spherharm40.py `Y_{4,0}`: .. image :: /plots/spherharm40.png `Y_{4,1}`: .. image :: /plots/spherharm41.png `Y_{4,2}`: .. image :: /plots/spherharm42.png `Y_{4,3}`: .. image :: /plots/spherharm43.png `Y_{4,4}`: .. image :: /plots/spherharm44.png **Examples** Some low-order spherical harmonics with reference values:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> theta = pi/4 >>> phi = pi/3 >>> spherharm(0,0,theta,phi); 0.5*sqrt(1/pi)*expj(0) (0.2820947917738781434740397 + 0.0j) (0.2820947917738781434740397 + 0.0j) >>> spherharm(1,-1,theta,phi); 0.5*sqrt(3/(2*pi))*expj(-phi)*sin(theta) (0.1221506279757299803965962 - 0.2115710938304086076055298j) (0.1221506279757299803965962 - 0.2115710938304086076055298j) >>> spherharm(1,0,theta,phi); 0.5*sqrt(3/pi)*cos(theta)*expj(0) (0.3454941494713354792652446 + 0.0j) (0.3454941494713354792652446 + 0.0j) >>> spherharm(1,1,theta,phi); -0.5*sqrt(3/(2*pi))*expj(phi)*sin(theta) (-0.1221506279757299803965962 - 0.2115710938304086076055298j) (-0.1221506279757299803965962 - 0.2115710938304086076055298j) With the normalization convention used, the spherical harmonics are orthonormal on the unit sphere:: >>> sphere = [0,pi], [0,2*pi] >>> dS = lambda t,p: fp.sin(t) # differential element >>> Y1 = lambda t,p: fp.spherharm(l1,m1,t,p) >>> Y2 = lambda t,p: fp.conj(fp.spherharm(l2,m2,t,p)) >>> l1 = l2 = 3; m1 = m2 = 2 >>> print(fp.quad(lambda t,p: Y1(t,p)*Y2(t,p)*dS(t,p), *sphere)) (1+0j) >>> m2 = 1 # m1 != m2 >>> print(fp.chop(fp.quad(lambda t,p: Y1(t,p)*Y2(t,p)*dS(t,p), *sphere))) 0.0 Evaluation is accurate for large orders:: >>> spherharm(1000,750,0.5,0.25) (3.776445785304252879026585e-102 - 5.82441278771834794493484e-102j) Evaluation works with complex parameter values:: >>> spherharm(1+j, 2j, 2+3j, -0.5j) (64.44922331113759992154992 + 1981.693919841408089681743j) """ scorergi = r""" Evaluates the Scorer function .. math :: \operatorname{Gi}(z) = \operatorname{Ai}(z) \int_0^z \operatorname{Bi}(t) dt + \operatorname{Bi}(z) \int_z^{\infty} \operatorname{Ai}(t) dt which gives a particular solution to the inhomogeneous Airy differential equation `f''(z) - z f(z) = 1/\pi`. Another particular solution is given by the Scorer Hi-function (:func:`~mpmath.scorerhi`). The two functions are related as `\operatorname{Gi}(z) + \operatorname{Hi}(z) = \operatorname{Bi}(z)`. **Plots** .. literalinclude :: /plots/gi.py .. image :: /plots/gi.png .. literalinclude :: /plots/gi_c.py .. image :: /plots/gi_c.png **Examples** Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> scorergi(0); 1/(power(3,'7/6')*gamma('2/3')) 0.2049755424820002450503075 0.2049755424820002450503075 >>> diff(scorergi, 0); 1/(power(3,'5/6')*gamma('1/3')) 0.1494294524512754526382746 0.1494294524512754526382746 >>> scorergi(+inf); scorergi(-inf) 0.0 0.0 >>> scorergi(1) 0.2352184398104379375986902 >>> scorergi(-1) -0.1166722172960152826494198 Evaluation for large arguments:: >>> scorergi(10) 0.03189600510067958798062034 >>> scorergi(100) 0.003183105228162961476590531 >>> scorergi(1000000) 0.0000003183098861837906721743873 >>> 1/(pi*1000000) 0.0000003183098861837906715377675 >>> scorergi(-1000) -0.08358288400262780392338014 >>> scorergi(-100000) 0.02886866118619660226809581 >>> scorergi(50+10j) (0.0061214102799778578790984 - 0.001224335676457532180747917j) >>> scorergi(-50-10j) (5.236047850352252236372551e+29 - 3.08254224233701381482228e+29j) >>> scorergi(100000j) (-8.806659285336231052679025e+6474077 + 8.684731303500835514850962e+6474077j) Verifying the connection between Gi and Hi:: >>> z = 0.25 >>> scorergi(z) + scorerhi(z) 0.7287469039362150078694543 >>> airybi(z) 0.7287469039362150078694543 Verifying the differential equation:: >>> for z in [-3.4, 0, 2.5, 1+2j]: ... chop(diff(scorergi,z,2) - z*scorergi(z)) ... -0.3183098861837906715377675 -0.3183098861837906715377675 -0.3183098861837906715377675 -0.3183098861837906715377675 Verifying the integral representation:: >>> z = 0.5 >>> scorergi(z) 0.2447210432765581976910539 >>> Ai,Bi = airyai,airybi >>> Bi(z)*(Ai(inf,-1)-Ai(z,-1)) + Ai(z)*(Bi(z,-1)-Bi(0,-1)) 0.2447210432765581976910539 **References** 1. [DLMF]_ section 9.12: Scorer Functions """ scorerhi = r""" Evaluates the second Scorer function .. math :: \operatorname{Hi}(z) = \operatorname{Bi}(z) \int_{-\infty}^z \operatorname{Ai}(t) dt - \operatorname{Ai}(z) \int_{-\infty}^z \operatorname{Bi}(t) dt which gives a particular solution to the inhomogeneous Airy differential equation `f''(z) - z f(z) = 1/\pi`. See also :func:`~mpmath.scorergi`. **Plots** .. literalinclude :: /plots/hi.py .. image :: /plots/hi.png .. literalinclude :: /plots/hi_c.py .. image :: /plots/hi_c.png **Examples** Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> scorerhi(0); 2/(power(3,'7/6')*gamma('2/3')) 0.4099510849640004901006149 0.4099510849640004901006149 >>> diff(scorerhi,0); 2/(power(3,'5/6')*gamma('1/3')) 0.2988589049025509052765491 0.2988589049025509052765491 >>> scorerhi(+inf); scorerhi(-inf) +inf 0.0 >>> scorerhi(1) 0.9722051551424333218376886 >>> scorerhi(-1) 0.2206696067929598945381098 Evaluation for large arguments:: >>> scorerhi(10) 455641153.5163291358991077 >>> scorerhi(100) 6.041223996670201399005265e+288 >>> scorerhi(1000000) 7.138269638197858094311122e+289529652 >>> scorerhi(-10) 0.0317685352825022727415011 >>> scorerhi(-100) 0.003183092495767499864680483 >>> scorerhi(100j) (-6.366197716545672122983857e-9 + 0.003183098861710582761688475j) >>> scorerhi(50+50j) (-5.322076267321435669290334e+63 + 1.478450291165243789749427e+65j) >>> scorerhi(-1000-1000j) (0.0001591549432510502796565538 - 0.000159154943091895334973109j) Verifying the differential equation:: >>> for z in [-3.4, 0, 2, 1+2j]: ... chop(diff(scorerhi,z,2) - z*scorerhi(z)) ... 0.3183098861837906715377675 0.3183098861837906715377675 0.3183098861837906715377675 0.3183098861837906715377675 Verifying the integral representation:: >>> z = 0.5 >>> scorerhi(z) 0.6095559998265972956089949 >>> Ai,Bi = airyai,airybi >>> Bi(z)*(Ai(z,-1)-Ai(-inf,-1)) - Ai(z)*(Bi(z,-1)-Bi(-inf,-1)) 0.6095559998265972956089949 """ stirling1 = r""" Gives the Stirling number of the first kind `s(n,k)`, defined by .. math :: x(x-1)(x-2)\cdots(x-n+1) = \sum_{k=0}^n s(n,k) x^k. The value is computed using an integer recurrence. The implementation is not optimized for approximating large values quickly. **Examples** Comparing with the generating function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> taylor(lambda x: ff(x, 5), 0, 5) [0.0, 24.0, -50.0, 35.0, -10.0, 1.0] >>> [stirling1(5, k) for k in range(6)] [0.0, 24.0, -50.0, 35.0, -10.0, 1.0] Recurrence relation:: >>> n, k = 5, 3 >>> stirling1(n+1,k) + n*stirling1(n,k) - stirling1(n,k-1) 0.0 The matrices of Stirling numbers of first and second kind are inverses of each other:: >>> A = matrix(5, 5); B = matrix(5, 5) >>> for n in range(5): ... for k in range(5): ... A[n,k] = stirling1(n,k) ... B[n,k] = stirling2(n,k) ... >>> A * B [1.0 0.0 0.0 0.0 0.0] [0.0 1.0 0.0 0.0 0.0] [0.0 0.0 1.0 0.0 0.0] [0.0 0.0 0.0 1.0 0.0] [0.0 0.0 0.0 0.0 1.0] Pass ``exact=True`` to obtain exact values of Stirling numbers as integers:: >>> stirling1(42, 5) -2.864498971768501633736628e+50 >>> print stirling1(42, 5, exact=True) -286449897176850163373662803014001546235808317440000 """ stirling2 = r""" Gives the Stirling number of the second kind `S(n,k)`, defined by .. math :: x^n = \sum_{k=0}^n S(n,k) x(x-1)(x-2)\cdots(x-k+1) The value is computed using integer arithmetic to evaluate a power sum. The implementation is not optimized for approximating large values quickly. **Examples** Comparing with the generating function:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> taylor(lambda x: sum(stirling2(5,k) * ff(x,k) for k in range(6)), 0, 5) [0.0, 0.0, 0.0, 0.0, 0.0, 1.0] Recurrence relation:: >>> n, k = 5, 3 >>> stirling2(n+1,k) - k*stirling2(n,k) - stirling2(n,k-1) 0.0 Pass ``exact=True`` to obtain exact values of Stirling numbers as integers:: >>> stirling2(52, 10) 2.641822121003543906807485e+45 >>> print stirling2(52, 10, exact=True) 2641822121003543906807485307053638921722527655 """ mpmath-1.1.0/mpmath/functions/000077500000000000000000000000001340375245600163065ustar00rootroot00000000000000mpmath-1.1.0/mpmath/functions/__init__.py000066400000000000000000000004641340375245600204230ustar00rootroot00000000000000from . import functions # Hack to update methods from . import factorials from . import hypergeometric from . import expintegrals from . import bessel from . import orthogonal from . import theta from . import elliptic from . import zeta from . import rszeta from . import zetazeros from . import qfunctions mpmath-1.1.0/mpmath/functions/bessel.py000066400000000000000000001120621340375245600201370ustar00rootroot00000000000000from .functions import defun, defun_wrapped @defun def j0(ctx, x): """Computes the Bessel function `J_0(x)`. See :func:`~mpmath.besselj`.""" return ctx.besselj(0, x) @defun def j1(ctx, x): """Computes the Bessel function `J_1(x)`. See :func:`~mpmath.besselj`.""" return ctx.besselj(1, x) @defun def besselj(ctx, n, z, derivative=0, **kwargs): if type(n) is int: n_isint = True else: n = ctx.convert(n) n_isint = ctx.isint(n) if n_isint: n = int(ctx._re(n)) if n_isint and n < 0: return (-1)**n * ctx.besselj(-n, z, derivative, **kwargs) z = ctx.convert(z) M = ctx.mag(z) if derivative: d = ctx.convert(derivative) # TODO: the integer special-casing shouldn't be necessary. # However, the hypergeometric series gets inaccurate for large d # because of inaccurate pole cancellation at a pole far from # zero (needs to be fixed in hypercomb or hypsum) if ctx.isint(d) and d >= 0: d = int(d) orig = ctx.prec try: ctx.prec += 15 v = ctx.fsum((-1)**k * ctx.binomial(d,k) * ctx.besselj(2*k+n-d,z) for k in range(d+1)) finally: ctx.prec = orig v *= ctx.mpf(2)**(-d) else: def h(n,d): r = ctx.fmul(ctx.fmul(z, z, prec=ctx.prec+M), -0.25, exact=True) B = [0.5*(n-d+1), 0.5*(n-d+2)] 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)] return T v = ctx.hypercomb(h, [n,d], **kwargs) else: # Fast case: J_n(x), n int, appropriate magnitude for fixed-point calculation if (not derivative) and n_isint and abs(M) < 10 and abs(n) < 20: try: return ctx._besselj(n, z) except NotImplementedError: pass if not z: if not n: v = ctx.one + n+z elif ctx.re(n) > 0: v = n*z else: v = ctx.inf + z + n else: #v = 0 orig = ctx.prec try: # XXX: workaround for accuracy in low level hypergeometric series # when alternating, large arguments ctx.prec += min(3*abs(M), ctx.prec) w = ctx.fmul(z, 0.5, exact=True) def h(n): r = ctx.fneg(ctx.fmul(w, w, prec=max(0,ctx.prec+M)), exact=True) return [([w], [n], [], [n+1], [], [n+1], r)] v = ctx.hypercomb(h, [n], **kwargs) finally: ctx.prec = orig v = +v return v @defun def besseli(ctx, n, z, derivative=0, **kwargs): n = ctx.convert(n) z = ctx.convert(z) if not z: if derivative: raise ValueError if not n: # I(0,0) = 1 return 1+n+z if ctx.isint(n): return 0*(n+z) r = ctx.re(n) if r == 0: return ctx.nan*(n+z) elif r > 0: return 0*(n+z) else: return ctx.inf+(n+z) M = ctx.mag(z) if derivative: d = ctx.convert(derivative) def h(n,d): r = ctx.fmul(ctx.fmul(z, z, prec=ctx.prec+M), 0.25, exact=True) B = [0.5*(n-d+1), 0.5*(n-d+2), n+1] 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)] return T v = ctx.hypercomb(h, [n,d], **kwargs) else: def h(n): w = ctx.fmul(z, 0.5, exact=True) r = ctx.fmul(w, w, prec=max(0,ctx.prec+M)) return [([w], [n], [], [n+1], [], [n+1], r)] v = ctx.hypercomb(h, [n], **kwargs) return v @defun_wrapped def bessely(ctx, n, z, derivative=0, **kwargs): if not z: if derivative: # Not implemented raise ValueError if not n: # ~ log(z/2) return -ctx.inf + (n+z) if ctx.im(n): return ctx.nan * (n+z) r = ctx.re(n) q = n+0.5 if ctx.isint(q): if n > 0: return -ctx.inf + (n+z) else: return 0 * (n+z) if r < 0 and int(ctx.floor(q)) % 2: return ctx.inf + (n+z) else: return ctx.ninf + (n+z) # XXX: use hypercomb ctx.prec += 10 m, d = ctx.nint_distance(n) if d < -ctx.prec: h = +ctx.eps ctx.prec *= 2 n += h elif d < 0: ctx.prec -= d # TODO: avoid cancellation for imaginary arguments cos, sin = ctx.cospi_sinpi(n) return (ctx.besselj(n,z,derivative,**kwargs)*cos - \ ctx.besselj(-n,z,derivative,**kwargs))/sin @defun_wrapped def besselk(ctx, n, z, **kwargs): if not z: return ctx.inf M = ctx.mag(z) if M < 1: # Represent as limit definition def h(n): r = (z/2)**2 T1 = [z, 2], [-n, n-1], [n], [], [], [1-n], r T2 = [z, 2], [n, -n-1], [-n], [], [], [1+n], r return T1, T2 # We could use the limit definition always, but it leads # to very bad cancellation (of exponentially large terms) # for large real z # Instead represent in terms of 2F0 else: ctx.prec += M def h(n): return [([ctx.pi/2, z, ctx.exp(-z)], [0.5,-0.5,1], [], [], \ [n+0.5, 0.5-n], [], -1/(2*z))] return ctx.hypercomb(h, [n], **kwargs) @defun_wrapped def hankel1(ctx,n,x,**kwargs): return ctx.besselj(n,x,**kwargs) + ctx.j*ctx.bessely(n,x,**kwargs) @defun_wrapped def hankel2(ctx,n,x,**kwargs): return ctx.besselj(n,x,**kwargs) - ctx.j*ctx.bessely(n,x,**kwargs) @defun_wrapped def whitm(ctx,k,m,z,**kwargs): if z == 0: # M(k,m,z) = 0^(1/2+m) if ctx.re(m) > -0.5: return z elif ctx.re(m) < -0.5: return ctx.inf + z else: return ctx.nan * z x = ctx.fmul(-0.5, z, exact=True) y = 0.5+m return ctx.exp(x) * z**y * ctx.hyp1f1(y-k, 1+2*m, z, **kwargs) @defun_wrapped def whitw(ctx,k,m,z,**kwargs): if z == 0: g = abs(ctx.re(m)) if g < 0.5: return z elif g > 0.5: return ctx.inf + z else: return ctx.nan * z x = ctx.fmul(-0.5, z, exact=True) y = 0.5+m return ctx.exp(x) * z**y * ctx.hyperu(y-k, 1+2*m, z, **kwargs) @defun def hyperu(ctx, a, b, z, **kwargs): a, atype = ctx._convert_param(a) b, btype = ctx._convert_param(b) z = ctx.convert(z) if not z: if ctx.re(b) <= 1: return ctx.gammaprod([1-b],[a-b+1]) else: return ctx.inf + z bb = 1+a-b bb, bbtype = ctx._convert_param(bb) try: orig = ctx.prec try: ctx.prec += 10 v = ctx.hypsum(2, 0, (atype, bbtype), [a, bb], -1/z, maxterms=ctx.prec) return v / z**a finally: ctx.prec = orig except ctx.NoConvergence: pass def h(a,b): w = ctx.sinpi(b) T1 = ([ctx.pi,w],[1,-1],[],[a-b+1,b],[a],[b],z) T2 = ([-ctx.pi,w,z],[1,-1,1-b],[],[a,2-b],[a-b+1],[2-b],z) return T1, T2 return ctx.hypercomb(h, [a,b], **kwargs) @defun def struveh(ctx,n,z, **kwargs): n = ctx.convert(n) z = ctx.convert(z) # http://functions.wolfram.com/Bessel-TypeFunctions/StruveH/26/01/02/ def h(n): return [([z/2, 0.5*ctx.sqrt(ctx.pi)], [n+1, -1], [], [n+1.5], [1], [1.5, n+1.5], -(z/2)**2)] return ctx.hypercomb(h, [n], **kwargs) @defun def struvel(ctx,n,z, **kwargs): n = ctx.convert(n) z = ctx.convert(z) # http://functions.wolfram.com/Bessel-TypeFunctions/StruveL/26/01/02/ def h(n): return [([z/2, 0.5*ctx.sqrt(ctx.pi)], [n+1, -1], [], [n+1.5], [1], [1.5, n+1.5], (z/2)**2)] return ctx.hypercomb(h, [n], **kwargs) def _anger(ctx,which,v,z,**kwargs): v = ctx._convert_param(v)[0] z = ctx.convert(z) def h(v): b = ctx.mpq_1_2 u = v*b m = b*3 a1,a2,b1,b2 = m-u, m+u, 1-u, 1+u c, s = ctx.cospi_sinpi(u) if which == 0: A, B = [b*z, s], [c] if which == 1: A, B = [b*z, -c], [s] w = ctx.square_exp_arg(z, mult=-0.25) T1 = A, [1, 1], [], [a1,a2], [1], [a1,a2], w T2 = B, [1], [], [b1,b2], [1], [b1,b2], w return T1, T2 return ctx.hypercomb(h, [v], **kwargs) @defun def angerj(ctx, v, z, **kwargs): return _anger(ctx, 0, v, z, **kwargs) @defun def webere(ctx, v, z, **kwargs): return _anger(ctx, 1, v, z, **kwargs) @defun def lommels1(ctx, u, v, z, **kwargs): u = ctx._convert_param(u)[0] v = ctx._convert_param(v)[0] z = ctx.convert(z) def h(u,v): b = ctx.mpq_1_2 w = ctx.square_exp_arg(z, mult=-0.25) return ([u-v+1, u+v+1, z], [-1, -1, u+1], [], [], [1], \ [b*(u-v+3),b*(u+v+3)], w), return ctx.hypercomb(h, [u,v], **kwargs) @defun def lommels2(ctx, u, v, z, **kwargs): u = ctx._convert_param(u)[0] v = ctx._convert_param(v)[0] z = ctx.convert(z) # Asymptotic expansion (GR p. 947) -- need to be careful # not to use for small arguments # def h(u,v): # b = ctx.mpq_1_2 # w = -(z/2)**(-2) # return ([z], [u-1], [], [], [b*(1-u+v)], [b*(1-u-v)], w), def h(u,v): b = ctx.mpq_1_2 w = ctx.square_exp_arg(z, mult=-0.25) T1 = [u-v+1, u+v+1, z], [-1, -1, u+1], [], [], [1], [b*(u-v+3),b*(u+v+3)], w T2 = [2, z], [u+v-1, -v], [v, b*(u+v+1)], [b*(v-u+1)], [], [1-v], w T3 = [2, z], [u-v-1, v], [-v, b*(u-v+1)], [b*(1-u-v)], [], [1+v], w #c1 = ctx.cospi((u-v)*b) #c2 = ctx.cospi((u+v)*b) #s = ctx.sinpi(v) #r1 = (u-v+1)*b #r2 = (u+v+1)*b #T2 = [c1, s, z, 2], [1, -1, -v, v], [], [-v+1], [], [-v+1], w #T3 = [-c2, s, z, 2], [1, -1, v, -v], [], [v+1], [], [v+1], w #T2 = [c1, s, z, 2], [1, -1, -v, v+u-1], [r1, r2], [-v+1], [], [-v+1], w #T3 = [-c2, s, z, 2], [1, -1, v, -v+u-1], [r1, r2], [v+1], [], [v+1], w return T1, T2, T3 return ctx.hypercomb(h, [u,v], **kwargs) @defun def ber(ctx, n, z, **kwargs): n = ctx.convert(n) z = ctx.convert(z) # http://functions.wolfram.com/Bessel-TypeFunctions/KelvinBer2/26/01/02/0001/ def h(n): r = -(z/4)**4 cos, sin = ctx.cospi_sinpi(-0.75*n) T1 = [cos, z/2], [1, n], [], [n+1], [], [0.5, 0.5*(n+1), 0.5*n+1], r T2 = [sin, z/2], [1, n+2], [], [n+2], [], [1.5, 0.5*(n+3), 0.5*n+1], r return T1, T2 return ctx.hypercomb(h, [n], **kwargs) @defun def bei(ctx, n, z, **kwargs): n = ctx.convert(n) z = ctx.convert(z) # http://functions.wolfram.com/Bessel-TypeFunctions/KelvinBei2/26/01/02/0001/ def h(n): r = -(z/4)**4 cos, sin = ctx.cospi_sinpi(0.75*n) T1 = [cos, z/2], [1, n+2], [], [n+2], [], [1.5, 0.5*(n+3), 0.5*n+1], r T2 = [sin, z/2], [1, n], [], [n+1], [], [0.5, 0.5*(n+1), 0.5*n+1], r return T1, T2 return ctx.hypercomb(h, [n], **kwargs) @defun def ker(ctx, n, z, **kwargs): n = ctx.convert(n) z = ctx.convert(z) # http://functions.wolfram.com/Bessel-TypeFunctions/KelvinKer2/26/01/02/0001/ def h(n): r = -(z/4)**4 cos1, sin1 = ctx.cospi_sinpi(0.25*n) cos2, sin2 = ctx.cospi_sinpi(0.75*n) T1 = [2, z, 4*cos1], [-n-3, n, 1], [-n], [], [], [0.5, 0.5*(1+n), 0.5*(n+2)], r T2 = [2, z, -sin1], [-n-3, 2+n, 1], [-n-1], [], [], [1.5, 0.5*(3+n), 0.5*(n+2)], r T3 = [2, z, 4*cos2], [n-3, -n, 1], [n], [], [], [0.5, 0.5*(1-n), 1-0.5*n], r T4 = [2, z, -sin2], [n-3, 2-n, 1], [n-1], [], [], [1.5, 0.5*(3-n), 1-0.5*n], r return T1, T2, T3, T4 return ctx.hypercomb(h, [n], **kwargs) @defun def kei(ctx, n, z, **kwargs): n = ctx.convert(n) z = ctx.convert(z) # http://functions.wolfram.com/Bessel-TypeFunctions/KelvinKei2/26/01/02/0001/ def h(n): r = -(z/4)**4 cos1, sin1 = ctx.cospi_sinpi(0.75*n) cos2, sin2 = ctx.cospi_sinpi(0.25*n) T1 = [-cos1, 2, z], [1, n-3, 2-n], [n-1], [], [], [1.5, 0.5*(3-n), 1-0.5*n], r T2 = [-sin1, 2, z], [1, n-1, -n], [n], [], [], [0.5, 0.5*(1-n), 1-0.5*n], r T3 = [-sin2, 2, z], [1, -n-1, n], [-n], [], [], [0.5, 0.5*(n+1), 0.5*(n+2)], r T4 = [-cos2, 2, z], [1, -n-3, n+2], [-n-1], [], [], [1.5, 0.5*(n+3), 0.5*(n+2)], r return T1, T2, T3, T4 return ctx.hypercomb(h, [n], **kwargs) # TODO: do this more generically? def c_memo(f): name = f.__name__ def f_wrapped(ctx): cache = ctx._misc_const_cache prec = ctx.prec p,v = cache.get(name, (-1,0)) if p >= prec: return +v else: cache[name] = (prec, f(ctx)) return cache[name][1] return f_wrapped @c_memo def _airyai_C1(ctx): return 1 / (ctx.cbrt(9) * ctx.gamma(ctx.mpf(2)/3)) @c_memo def _airyai_C2(ctx): return -1 / (ctx.cbrt(3) * ctx.gamma(ctx.mpf(1)/3)) @c_memo def _airybi_C1(ctx): return 1 / (ctx.nthroot(3,6) * ctx.gamma(ctx.mpf(2)/3)) @c_memo def _airybi_C2(ctx): return ctx.nthroot(3,6) / ctx.gamma(ctx.mpf(1)/3) def _airybi_n2_inf(ctx): prec = ctx.prec try: v = ctx.power(3,'2/3')*ctx.gamma('2/3')/(2*ctx.pi) finally: ctx.prec = prec return +v # Derivatives at z = 0 # TODO: could be expressed more elegantly using triple factorials def _airyderiv_0(ctx, z, n, ntype, which): if ntype == 'Z': if n < 0: return z r = ctx.mpq_1_3 prec = ctx.prec try: ctx.prec += 10 v = ctx.gamma((n+1)*r) * ctx.power(3,n*r) / ctx.pi if which == 0: v *= ctx.sinpi(2*(n+1)*r) v /= ctx.power(3,'2/3') else: v *= abs(ctx.sinpi(2*(n+1)*r)) v /= ctx.power(3,'1/6') finally: ctx.prec = prec return +v + z else: # singular (does the limit exist?) raise NotImplementedError @defun def airyai(ctx, z, derivative=0, **kwargs): z = ctx.convert(z) if derivative: n, ntype = ctx._convert_param(derivative) else: n = 0 # Values at infinities if not ctx.isnormal(z) and z: if n and ntype == 'Z': if n == -1: if z == ctx.inf: return ctx.mpf(1)/3 + 1/z if z == ctx.ninf: return ctx.mpf(-2)/3 + 1/z if n < -1: if z == ctx.inf: return z if z == ctx.ninf: return (-1)**n * (-z) if (not n) and z == ctx.inf or z == ctx.ninf: return 1/z # TODO: limits raise ValueError("essential singularity of Ai(z)") # Account for exponential scaling if z: extraprec = max(0, int(1.5*ctx.mag(z))) else: extraprec = 0 if n: if n == 1: def h(): # http://functions.wolfram.com/03.07.06.0005.01 if ctx._re(z) > 4: ctx.prec += extraprec w = z**1.5; r = -0.75/w; u = -2*w/3 ctx.prec -= extraprec C = -ctx.exp(u)/(2*ctx.sqrt(ctx.pi))*ctx.nthroot(z,4) return ([C],[1],[],[],[(-1,6),(7,6)],[],r), # http://functions.wolfram.com/03.07.26.0001.01 else: ctx.prec += extraprec w = z**3 / 9 ctx.prec -= extraprec C1 = _airyai_C1(ctx) * 0.5 C2 = _airyai_C2(ctx) T1 = [C1,z],[1,2],[],[],[],[ctx.mpq_5_3],w T2 = [C2],[1],[],[],[],[ctx.mpq_1_3],w return T1, T2 return ctx.hypercomb(h, [], **kwargs) else: if z == 0: return _airyderiv_0(ctx, z, n, ntype, 0) # http://functions.wolfram.com/03.05.20.0004.01 def h(n): ctx.prec += extraprec w = z**3/9 ctx.prec -= extraprec q13,q23,q43 = ctx.mpq_1_3, ctx.mpq_2_3, ctx.mpq_4_3 a1=q13; a2=1; b1=(1-n)*q13; b2=(2-n)*q13; b3=1-n*q13 T1 = [3, z], [n-q23, -n], [a1], [b1,b2,b3], \ [a1,a2], [b1,b2,b3], w a1=q23; b1=(2-n)*q13; b2=1-n*q13; b3=(4-n)*q13 T2 = [3, z, -z], [n-q43, -n, 1], [a1], [b1,b2,b3], \ [a1,a2], [b1,b2,b3], w return T1, T2 v = ctx.hypercomb(h, [n], **kwargs) if ctx._is_real_type(z) and ctx.isint(n): v = ctx._re(v) return v else: def h(): if ctx._re(z) > 4: # We could use 1F1, but it results in huge cancellation; # the following expansion is better. # TODO: asymptotic series for derivatives ctx.prec += extraprec w = z**1.5; r = -0.75/w; u = -2*w/3 ctx.prec -= extraprec C = ctx.exp(u)/(2*ctx.sqrt(ctx.pi)*ctx.nthroot(z,4)) return ([C],[1],[],[],[(1,6),(5,6)],[],r), else: ctx.prec += extraprec w = z**3 / 9 ctx.prec -= extraprec C1 = _airyai_C1(ctx) C2 = _airyai_C2(ctx) T1 = [C1],[1],[],[],[],[ctx.mpq_2_3],w T2 = [z*C2],[1],[],[],[],[ctx.mpq_4_3],w return T1, T2 return ctx.hypercomb(h, [], **kwargs) @defun def airybi(ctx, z, derivative=0, **kwargs): z = ctx.convert(z) if derivative: n, ntype = ctx._convert_param(derivative) else: n = 0 # Values at infinities if not ctx.isnormal(z) and z: if n and ntype == 'Z': if z == ctx.inf: return z if z == ctx.ninf: if n == -1: return 1/z if n == -2: return _airybi_n2_inf(ctx) if n < -2: return (-1)**n * (-z) if not n: if z == ctx.inf: return z if z == ctx.ninf: return 1/z # TODO: limits raise ValueError("essential singularity of Bi(z)") if z: extraprec = max(0, int(1.5*ctx.mag(z))) else: extraprec = 0 if n: if n == 1: # http://functions.wolfram.com/03.08.26.0001.01 def h(): ctx.prec += extraprec w = z**3 / 9 ctx.prec -= extraprec C1 = _airybi_C1(ctx)*0.5 C2 = _airybi_C2(ctx) T1 = [C1,z],[1,2],[],[],[],[ctx.mpq_5_3],w T2 = [C2],[1],[],[],[],[ctx.mpq_1_3],w return T1, T2 return ctx.hypercomb(h, [], **kwargs) else: if z == 0: return _airyderiv_0(ctx, z, n, ntype, 1) def h(n): ctx.prec += extraprec w = z**3/9 ctx.prec -= extraprec q13,q23,q43 = ctx.mpq_1_3, ctx.mpq_2_3, ctx.mpq_4_3 q16 = ctx.mpq_1_6 q56 = ctx.mpq_5_6 a1=q13; a2=1; b1=(1-n)*q13; b2=(2-n)*q13; b3=1-n*q13 T1 = [3, z], [n-q16, -n], [a1], [b1,b2,b3], \ [a1,a2], [b1,b2,b3], w a1=q23; b1=(2-n)*q13; b2=1-n*q13; b3=(4-n)*q13 T2 = [3, z], [n-q56, 1-n], [a1], [b1,b2,b3], \ [a1,a2], [b1,b2,b3], w return T1, T2 v = ctx.hypercomb(h, [n], **kwargs) if ctx._is_real_type(z) and ctx.isint(n): v = ctx._re(v) return v else: def h(): ctx.prec += extraprec w = z**3 / 9 ctx.prec -= extraprec C1 = _airybi_C1(ctx) C2 = _airybi_C2(ctx) T1 = [C1],[1],[],[],[],[ctx.mpq_2_3],w T2 = [z*C2],[1],[],[],[],[ctx.mpq_4_3],w return T1, T2 return ctx.hypercomb(h, [], **kwargs) def _airy_zero(ctx, which, k, derivative, complex=False): # Asymptotic formulas are given in DLMF section 9.9 def U(t): return t**(2/3.)*(1-7/(t**2*48)) def T(t): return t**(2/3.)*(1+5/(t**2*48)) k = int(k) if k < 1: raise ValueError("k cannot be less than 1") if not derivative in (0,1): raise ValueError("Derivative should lie between 0 and 1") if which == 0: if derivative: return ctx.findroot(lambda z: ctx.airyai(z,1), -U(3*ctx.pi*(4*k-3)/8)) return ctx.findroot(ctx.airyai, -T(3*ctx.pi*(4*k-1)/8)) if which == 1 and complex == False: if derivative: return ctx.findroot(lambda z: ctx.airybi(z,1), -U(3*ctx.pi*(4*k-1)/8)) return ctx.findroot(ctx.airybi, -T(3*ctx.pi*(4*k-3)/8)) if which == 1 and complex == True: if derivative: t = 3*ctx.pi*(4*k-3)/8 + 0.75j*ctx.ln2 s = ctx.expjpi(ctx.mpf(1)/3) * T(t) return ctx.findroot(lambda z: ctx.airybi(z,1), s) t = 3*ctx.pi*(4*k-1)/8 + 0.75j*ctx.ln2 s = ctx.expjpi(ctx.mpf(1)/3) * U(t) return ctx.findroot(ctx.airybi, s) @defun def airyaizero(ctx, k, derivative=0): return _airy_zero(ctx, 0, k, derivative, False) @defun def airybizero(ctx, k, derivative=0, complex=False): return _airy_zero(ctx, 1, k, derivative, complex) def _scorer(ctx, z, which, kwargs): z = ctx.convert(z) if ctx.isinf(z): if z == ctx.inf: if which == 0: return 1/z if which == 1: return z if z == ctx.ninf: return 1/z raise ValueError("essential singularity") if z: extraprec = max(0, int(1.5*ctx.mag(z))) else: extraprec = 0 if kwargs.get('derivative'): raise NotImplementedError # Direct asymptotic expansions, to avoid # exponentially large cancellation try: if ctx.mag(z) > 3: if which == 0 and abs(ctx.arg(z)) < ctx.pi/3 * 0.999: def h(): return (([ctx.pi,z],[-1,-1],[],[],[(1,3),(2,3),1],[],9/z**3),) return ctx.hypercomb(h, [], maxterms=ctx.prec, force_series=True) if which == 1 and abs(ctx.arg(-z)) < 2*ctx.pi/3 * 0.999: def h(): return (([-ctx.pi,z],[-1,-1],[],[],[(1,3),(2,3),1],[],9/z**3),) return ctx.hypercomb(h, [], maxterms=ctx.prec, force_series=True) except ctx.NoConvergence: pass def h(): A = ctx.airybi(z, **kwargs)/3 B = -2*ctx.pi if which == 1: A *= 2 B *= -1 ctx.prec += extraprec w = z**3/9 ctx.prec -= extraprec T1 = [A], [1], [], [], [], [], 0 T2 = [B,z], [-1,2], [], [], [1], [ctx.mpq_4_3,ctx.mpq_5_3], w return T1, T2 return ctx.hypercomb(h, [], **kwargs) @defun def scorergi(ctx, z, **kwargs): return _scorer(ctx, z, 0, kwargs) @defun def scorerhi(ctx, z, **kwargs): return _scorer(ctx, z, 1, kwargs) @defun_wrapped def coulombc(ctx, l, eta, _cache={}): if (l, eta) in _cache and _cache[l,eta][0] >= ctx.prec: return +_cache[l,eta][1] G3 = ctx.loggamma(2*l+2) G1 = ctx.loggamma(1+l+ctx.j*eta) G2 = ctx.loggamma(1+l-ctx.j*eta) v = 2**l * ctx.exp((-ctx.pi*eta+G1+G2)/2 - G3) if not (ctx.im(l) or ctx.im(eta)): v = ctx.re(v) _cache[l,eta] = (ctx.prec, v) return v @defun_wrapped def coulombf(ctx, l, eta, z, w=1, chop=True, **kwargs): # Regular Coulomb wave function # Note: w can be either 1 or -1; the other may be better in some cases # TODO: check that chop=True chops when and only when it should #ctx.prec += 10 def h(l, eta): try: jw = ctx.j*w jwz = ctx.fmul(jw, z, exact=True) jwz2 = ctx.fmul(jwz, -2, exact=True) C = ctx.coulombc(l, eta) T1 = [C, z, ctx.exp(jwz)], [1, l+1, 1], [], [], [1+l+jw*eta], \ [2*l+2], jwz2 except ValueError: T1 = [0], [-1], [], [], [], [], 0 return (T1,) v = ctx.hypercomb(h, [l,eta], **kwargs) if chop and (not ctx.im(l)) and (not ctx.im(eta)) and (not ctx.im(z)) and \ (ctx.re(z) >= 0): v = ctx.re(v) return v @defun_wrapped def _coulomb_chi(ctx, l, eta, _cache={}): if (l, eta) in _cache and _cache[l,eta][0] >= ctx.prec: return _cache[l,eta][1] def terms(): l2 = -l-1 jeta = ctx.j*eta return [ctx.loggamma(1+l+jeta) * (-0.5j), ctx.loggamma(1+l-jeta) * (0.5j), ctx.loggamma(1+l2+jeta) * (0.5j), ctx.loggamma(1+l2-jeta) * (-0.5j), -(l+0.5)*ctx.pi] v = ctx.sum_accurately(terms, 1) _cache[l,eta] = (ctx.prec, v) return v @defun_wrapped def coulombg(ctx, l, eta, z, w=1, chop=True, **kwargs): # Irregular Coulomb wave function # Note: w can be either 1 or -1; the other may be better in some cases # TODO: check that chop=True chops when and only when it should if not ctx._im(l): l = ctx._re(l) # XXX: for isint def h(l, eta): # Force perturbation for integers and half-integers if ctx.isint(l*2): T1 = [0], [-1], [], [], [], [], 0 return (T1,) l2 = -l-1 try: chi = ctx._coulomb_chi(l, eta) jw = ctx.j*w s = ctx.sin(chi); c = ctx.cos(chi) C1 = ctx.coulombc(l,eta) C2 = ctx.coulombc(l2,eta) u = ctx.exp(jw*z) x = -2*jw*z T1 = [s, C1, z, u, c], [-1, 1, l+1, 1, 1], [], [], \ [1+l+jw*eta], [2*l+2], x T2 = [-s, C2, z, u], [-1, 1, l2+1, 1], [], [], \ [1+l2+jw*eta], [2*l2+2], x return T1, T2 except ValueError: T1 = [0], [-1], [], [], [], [], 0 return (T1,) v = ctx.hypercomb(h, [l,eta], **kwargs) if chop and (not ctx._im(l)) and (not ctx._im(eta)) and (not ctx._im(z)) and \ (ctx._re(z) >= 0): v = ctx._re(v) return v def mcmahon(ctx,kind,prime,v,m): """ Computes an estimate for the location of the Bessel function zero j_{v,m}, y_{v,m}, j'_{v,m} or y'_{v,m} using McMahon's asymptotic expansion (Abramowitz & Stegun 9.5.12-13, DLMF 20.21(vi)). Returns (r,err) where r is the estimated location of the root and err is a positive number estimating the error of the asymptotic expansion. """ u = 4*v**2 if kind == 1 and not prime: b = (4*m+2*v-1)*ctx.pi/4 if kind == 2 and not prime: b = (4*m+2*v-3)*ctx.pi/4 if kind == 1 and prime: b = (4*m+2*v-3)*ctx.pi/4 if kind == 2 and prime: b = (4*m+2*v-1)*ctx.pi/4 if not prime: s1 = b s2 = -(u-1)/(8*b) s3 = -4*(u-1)*(7*u-31)/(3*(8*b)**3) s4 = -32*(u-1)*(83*u**2-982*u+3779)/(15*(8*b)**5) s5 = -64*(u-1)*(6949*u**3-153855*u**2+1585743*u-6277237)/(105*(8*b)**7) if prime: s1 = b s2 = -(u+3)/(8*b) s3 = -4*(7*u**2+82*u-9)/(3*(8*b)**3) s4 = -32*(83*u**3+2075*u**2-3039*u+3537)/(15*(8*b)**5) s5 = -64*(6949*u**4+296492*u**3-1248002*u**2+7414380*u-5853627)/(105*(8*b)**7) terms = [s1,s2,s3,s4,s5] s = s1 err = 0.0 for i in range(1,len(terms)): if abs(terms[i]) < abs(terms[i-1]): s += terms[i] else: err = abs(terms[i]) if i == len(terms)-1: err = abs(terms[-1]) return s, err def generalized_bisection(ctx,f,a,b,n): """ Given f known to have exactly n simple roots within [a,b], return a list of n intervals isolating the roots and having opposite signs at the endpoints. TODO: this can be optimized, e.g. by reusing evaluation points. """ if n < 1: raise ValueError("n cannot be less than 1") N = n+1 points = [] signs = [] while 1: points = ctx.linspace(a,b,N) signs = [ctx.sign(f(x)) for x in points] ok_intervals = [(points[i],points[i+1]) for i in range(N-1) \ if signs[i]*signs[i+1] == -1] if len(ok_intervals) == n: return ok_intervals N = N*2 def find_in_interval(ctx, f, ab): return ctx.findroot(f, ab, solver='illinois', verify=False) def bessel_zero(ctx, kind, prime, v, m, isoltol=0.01, _interval_cache={}): prec = ctx.prec workprec = max(prec, ctx.mag(v), ctx.mag(m))+10 try: ctx.prec = workprec v = ctx.mpf(v) m = int(m) prime = int(prime) if v < 0: raise ValueError("v cannot be negative") if m < 1: raise ValueError("m cannot be less than 1") if not prime in (0,1): raise ValueError("prime should lie between 0 and 1") if kind == 1: if prime: f = lambda x: ctx.besselj(v,x,derivative=1) else: f = lambda x: ctx.besselj(v,x) if kind == 2: if prime: f = lambda x: ctx.bessely(v,x,derivative=1) else: f = lambda x: ctx.bessely(v,x) # The first root of J' is very close to 0 for small # orders, and this needs to be special-cased if kind == 1 and prime and m == 1: if v == 0: return ctx.zero if v <= 1: # TODO: use v <= j'_{v,1} < y_{v,1}? r = 2*ctx.sqrt(v*(1+v)/(v+2)) return find_in_interval(ctx, f, (r/10, 2*r)) if (kind,prime,v,m) in _interval_cache: return find_in_interval(ctx, f, _interval_cache[kind,prime,v,m]) r, err = mcmahon(ctx, kind, prime, v, m) if err < isoltol: return find_in_interval(ctx, f, (r-isoltol, r+isoltol)) # An x such that 0 < x < r_{v,1} if kind == 1 and not prime: low = 2.4 if kind == 1 and prime: low = 1.8 if kind == 2 and not prime: low = 0.8 if kind == 2 and prime: low = 2.0 n = m+1 while 1: r1, err = mcmahon(ctx, kind, prime, v, n) if err < isoltol: r2, err2 = mcmahon(ctx, kind, prime, v, n+1) intervals = generalized_bisection(ctx, f, low, 0.5*(r1+r2), n) for k, ab in enumerate(intervals): _interval_cache[kind,prime,v,k+1] = ab return find_in_interval(ctx, f, intervals[m-1]) else: n = n*2 finally: ctx.prec = prec @defun def besseljzero(ctx, v, m, derivative=0): r""" For a real order `\nu \ge 0` and a positive integer `m`, returns `j_{\nu,m}`, the `m`-th positive zero of the Bessel function of the first kind `J_{\nu}(z)` (see :func:`~mpmath.besselj`). Alternatively, with *derivative=1*, gives the first nonnegative simple zero `j'_{\nu,m}` of `J'_{\nu}(z)`. The indexing convention is that used by Abramowitz & Stegun and the DLMF. Note the special case `j'_{0,1} = 0`, while all other zeros are positive. In effect, only simple zeros are counted (all zeros of Bessel functions are simple except possibly `z = 0`) and `j_{\nu,m}` becomes a monotonic function of both `\nu` and `m`. The zeros are interlaced according to the inequalities .. math :: j'_{\nu,k} < j_{\nu,k} < j'_{\nu,k+1} j_{\nu,1} < j_{\nu+1,2} < j_{\nu,2} < j_{\nu+1,2} < j_{\nu,3} < \cdots **Examples** Initial zeros of the Bessel functions `J_0(z), J_1(z), J_2(z)`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> besseljzero(0,1); besseljzero(0,2); besseljzero(0,3) 2.404825557695772768621632 5.520078110286310649596604 8.653727912911012216954199 >>> besseljzero(1,1); besseljzero(1,2); besseljzero(1,3) 3.831705970207512315614436 7.01558666981561875353705 10.17346813506272207718571 >>> besseljzero(2,1); besseljzero(2,2); besseljzero(2,3) 5.135622301840682556301402 8.417244140399864857783614 11.61984117214905942709415 Initial zeros of `J'_0(z), J'_1(z), J'_2(z)`:: 0.0 3.831705970207512315614436 7.01558666981561875353705 >>> besseljzero(1,1,1); besseljzero(1,2,1); besseljzero(1,3,1) 1.84118378134065930264363 5.331442773525032636884016 8.536316366346285834358961 >>> besseljzero(2,1,1); besseljzero(2,2,1); besseljzero(2,3,1) 3.054236928227140322755932 6.706133194158459146634394 9.969467823087595793179143 Zeros with large index:: >>> besseljzero(0,100); besseljzero(0,1000); besseljzero(0,10000) 313.3742660775278447196902 3140.807295225078628895545 31415.14114171350798533666 >>> besseljzero(5,100); besseljzero(5,1000); besseljzero(5,10000) 321.1893195676003157339222 3148.657306813047523500494 31422.9947255486291798943 >>> besseljzero(0,100,1); besseljzero(0,1000,1); besseljzero(0,10000,1) 311.8018681873704508125112 3139.236339643802482833973 31413.57032947022399485808 Zeros of functions with large order:: >>> besseljzero(50,1) 57.11689916011917411936228 >>> besseljzero(50,2) 62.80769876483536093435393 >>> besseljzero(50,100) 388.6936600656058834640981 >>> besseljzero(50,1,1) 52.99764038731665010944037 >>> besseljzero(50,2,1) 60.02631933279942589882363 >>> besseljzero(50,100,1) 387.1083151608726181086283 Zeros of functions with fractional order:: >>> besseljzero(0.5,1); besseljzero(1.5,1); besseljzero(2.25,4) 3.141592653589793238462643 4.493409457909064175307881 15.15657692957458622921634 Both `J_{\nu}(z)` and `J'_{\nu}(z)` can be expressed as infinite products over their zeros:: >>> v,z = 2, mpf(1) >>> (z/2)**v/gamma(v+1) * \ ... nprod(lambda k: 1-(z/besseljzero(v,k))**2, [1,inf]) ... 0.1149034849319004804696469 >>> besselj(v,z) 0.1149034849319004804696469 >>> (z/2)**(v-1)/2/gamma(v) * \ ... nprod(lambda k: 1-(z/besseljzero(v,k,1))**2, [1,inf]) ... 0.2102436158811325550203884 >>> besselj(v,z,1) 0.2102436158811325550203884 """ return +bessel_zero(ctx, 1, derivative, v, m) @defun def besselyzero(ctx, v, m, derivative=0): r""" For a real order `\nu \ge 0` and a positive integer `m`, returns `y_{\nu,m}`, the `m`-th positive zero of the Bessel function of the second kind `Y_{\nu}(z)` (see :func:`~mpmath.bessely`). Alternatively, with *derivative=1*, gives the first positive zero `y'_{\nu,m}` of `Y'_{\nu}(z)`. The zeros are interlaced according to the inequalities .. math :: y_{\nu,k} < y'_{\nu,k} < y_{\nu,k+1} y_{\nu,1} < y_{\nu+1,2} < y_{\nu,2} < y_{\nu+1,2} < y_{\nu,3} < \cdots **Examples** Initial zeros of the Bessel functions `Y_0(z), Y_1(z), Y_2(z)`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> besselyzero(0,1); besselyzero(0,2); besselyzero(0,3) 0.8935769662791675215848871 3.957678419314857868375677 7.086051060301772697623625 >>> besselyzero(1,1); besselyzero(1,2); besselyzero(1,3) 2.197141326031017035149034 5.429681040794135132772005 8.596005868331168926429606 >>> besselyzero(2,1); besselyzero(2,2); besselyzero(2,3) 3.384241767149593472701426 6.793807513268267538291167 10.02347797936003797850539 Initial zeros of `Y'_0(z), Y'_1(z), Y'_2(z)`:: >>> besselyzero(0,1,1); besselyzero(0,2,1); besselyzero(0,3,1) 2.197141326031017035149034 5.429681040794135132772005 8.596005868331168926429606 >>> besselyzero(1,1,1); besselyzero(1,2,1); besselyzero(1,3,1) 3.683022856585177699898967 6.941499953654175655751944 10.12340465543661307978775 >>> besselyzero(2,1,1); besselyzero(2,2,1); besselyzero(2,3,1) 5.002582931446063945200176 8.350724701413079526349714 11.57419546521764654624265 Zeros with large index:: >>> besselyzero(0,100); besselyzero(0,1000); besselyzero(0,10000) 311.8034717601871549333419 3139.236498918198006794026 31413.57034538691205229188 >>> besselyzero(5,100); besselyzero(5,1000); besselyzero(5,10000) 319.6183338562782156235062 3147.086508524556404473186 31421.42392920214673402828 >>> besselyzero(0,100,1); besselyzero(0,1000,1); besselyzero(0,10000,1) 313.3726705426359345050449 3140.807136030340213610065 31415.14112579761578220175 Zeros of functions with large order:: >>> besselyzero(50,1) 53.50285882040036394680237 >>> besselyzero(50,2) 60.11244442774058114686022 >>> besselyzero(50,100) 387.1096509824943957706835 >>> besselyzero(50,1,1) 56.96290427516751320063605 >>> besselyzero(50,2,1) 62.74888166945933944036623 >>> besselyzero(50,100,1) 388.6923300548309258355475 Zeros of functions with fractional order:: >>> besselyzero(0.5,1); besselyzero(1.5,1); besselyzero(2.25,4) 1.570796326794896619231322 2.798386045783887136720249 13.56721208770735123376018 """ return +bessel_zero(ctx, 2, derivative, v, m) mpmath-1.1.0/mpmath/functions/elliptic.py000066400000000000000000001141661340375245600204760ustar00rootroot00000000000000r""" Elliptic functions historically comprise the elliptic integrals and their inverses, and originate from the problem of computing the arc length of an ellipse. From a more modern point of view, an elliptic function is defined as a doubly periodic function, i.e. a function which satisfies .. math :: f(z + 2 \omega_1) = f(z + 2 \omega_2) = f(z) for some half-periods `\omega_1, \omega_2` with `\mathrm{Im}[\omega_1 / \omega_2] > 0`. The canonical elliptic functions are the Jacobi elliptic functions. More broadly, this section includes quasi-doubly periodic functions (such as the Jacobi theta functions) and other functions useful in the study of elliptic functions. Many different conventions for the arguments of elliptic functions are in use. It is even standard to use different parameterizations for different functions in the same text or software (and mpmath is no exception). The usual parameters are the elliptic nome `q`, which usually must satisfy `|q| < 1`; the elliptic parameter `m` (an arbitrary complex number); the elliptic modulus `k` (an arbitrary complex number); and the half-period ratio `\tau`, which usually must satisfy `\mathrm{Im}[\tau] > 0`. These quantities can be expressed in terms of each other using the following relations: .. math :: m = k^2 .. math :: \tau = i \frac{K(1-m)}{K(m)} .. math :: q = e^{i \pi \tau} .. math :: k = \frac{\vartheta_2^2(q)}{\vartheta_3^2(q)} In addition, an alternative definition is used for the nome in number theory, which we here denote by q-bar: .. math :: \bar{q} = q^2 = e^{2 i \pi \tau} For convenience, mpmath provides functions to convert between the various parameters (:func:`~mpmath.qfrom`, :func:`~mpmath.mfrom`, :func:`~mpmath.kfrom`, :func:`~mpmath.taufrom`, :func:`~mpmath.qbarfrom`). **References** 1. [AbramowitzStegun]_ 2. [WhittakerWatson]_ """ from .functions import defun, defun_wrapped def nome(ctx, m): m = ctx.convert(m) if not m: return m if m == ctx.one: return m if ctx.isnan(m): return m if ctx.isinf(m): if m == ctx.ninf: return type(m)(-1) else: return ctx.mpc(-1) a = ctx.ellipk(ctx.one-m) b = ctx.ellipk(m) v = ctx.exp(-ctx.pi*a/b) if not ctx._im(m) and ctx._re(m) < 1: if ctx._is_real_type(m): return v.real else: return v.real + 0j elif m == 2: v = ctx.mpc(0, v.imag) return v @defun_wrapped def qfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None): r""" Returns the elliptic nome `q`, given any of `q, m, k, \tau, \bar{q}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> qfrom(q=0.25) 0.25 >>> qfrom(m=mfrom(q=0.25)) 0.25 >>> qfrom(k=kfrom(q=0.25)) 0.25 >>> qfrom(tau=taufrom(q=0.25)) (0.25 + 0.0j) >>> qfrom(qbar=qbarfrom(q=0.25)) 0.25 """ if q is not None: return ctx.convert(q) if m is not None: return nome(ctx, m) if k is not None: return nome(ctx, ctx.convert(k)**2) if tau is not None: return ctx.expjpi(tau) if qbar is not None: return ctx.sqrt(qbar) @defun_wrapped def qbarfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None): r""" Returns the number-theoretic nome `\bar q`, given any of `q, m, k, \tau, \bar{q}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> qbarfrom(qbar=0.25) 0.25 >>> qbarfrom(q=qfrom(qbar=0.25)) 0.25 >>> qbarfrom(m=extraprec(20)(mfrom)(qbar=0.25)) # ill-conditioned 0.25 >>> qbarfrom(k=extraprec(20)(kfrom)(qbar=0.25)) # ill-conditioned 0.25 >>> qbarfrom(tau=taufrom(qbar=0.25)) (0.25 + 0.0j) """ if qbar is not None: return ctx.convert(qbar) if q is not None: return ctx.convert(q) ** 2 if m is not None: return nome(ctx, m) ** 2 if k is not None: return nome(ctx, ctx.convert(k)**2) ** 2 if tau is not None: return ctx.expjpi(2*tau) @defun_wrapped def taufrom(ctx, q=None, m=None, k=None, tau=None, qbar=None): r""" Returns the elliptic half-period ratio `\tau`, given any of `q, m, k, \tau, \bar{q}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> taufrom(tau=0.5j) (0.0 + 0.5j) >>> taufrom(q=qfrom(tau=0.5j)) (0.0 + 0.5j) >>> taufrom(m=mfrom(tau=0.5j)) (0.0 + 0.5j) >>> taufrom(k=kfrom(tau=0.5j)) (0.0 + 0.5j) >>> taufrom(qbar=qbarfrom(tau=0.5j)) (0.0 + 0.5j) """ if tau is not None: return ctx.convert(tau) if m is not None: m = ctx.convert(m) return ctx.j*ctx.ellipk(1-m)/ctx.ellipk(m) if k is not None: k = ctx.convert(k) return ctx.j*ctx.ellipk(1-k**2)/ctx.ellipk(k**2) if q is not None: return ctx.log(q) / (ctx.pi*ctx.j) if qbar is not None: qbar = ctx.convert(qbar) return ctx.log(qbar) / (2*ctx.pi*ctx.j) @defun_wrapped def kfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None): r""" Returns the elliptic modulus `k`, given any of `q, m, k, \tau, \bar{q}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> kfrom(k=0.25) 0.25 >>> kfrom(m=mfrom(k=0.25)) 0.25 >>> kfrom(q=qfrom(k=0.25)) 0.25 >>> kfrom(tau=taufrom(k=0.25)) (0.25 + 0.0j) >>> kfrom(qbar=qbarfrom(k=0.25)) 0.25 As `q \to 1` and `q \to -1`, `k` rapidly approaches `1` and `i \infty` respectively:: >>> kfrom(q=0.75) 0.9999999999999899166471767 >>> kfrom(q=-0.75) (0.0 + 7041781.096692038332790615j) >>> kfrom(q=1) 1 >>> kfrom(q=-1) (0.0 + +infj) """ if k is not None: return ctx.convert(k) if m is not None: return ctx.sqrt(m) if tau is not None: q = ctx.expjpi(tau) if qbar is not None: q = ctx.sqrt(qbar) if q == 1: return q if q == -1: return ctx.mpc(0,'inf') return (ctx.jtheta(2,0,q)/ctx.jtheta(3,0,q))**2 @defun_wrapped def mfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None): r""" Returns the elliptic parameter `m`, given any of `q, m, k, \tau, \bar{q}`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> mfrom(m=0.25) 0.25 >>> mfrom(q=qfrom(m=0.25)) 0.25 >>> mfrom(k=kfrom(m=0.25)) 0.25 >>> mfrom(tau=taufrom(m=0.25)) (0.25 + 0.0j) >>> mfrom(qbar=qbarfrom(m=0.25)) 0.25 As `q \to 1` and `q \to -1`, `m` rapidly approaches `1` and `-\infty` respectively:: >>> mfrom(q=0.75) 0.9999999999999798332943533 >>> mfrom(q=-0.75) -49586681013729.32611558353 >>> mfrom(q=1) 1.0 >>> mfrom(q=-1) -inf The inverse nome as a function of `q` has an integer Taylor series expansion:: >>> taylor(lambda q: mfrom(q), 0, 7) [0.0, 16.0, -128.0, 704.0, -3072.0, 11488.0, -38400.0, 117632.0] """ if m is not None: return m if k is not None: return k**2 if tau is not None: q = ctx.expjpi(tau) if qbar is not None: q = ctx.sqrt(qbar) if q == 1: return ctx.convert(q) if q == -1: return q*ctx.inf v = (ctx.jtheta(2,0,q)/ctx.jtheta(3,0,q))**4 if ctx._is_real_type(q) and q < 0: v = v.real return v jacobi_spec = { 'sn' : ([3],[2],[1],[4], 'sin', 'tanh'), 'cn' : ([4],[2],[2],[4], 'cos', 'sech'), 'dn' : ([4],[3],[3],[4], '1', 'sech'), 'ns' : ([2],[3],[4],[1], 'csc', 'coth'), 'nc' : ([2],[4],[4],[2], 'sec', 'cosh'), 'nd' : ([3],[4],[4],[3], '1', 'cosh'), 'sc' : ([3],[4],[1],[2], 'tan', 'sinh'), 'sd' : ([3,3],[2,4],[1],[3], 'sin', 'sinh'), 'cd' : ([3],[2],[2],[3], 'cos', '1'), 'cs' : ([4],[3],[2],[1], 'cot', 'csch'), 'dc' : ([2],[3],[3],[2], 'sec', '1'), 'ds' : ([2,4],[3,3],[3],[1], 'csc', 'csch'), 'cc' : None, 'ss' : None, 'nn' : None, 'dd' : None } @defun def ellipfun(ctx, kind, u=None, m=None, q=None, k=None, tau=None): try: S = jacobi_spec[kind] except KeyError: raise ValueError("First argument must be a two-character string " "containing 's', 'c', 'd' or 'n', e.g.: 'sn'") if u is None: def f(*args, **kwargs): return ctx.ellipfun(kind, *args, **kwargs) f.__name__ = kind return f prec = ctx.prec try: ctx.prec += 10 u = ctx.convert(u) q = ctx.qfrom(m=m, q=q, k=k, tau=tau) if S is None: v = ctx.one + 0*q*u elif q == ctx.zero: if S[4] == '1': v = ctx.one else: v = getattr(ctx, S[4])(u) v += 0*q*u elif q == ctx.one: if S[5] == '1': v = ctx.one else: v = getattr(ctx, S[5])(u) v += 0*q*u else: t = u / ctx.jtheta(3, 0, q)**2 v = ctx.one for a in S[0]: v *= ctx.jtheta(a, 0, q) for b in S[1]: v /= ctx.jtheta(b, 0, q) for c in S[2]: v *= ctx.jtheta(c, t, q) for d in S[3]: v /= ctx.jtheta(d, t, q) finally: ctx.prec = prec return +v @defun_wrapped def kleinj(ctx, tau=None, **kwargs): r""" Evaluates the Klein j-invariant, which is a modular function defined for `\tau` in the upper half-plane as .. math :: J(\tau) = \frac{g_2^3(\tau)}{g_2^3(\tau) - 27 g_3^2(\tau)} where `g_2` and `g_3` are the modular invariants of the Weierstrass elliptic function, .. math :: g_2(\tau) = 60 \sum_{(m,n) \in \mathbb{Z}^2 \setminus (0,0)} (m \tau+n)^{-4} g_3(\tau) = 140 \sum_{(m,n) \in \mathbb{Z}^2 \setminus (0,0)} (m \tau+n)^{-6}. An alternative, common notation is that of the j-function `j(\tau) = 1728 J(\tau)`. **Plots** .. literalinclude :: /plots/kleinj.py .. image :: /plots/kleinj.png .. literalinclude :: /plots/kleinj2.py .. image :: /plots/kleinj2.png **Examples** Verifying the functional equation `J(\tau) = J(\tau+1) = J(-\tau^{-1})`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> tau = 0.625+0.75*j >>> tau = 0.625+0.75*j >>> kleinj(tau) (-0.1507492166511182267125242 + 0.07595948379084571927228948j) >>> kleinj(tau+1) (-0.1507492166511182267125242 + 0.07595948379084571927228948j) >>> kleinj(-1/tau) (-0.1507492166511182267125242 + 0.07595948379084571927228946j) The j-function has a famous Laurent series expansion in terms of the nome `\bar{q}`, `j(\tau) = \bar{q}^{-1} + 744 + 196884\bar{q} + \ldots`:: >>> mp.dps = 15 >>> taylor(lambda q: 1728*q*kleinj(qbar=q), 0, 5, singular=True) [1.0, 744.0, 196884.0, 21493760.0, 864299970.0, 20245856256.0] The j-function admits exact evaluation at special algebraic points related to the Heegner numbers 1, 2, 3, 7, 11, 19, 43, 67, 163:: >>> @extraprec(10) ... def h(n): ... v = (1+sqrt(n)*j) ... if n > 2: ... v *= 0.5 ... return v ... >>> mp.dps = 25 >>> for n in [1,2,3,7,11,19,43,67,163]: ... n, chop(1728*kleinj(h(n))) ... (1, 1728.0) (2, 8000.0) (3, 0.0) (7, -3375.0) (11, -32768.0) (19, -884736.0) (43, -884736000.0) (67, -147197952000.0) (163, -262537412640768000.0) Also at other special points, the j-function assumes explicit algebraic values, e.g.:: >>> chop(1728*kleinj(j*sqrt(5))) 1264538.909475140509320227 >>> identify(cbrt(_)) # note: not simplified '((100+sqrt(13520))/2)' >>> (50+26*sqrt(5))**3 1264538.909475140509320227 """ q = ctx.qfrom(tau=tau, **kwargs) t2 = ctx.jtheta(2,0,q) t3 = ctx.jtheta(3,0,q) t4 = ctx.jtheta(4,0,q) P = (t2**8 + t3**8 + t4**8)**3 Q = 54*(t2*t3*t4)**8 return P/Q def RF_calc(ctx, x, y, z, r): if y == z: return RC_calc(ctx, x, y, r) if x == z: return RC_calc(ctx, y, x, r) if x == y: return RC_calc(ctx, z, x, r) if not (ctx.isnormal(x) and ctx.isnormal(y) and ctx.isnormal(z)): if ctx.isnan(x) or ctx.isnan(y) or ctx.isnan(z): return x*y*z if ctx.isinf(x) or ctx.isinf(y) or ctx.isinf(z): return ctx.zero xm,ym,zm = x,y,z A0 = Am = (x+y+z)/3 Q = ctx.root(3*r, -6) * max(abs(A0-x),abs(A0-y),abs(A0-z)) g = ctx.mpf(0.25) pow4 = ctx.one m = 0 while 1: xs = ctx.sqrt(xm) ys = ctx.sqrt(ym) zs = ctx.sqrt(zm) lm = xs*ys + xs*zs + ys*zs Am1 = (Am+lm)*g xm, ym, zm = (xm+lm)*g, (ym+lm)*g, (zm+lm)*g if pow4 * Q < abs(Am): break Am = Am1 m += 1 pow4 *= g t = pow4/Am X = (A0-x)*t Y = (A0-y)*t Z = -X-Y E2 = X*Y-Z**2 E3 = X*Y*Z return ctx.power(Am,-0.5) * (9240-924*E2+385*E2**2+660*E3-630*E2*E3)/9240 def RC_calc(ctx, x, y, r, pv=True): if not (ctx.isnormal(x) and ctx.isnormal(y)): if ctx.isinf(x) or ctx.isinf(y): return 1/(x*y) if y == 0: return ctx.inf if x == 0: return ctx.pi / ctx.sqrt(y) / 2 raise ValueError # Cauchy principal value if pv and ctx._im(y) == 0 and ctx._re(y) < 0: return ctx.sqrt(x/(x-y)) * RC_calc(ctx, x-y, -y, r) if x == y: return 1/ctx.sqrt(x) extraprec = 2*max(0,-ctx.mag(x-y)+ctx.mag(x)) ctx.prec += extraprec if ctx._is_real_type(x) and ctx._is_real_type(y): x = ctx._re(x) y = ctx._re(y) a = ctx.sqrt(x/y) if x < y: b = ctx.sqrt(y-x) v = ctx.acos(a)/b else: b = ctx.sqrt(x-y) v = ctx.acosh(a)/b else: sx = ctx.sqrt(x) sy = ctx.sqrt(y) v = ctx.acos(sx/sy)/(ctx.sqrt((1-x/y))*sy) ctx.prec -= extraprec return v def RJ_calc(ctx, x, y, z, p, r): if not (ctx.isnormal(x) and ctx.isnormal(y) and \ ctx.isnormal(z) and ctx.isnormal(p)): if ctx.isnan(x) or ctx.isnan(y) or ctx.isnan(z) or ctx.isnan(p): return x*y*z if ctx.isinf(x) or ctx.isinf(y) or ctx.isinf(z) or ctx.isinf(p): return ctx.zero if not p: return ctx.inf xm,ym,zm,pm = x,y,z,p A0 = Am = (x + y + z + 2*p)/5 delta = (p-x)*(p-y)*(p-z) Q = ctx.root(0.25*r, -6) * max(abs(A0-x),abs(A0-y),abs(A0-z),abs(A0-p)) m = 0 g = ctx.mpf(0.25) pow4 = ctx.one S = 0 while 1: sx = ctx.sqrt(xm) sy = ctx.sqrt(ym) sz = ctx.sqrt(zm) sp = ctx.sqrt(pm) lm = sx*sy + sx*sz + sy*sz Am1 = (Am+lm)*g xm = (xm+lm)*g; ym = (ym+lm)*g; zm = (zm+lm)*g; pm = (pm+lm)*g dm = (sp+sx) * (sp+sy) * (sp+sz) em = delta * ctx.power(4, -3*m) / dm**2 if pow4 * Q < abs(Am): break T = RC_calc(ctx, ctx.one, ctx.one+em, r) * pow4 / dm S += T pow4 *= g m += 1 Am = Am1 t = ctx.ldexp(1,-2*m) / Am X = (A0-x)*t Y = (A0-y)*t Z = (A0-z)*t P = (-X-Y-Z)/2 E2 = X*Y + X*Z + Y*Z - 3*P**2 E3 = X*Y*Z + 2*E2*P + 4*P**3 E4 = (2*X*Y*Z + E2*P + 3*P**3)*P E5 = X*Y*Z*P**2 P = 24024 - 5148*E2 + 2457*E2**2 + 4004*E3 - 4158*E2*E3 - 3276*E4 + 2772*E5 Q = 24024 v1 = g**m * ctx.power(Am, -1.5) * P/Q v2 = 6*S return v1 + v2 @defun def elliprf(ctx, x, y, z): r""" Evaluates the Carlson symmetric elliptic integral of the first kind .. math :: R_F(x,y,z) = \frac{1}{2} \int_0^{\infty} \frac{dt}{\sqrt{(t+x)(t+y)(t+z)}} which is defined for `x,y,z \notin (-\infty,0)`, and with at most one of `x,y,z` being zero. For real `x,y,z \ge 0`, the principal square root is taken in the integrand. For complex `x,y,z`, the principal square root is taken as `t \to \infty` and as `t \to 0` non-principal branches are chosen as necessary so as to make the integrand continuous. **Examples** Some basic values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> elliprf(0,1,1); pi/2 1.570796326794896619231322 1.570796326794896619231322 >>> elliprf(0,1,inf) 0.0 >>> elliprf(1,1,1) 1.0 >>> elliprf(2,2,2)**2 0.5 >>> elliprf(1,0,0); elliprf(0,0,1); elliprf(0,1,0); elliprf(0,0,0) +inf +inf +inf +inf Representing complete elliptic integrals in terms of `R_F`:: >>> m = mpf(0.75) >>> ellipk(m); elliprf(0,1-m,1) 2.156515647499643235438675 2.156515647499643235438675 >>> ellipe(m); elliprf(0,1-m,1)-m*elliprd(0,1-m,1)/3 1.211056027568459524803563 1.211056027568459524803563 Some symmetries and argument transformations:: >>> x,y,z = 2,3,4 >>> elliprf(x,y,z); elliprf(y,x,z); elliprf(z,y,x) 0.5840828416771517066928492 0.5840828416771517066928492 0.5840828416771517066928492 >>> k = mpf(100000) >>> elliprf(k*x,k*y,k*z); k**(-0.5) * elliprf(x,y,z) 0.001847032121923321253219284 0.001847032121923321253219284 >>> l = sqrt(x*y) + sqrt(y*z) + sqrt(z*x) >>> elliprf(x,y,z); 2*elliprf(x+l,y+l,z+l) 0.5840828416771517066928492 0.5840828416771517066928492 >>> elliprf((x+l)/4,(y+l)/4,(z+l)/4) 0.5840828416771517066928492 Comparing with numerical integration:: >>> x,y,z = 2,3,4 >>> elliprf(x,y,z) 0.5840828416771517066928492 >>> f = lambda t: 0.5*((t+x)*(t+y)*(t+z))**(-0.5) >>> q = extradps(25)(quad) >>> q(f, [0,inf]) 0.5840828416771517066928492 With the following arguments, the square root in the integrand becomes discontinuous at `t = 1/2` if the principal branch is used. To obtain the right value, `-\sqrt{r}` must be taken instead of `\sqrt{r}` on `t \in (0, 1/2)`:: >>> x,y,z = j-1,j,0 >>> elliprf(x,y,z) (0.7961258658423391329305694 - 1.213856669836495986430094j) >>> -q(f, [0,0.5]) + q(f, [0.5,inf]) (0.7961258658423391329305694 - 1.213856669836495986430094j) The so-called *first lemniscate constant*, a transcendental number:: >>> elliprf(0,1,2) 1.31102877714605990523242 >>> extradps(25)(quad)(lambda t: 1/sqrt(1-t**4), [0,1]) 1.31102877714605990523242 >>> gamma('1/4')**2/(4*sqrt(2*pi)) 1.31102877714605990523242 **References** 1. [Carlson]_ 2. [DLMF]_ Chapter 19. Elliptic Integrals """ x = ctx.convert(x) y = ctx.convert(y) z = ctx.convert(z) prec = ctx.prec try: ctx.prec += 20 tol = ctx.eps * 2**10 v = RF_calc(ctx, x, y, z, tol) finally: ctx.prec = prec return +v @defun def elliprc(ctx, x, y, pv=True): r""" Evaluates the degenerate Carlson symmetric elliptic integral of the first kind .. math :: R_C(x,y) = R_F(x,y,y) = \frac{1}{2} \int_0^{\infty} \frac{dt}{(t+y) \sqrt{(t+x)}}. If `y \in (-\infty,0)`, either a value defined by continuity, or with *pv=True* the Cauchy principal value, can be computed. If `x \ge 0, y > 0`, the value can be expressed in terms of elementary functions as .. math :: R_C(x,y) = \begin{cases} \dfrac{1}{\sqrt{y-x}} \cos^{-1}\left(\sqrt{\dfrac{x}{y}}\right), & x < y \\ \dfrac{1}{\sqrt{y}}, & x = y \\ \dfrac{1}{\sqrt{x-y}} \cosh^{-1}\left(\sqrt{\dfrac{x}{y}}\right), & x > y \\ \end{cases}. **Examples** Some special values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> elliprc(1,2)*4; elliprc(0,1)*2; +pi 3.141592653589793238462643 3.141592653589793238462643 3.141592653589793238462643 >>> elliprc(1,0) +inf >>> elliprc(5,5)**2 0.2 >>> elliprc(1,inf); elliprc(inf,1); elliprc(inf,inf) 0.0 0.0 0.0 Comparing with the elementary closed-form solution:: >>> elliprc('1/3', '1/5'); sqrt(7.5)*acosh(sqrt('5/3')) 2.041630778983498390751238 2.041630778983498390751238 >>> elliprc('1/5', '1/3'); sqrt(7.5)*acos(sqrt('3/5')) 1.875180765206547065111085 1.875180765206547065111085 Comparing with numerical integration:: >>> q = extradps(25)(quad) >>> elliprc(2, -3, pv=True) 0.3333969101113672670749334 >>> elliprc(2, -3, pv=False) (0.3333969101113672670749334 + 0.7024814731040726393156375j) >>> 0.5*q(lambda t: 1/(sqrt(t+2)*(t-3)), [0,3-j,6,inf]) (0.3333969101113672670749334 + 0.7024814731040726393156375j) """ x = ctx.convert(x) y = ctx.convert(y) prec = ctx.prec try: ctx.prec += 20 tol = ctx.eps * 2**10 v = RC_calc(ctx, x, y, tol, pv) finally: ctx.prec = prec return +v @defun def elliprj(ctx, x, y, z, p): r""" Evaluates the Carlson symmetric elliptic integral of the third kind .. math :: R_J(x,y,z,p) = \frac{3}{2} \int_0^{\infty} \frac{dt}{(t+p)\sqrt{(t+x)(t+y)(t+z)}}. Like :func:`~mpmath.elliprf`, the branch of the square root in the integrand is defined so as to be continuous along the path of integration for complex values of the arguments. **Examples** Some values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> elliprj(1,1,1,1) 1.0 >>> elliprj(2,2,2,2); 1/(2*sqrt(2)) 0.3535533905932737622004222 0.3535533905932737622004222 >>> elliprj(0,1,2,2) 1.067937989667395702268688 >>> 3*(2*gamma('5/4')**2-pi**2/gamma('1/4')**2)/(sqrt(2*pi)) 1.067937989667395702268688 >>> elliprj(0,1,1,2); 3*pi*(2-sqrt(2))/4 1.380226776765915172432054 1.380226776765915172432054 >>> elliprj(1,3,2,0); elliprj(0,1,1,0); elliprj(0,0,0,0) +inf +inf +inf >>> elliprj(1,inf,1,0); elliprj(1,1,1,inf) 0.0 0.0 >>> chop(elliprj(1+j, 1-j, 1, 1)) 0.8505007163686739432927844 Scale transformation:: >>> x,y,z,p = 2,3,4,5 >>> k = mpf(100000) >>> elliprj(k*x,k*y,k*z,k*p); k**(-1.5)*elliprj(x,y,z,p) 4.521291677592745527851168e-9 4.521291677592745527851168e-9 Comparing with numerical integration:: >>> elliprj(1,2,3,4) 0.2398480997495677621758617 >>> f = lambda t: 1/((t+4)*sqrt((t+1)*(t+2)*(t+3))) >>> 1.5*quad(f, [0,inf]) 0.2398480997495677621758617 >>> elliprj(1,2+1j,3,4-2j) (0.216888906014633498739952 + 0.04081912627366673332369512j) >>> f = lambda t: 1/((t+4-2j)*sqrt((t+1)*(t+2+1j)*(t+3))) >>> 1.5*quad(f, [0,inf]) (0.216888906014633498739952 + 0.04081912627366673332369511j) """ x = ctx.convert(x) y = ctx.convert(y) z = ctx.convert(z) p = ctx.convert(p) prec = ctx.prec try: ctx.prec += 20 tol = ctx.eps * 2**10 v = RJ_calc(ctx, x, y, z, p, tol) finally: ctx.prec = prec return +v @defun def elliprd(ctx, x, y, z): r""" Evaluates the degenerate Carlson symmetric elliptic integral of the third kind or Carlson elliptic integral of the second kind `R_D(x,y,z) = R_J(x,y,z,z)`. See :func:`~mpmath.elliprj` for additional information. **Examples** >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> elliprd(1,2,3) 0.2904602810289906442326534 >>> elliprj(1,2,3,3) 0.2904602810289906442326534 The so-called *second lemniscate constant*, a transcendental number:: >>> elliprd(0,2,1)/3 0.5990701173677961037199612 >>> extradps(25)(quad)(lambda t: t**2/sqrt(1-t**4), [0,1]) 0.5990701173677961037199612 >>> gamma('3/4')**2/sqrt(2*pi) 0.5990701173677961037199612 """ return ctx.elliprj(x,y,z,z) @defun def elliprg(ctx, x, y, z): r""" Evaluates the Carlson completely symmetric elliptic integral of the second kind .. math :: R_G(x,y,z) = \frac{1}{4} \int_0^{\infty} \frac{t}{\sqrt{(t+x)(t+y)(t+z)}} \left( \frac{x}{t+x} + \frac{y}{t+y} + \frac{z}{t+z}\right) dt. **Examples** Evaluation for real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> elliprg(0,1,1)*4; +pi 3.141592653589793238462643 3.141592653589793238462643 >>> elliprg(0,0.5,1) 0.6753219405238377512600874 >>> chop(elliprg(1+j, 1-j, 2)) 1.172431327676416604532822 A double integral that can be evaluated in terms of `R_G`:: >>> x,y,z = 2,3,4 >>> def f(t,u): ... st = fp.sin(t); ct = fp.cos(t) ... su = fp.sin(u); cu = fp.cos(u) ... return (x*(st*cu)**2 + y*(st*su)**2 + z*ct**2)**0.5 * st ... >>> nprint(mpf(fp.quad(f, [0,fp.pi], [0,2*fp.pi])/(4*fp.pi)), 13) 1.725503028069 >>> nprint(elliprg(x,y,z), 13) 1.725503028069 """ x = ctx.convert(x) y = ctx.convert(y) z = ctx.convert(z) zeros = (not x) + (not y) + (not z) if zeros == 3: return (x+y+z)*0 if zeros == 2: if x: return 0.5*ctx.sqrt(x) if y: return 0.5*ctx.sqrt(y) return 0.5*ctx.sqrt(z) if zeros == 1: if not z: x, z = z, x def terms(): T1 = 0.5*z*ctx.elliprf(x,y,z) T2 = -0.5*(x-z)*(y-z)*ctx.elliprd(x,y,z)/3 T3 = 0.5*ctx.sqrt(x)*ctx.sqrt(y)/ctx.sqrt(z) return T1,T2,T3 return ctx.sum_accurately(terms) @defun_wrapped def ellipf(ctx, phi, m): r""" Evaluates the Legendre incomplete elliptic integral of the first kind .. math :: F(\phi,m) = \int_0^{\phi} \frac{dt}{\sqrt{1-m \sin^2 t}} or equivalently .. math :: F(\phi,m) = \int_0^{\sin \phi} \frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)}. The function reduces to a complete elliptic integral of the first kind (see :func:`~mpmath.ellipk`) when `\phi = \frac{\pi}{2}`; that is, .. math :: F\left(\frac{\pi}{2}, m\right) = K(m). In the defining integral, it is assumed that the principal branch of the square root is taken and that the path of integration avoids crossing any branch cuts. Outside `-\pi/2 \le \Re(\phi) \le \pi/2`, the function extends quasi-periodically as .. math :: F(\phi + n \pi, m) = 2 n K(m) + F(\phi,m), n \in \mathbb{Z}. **Plots** .. literalinclude :: /plots/ellipf.py .. image :: /plots/ellipf.png **Examples** Basic values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> ellipf(0,1) 0.0 >>> ellipf(0,0) 0.0 >>> ellipf(1,0); ellipf(2+3j,0) 1.0 (2.0 + 3.0j) >>> ellipf(1,1); log(sec(1)+tan(1)) 1.226191170883517070813061 1.226191170883517070813061 >>> ellipf(pi/2, -0.5); ellipk(-0.5) 1.415737208425956198892166 1.415737208425956198892166 >>> ellipf(pi/2+eps, 1); ellipf(-pi/2-eps, 1) +inf +inf >>> ellipf(1.5, 1) 3.340677542798311003320813 Comparing with numerical integration:: >>> z,m = 0.5, 1.25 >>> ellipf(z,m) 0.5287219202206327872978255 >>> quad(lambda t: (1-m*sin(t)**2)**(-0.5), [0,z]) 0.5287219202206327872978255 The arguments may be complex numbers:: >>> ellipf(3j, 0.5) (0.0 + 1.713602407841590234804143j) >>> ellipf(3+4j, 5-6j) (1.269131241950351323305741 - 0.3561052815014558335412538j) >>> z,m = 2+3j, 1.25 >>> k = 1011 >>> ellipf(z+pi*k,m); ellipf(z,m) + 2*k*ellipk(m) (4086.184383622179764082821 - 3003.003538923749396546871j) (4086.184383622179764082821 - 3003.003538923749396546871j) For `|\Re(z)| < \pi/2`, the function can be expressed as a hypergeometric series of two variables (see :func:`~mpmath.appellf1`):: >>> z,m = 0.5, 0.25 >>> ellipf(z,m) 0.5050887275786480788831083 >>> sin(z)*appellf1(0.5,0.5,0.5,1.5,sin(z)**2,m*sin(z)**2) 0.5050887275786480788831083 """ z = phi if not (ctx.isnormal(z) and ctx.isnormal(m)): if m == 0: return z + m if z == 0: return z * m if m == ctx.inf or m == ctx.ninf: return z/m raise ValueError x = z.real ctx.prec += max(0, ctx.mag(x)) pi = +ctx.pi away = abs(x) > pi/2 if m == 1: if away: return ctx.inf if away: d = ctx.nint(x/pi) z = z-pi*d P = 2*d*ctx.ellipk(m) else: P = 0 c, s = ctx.cos_sin(z) return s * ctx.elliprf(c**2, 1-m*s**2, 1) + P @defun_wrapped def ellipe(ctx, *args): r""" Called with a single argument `m`, evaluates the Legendre complete elliptic integral of the second kind, `E(m)`, defined by .. math :: E(m) = \int_0^{\pi/2} \sqrt{1-m \sin^2 t} \, dt \,=\, \frac{\pi}{2} \,_2F_1\left(\frac{1}{2}, -\frac{1}{2}, 1, m\right). Called with two arguments `\phi, m`, evaluates the incomplete elliptic integral of the second kind .. math :: E(\phi,m) = \int_0^{\phi} \sqrt{1-m \sin^2 t} \, dt = \int_0^{\sin z} \frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt. The incomplete integral reduces to a complete integral when `\phi = \frac{\pi}{2}`; that is, .. math :: E\left(\frac{\pi}{2}, m\right) = E(m). In the defining integral, it is assumed that the principal branch of the square root is taken and that the path of integration avoids crossing any branch cuts. Outside `-\pi/2 \le \Re(z) \le \pi/2`, the function extends quasi-periodically as .. math :: E(\phi + n \pi, m) = 2 n E(m) + E(\phi,m), n \in \mathbb{Z}. **Plots** .. literalinclude :: /plots/ellipe.py .. image :: /plots/ellipe.png **Examples for the complete integral** Basic values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> ellipe(0) 1.570796326794896619231322 >>> ellipe(1) 1.0 >>> ellipe(-1) 1.910098894513856008952381 >>> ellipe(2) (0.5990701173677961037199612 + 0.5990701173677961037199612j) >>> ellipe(inf) (0.0 + +infj) >>> ellipe(-inf) +inf Verifying the defining integral and hypergeometric representation:: >>> ellipe(0.5) 1.350643881047675502520175 >>> quad(lambda t: sqrt(1-0.5*sin(t)**2), [0, pi/2]) 1.350643881047675502520175 >>> pi/2*hyp2f1(0.5,-0.5,1,0.5) 1.350643881047675502520175 Evaluation is supported for arbitrary complex `m`:: >>> ellipe(0.5+0.25j) (1.360868682163129682716687 - 0.1238733442561786843557315j) >>> ellipe(3+4j) (1.499553520933346954333612 - 1.577879007912758274533309j) A definite integral:: >>> quad(ellipe, [0,1]) 1.333333333333333333333333 **Examples for the incomplete integral** Basic values and limits:: >>> ellipe(0,1) 0.0 >>> ellipe(0,0) 0.0 >>> ellipe(1,0) 1.0 >>> ellipe(2+3j,0) (2.0 + 3.0j) >>> ellipe(1,1); sin(1) 0.8414709848078965066525023 0.8414709848078965066525023 >>> ellipe(pi/2, -0.5); ellipe(-0.5) 1.751771275694817862026502 1.751771275694817862026502 >>> ellipe(pi/2, 1); ellipe(-pi/2, 1) 1.0 -1.0 >>> ellipe(1.5, 1) 0.9974949866040544309417234 Comparing with numerical integration:: >>> z,m = 0.5, 1.25 >>> ellipe(z,m) 0.4740152182652628394264449 >>> quad(lambda t: sqrt(1-m*sin(t)**2), [0,z]) 0.4740152182652628394264449 The arguments may be complex numbers:: >>> ellipe(3j, 0.5) (0.0 + 7.551991234890371873502105j) >>> ellipe(3+4j, 5-6j) (24.15299022574220502424466 + 75.2503670480325997418156j) >>> k = 35 >>> z,m = 2+3j, 1.25 >>> ellipe(z+pi*k,m); ellipe(z,m) + 2*k*ellipe(m) (48.30138799412005235090766 + 17.47255216721987688224357j) (48.30138799412005235090766 + 17.47255216721987688224357j) For `|\Re(z)| < \pi/2`, the function can be expressed as a hypergeometric series of two variables (see :func:`~mpmath.appellf1`):: >>> z,m = 0.5, 0.25 >>> ellipe(z,m) 0.4950017030164151928870375 >>> sin(z)*appellf1(0.5,0.5,-0.5,1.5,sin(z)**2,m*sin(z)**2) 0.4950017030164151928870376 """ if len(args) == 1: return ctx._ellipe(args[0]) else: phi, m = args z = phi if not (ctx.isnormal(z) and ctx.isnormal(m)): if m == 0: return z + m if z == 0: return z * m if m == ctx.inf or m == ctx.ninf: return ctx.inf raise ValueError x = z.real ctx.prec += max(0, ctx.mag(x)) pi = +ctx.pi away = abs(x) > pi/2 if away: d = ctx.nint(x/pi) z = z-pi*d P = 2*d*ctx.ellipe(m) else: P = 0 def terms(): c, s = ctx.cos_sin(z) x = c**2 y = 1-m*s**2 RF = ctx.elliprf(x, y, 1) RD = ctx.elliprd(x, y, 1) return s*RF, -m*s**3*RD/3 return ctx.sum_accurately(terms) + P @defun_wrapped def ellippi(ctx, *args): r""" Called with three arguments `n, \phi, m`, evaluates the Legendre incomplete elliptic integral of the third kind .. math :: \Pi(n; \phi, m) = \int_0^{\phi} \frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} = \int_0^{\sin \phi} \frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}}. Called with two arguments `n, m`, evaluates the complete elliptic integral of the third kind `\Pi(n,m) = \Pi(n; \frac{\pi}{2},m)`. In the defining integral, it is assumed that the principal branch of the square root is taken and that the path of integration avoids crossing any branch cuts. Outside `-\pi/2 \le \Re(\phi) \le \pi/2`, the function extends quasi-periodically as .. math :: \Pi(n,\phi+k\pi,m) = 2k\Pi(n,m) + \Pi(n,\phi,m), k \in \mathbb{Z}. **Plots** .. literalinclude :: /plots/ellippi.py .. image :: /plots/ellippi.png **Examples for the complete integral** Some basic values and limits:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> ellippi(0,-5); ellipk(-5) 0.9555039270640439337379334 0.9555039270640439337379334 >>> ellippi(inf,2) 0.0 >>> ellippi(2,inf) 0.0 >>> abs(ellippi(1,5)) +inf >>> abs(ellippi(0.25,1)) +inf Evaluation in terms of simpler functions:: >>> ellippi(0.25,0.25); ellipe(0.25)/(1-0.25) 1.956616279119236207279727 1.956616279119236207279727 >>> ellippi(3,0); pi/(2*sqrt(-2)) (0.0 - 1.11072073453959156175397j) (0.0 - 1.11072073453959156175397j) >>> ellippi(-3,0); pi/(2*sqrt(4)) 0.7853981633974483096156609 0.7853981633974483096156609 **Examples for the incomplete integral** Basic values and limits:: >>> ellippi(0.25,-0.5); ellippi(0.25,pi/2,-0.5) 1.622944760954741603710555 1.622944760954741603710555 >>> ellippi(1,0,1) 0.0 >>> ellippi(inf,0,1) 0.0 >>> ellippi(0,0.25,0.5); ellipf(0.25,0.5) 0.2513040086544925794134591 0.2513040086544925794134591 >>> ellippi(1,1,1); (log(sec(1)+tan(1))+sec(1)*tan(1))/2 2.054332933256248668692452 2.054332933256248668692452 >>> ellippi(0.25, 53*pi/2, 0.75); 53*ellippi(0.25,0.75) 135.240868757890840755058 135.240868757890840755058 >>> ellippi(0.5,pi/4,0.5); 2*ellipe(pi/4,0.5)-1/sqrt(3) 0.9190227391656969903987269 0.9190227391656969903987269 Complex arguments are supported:: >>> ellippi(0.5, 5+6j-2*pi, -7-8j) (-0.3612856620076747660410167 + 0.5217735339984807829755815j) Some degenerate cases:: >>> ellippi(1,1) +inf >>> ellippi(1,0) +inf >>> ellippi(1,2,0) +inf >>> ellippi(1,2,1) +inf >>> ellippi(1,0,1) 0.0 """ if len(args) == 2: n, m = args complete = True z = phi = ctx.pi/2 else: n, phi, m = args complete = False z = phi if not (ctx.isnormal(n) and ctx.isnormal(z) and ctx.isnormal(m)): if ctx.isnan(n) or ctx.isnan(z) or ctx.isnan(m): raise ValueError if complete: if m == 0: if n == 1: return ctx.inf return ctx.pi/(2*ctx.sqrt(1-n)) if n == 0: return ctx.ellipk(m) if ctx.isinf(n) or ctx.isinf(m): return ctx.zero else: if z == 0: return z if ctx.isinf(n): return ctx.zero if ctx.isinf(m): return ctx.zero if ctx.isinf(n) or ctx.isinf(z) or ctx.isinf(m): raise ValueError if complete: if m == 1: if n == 1: return ctx.inf return -ctx.inf/ctx.sign(n-1) away = False else: x = z.real ctx.prec += max(0, ctx.mag(x)) pi = +ctx.pi away = abs(x) > pi/2 if away: d = ctx.nint(x/pi) z = z-pi*d P = 2*d*ctx.ellippi(n,m) if ctx.isinf(P): return ctx.inf else: P = 0 def terms(): if complete: c, s = ctx.zero, ctx.one else: c, s = ctx.cos_sin(z) x = c**2 y = 1-m*s**2 RF = ctx.elliprf(x, y, 1) RJ = ctx.elliprj(x, y, 1, 1-n*s**2) return s*RF, n*s**3*RJ/3 return ctx.sum_accurately(terms) + P mpmath-1.1.0/mpmath/functions/expintegrals.py000066400000000000000000000265741340375245600214030ustar00rootroot00000000000000from .functions import defun, defun_wrapped @defun_wrapped def _erf_complex(ctx, z): z2 = ctx.square_exp_arg(z, -1) #z2 = -z**2 v = (2/ctx.sqrt(ctx.pi))*z * ctx.hyp1f1((1,2),(3,2), z2) if not ctx._re(z): v = ctx._im(v)*ctx.j return v @defun_wrapped def _erfc_complex(ctx, z): if ctx.re(z) > 2: z2 = ctx.square_exp_arg(z) nz2 = ctx.fneg(z2, exact=True) v = ctx.exp(nz2)/ctx.sqrt(ctx.pi) * ctx.hyperu((1,2),(1,2), z2) else: v = 1 - ctx._erf_complex(z) if not ctx._re(z): v = 1+ctx._im(v)*ctx.j return v @defun def erf(ctx, z): z = ctx.convert(z) if ctx._is_real_type(z): try: return ctx._erf(z) except NotImplementedError: pass if ctx._is_complex_type(z) and not z.imag: try: return type(z)(ctx._erf(z.real)) except NotImplementedError: pass return ctx._erf_complex(z) @defun def erfc(ctx, z): z = ctx.convert(z) if ctx._is_real_type(z): try: return ctx._erfc(z) except NotImplementedError: pass if ctx._is_complex_type(z) and not z.imag: try: return type(z)(ctx._erfc(z.real)) except NotImplementedError: pass return ctx._erfc_complex(z) @defun def square_exp_arg(ctx, z, mult=1, reciprocal=False): prec = ctx.prec*4+20 if reciprocal: z2 = ctx.fmul(z, z, prec=prec) z2 = ctx.fdiv(ctx.one, z2, prec=prec) else: z2 = ctx.fmul(z, z, prec=prec) if mult != 1: z2 = ctx.fmul(z2, mult, exact=True) return z2 @defun_wrapped def erfi(ctx, z): if not z: return z z2 = ctx.square_exp_arg(z) v = (2/ctx.sqrt(ctx.pi)*z) * ctx.hyp1f1((1,2), (3,2), z2) if not ctx._re(z): v = ctx._im(v)*ctx.j return v @defun_wrapped def erfinv(ctx, x): xre = ctx._re(x) if (xre != x) or (xre < -1) or (xre > 1): return ctx.bad_domain("erfinv(x) is defined only for -1 <= x <= 1") x = xre #if ctx.isnan(x): return x if not x: return x if x == 1: return ctx.inf if x == -1: return ctx.ninf if abs(x) < 0.9: a = 0.53728*x**3 + 0.813198*x else: # An asymptotic formula u = ctx.ln(2/ctx.pi/(abs(x)-1)**2) a = ctx.sign(x) * ctx.sqrt(u - ctx.ln(u))/ctx.sqrt(2) ctx.prec += 10 return ctx.findroot(lambda t: ctx.erf(t)-x, a) @defun_wrapped def npdf(ctx, x, mu=0, sigma=1): sigma = ctx.convert(sigma) return ctx.exp(-(x-mu)**2/(2*sigma**2)) / (sigma*ctx.sqrt(2*ctx.pi)) @defun_wrapped def ncdf(ctx, x, mu=0, sigma=1): a = (x-mu)/(sigma*ctx.sqrt(2)) if a < 0: return ctx.erfc(-a)/2 else: return (1+ctx.erf(a))/2 @defun_wrapped def betainc(ctx, a, b, x1=0, x2=1, regularized=False): if x1 == x2: v = 0 elif not x1: if x1 == 0 and x2 == 1: v = ctx.beta(a, b) else: v = x2**a * ctx.hyp2f1(a, 1-b, a+1, x2) / a else: m, d = ctx.nint_distance(a) if m <= 0: if d < -ctx.prec: h = +ctx.eps ctx.prec *= 2 a += h elif d < -4: ctx.prec -= d s1 = x2**a * ctx.hyp2f1(a,1-b,a+1,x2) s2 = x1**a * ctx.hyp2f1(a,1-b,a+1,x1) v = (s1 - s2) / a if regularized: v /= ctx.beta(a,b) return v @defun def gammainc(ctx, z, a=0, b=None, regularized=False): regularized = bool(regularized) z = ctx.convert(z) if a is None: a = ctx.zero lower_modified = False else: a = ctx.convert(a) lower_modified = a != ctx.zero if b is None: b = ctx.inf upper_modified = False else: b = ctx.convert(b) upper_modified = b != ctx.inf # Complete gamma function if not (upper_modified or lower_modified): if regularized: if ctx.re(z) < 0: return ctx.inf elif ctx.re(z) > 0: return ctx.one else: return ctx.nan return ctx.gamma(z) if a == b: return ctx.zero # Standardize if ctx.re(a) > ctx.re(b): return -ctx.gammainc(z, b, a, regularized) # Generalized gamma if upper_modified and lower_modified: return +ctx._gamma3(z, a, b, regularized) # Upper gamma elif lower_modified: return ctx._upper_gamma(z, a, regularized) # Lower gamma elif upper_modified: return ctx._lower_gamma(z, b, regularized) @defun def _lower_gamma(ctx, z, b, regularized=False): # Pole if ctx.isnpint(z): return type(z)(ctx.inf) G = [z] * regularized negb = ctx.fneg(b, exact=True) def h(z): T1 = [ctx.exp(negb), b, z], [1, z, -1], [], G, [1], [1+z], b return (T1,) return ctx.hypercomb(h, [z]) @defun def _upper_gamma(ctx, z, a, regularized=False): # Fast integer case, when available if ctx.isint(z): try: if regularized: # Gamma pole if ctx.isnpint(z): return type(z)(ctx.zero) orig = ctx.prec try: ctx.prec += 10 return ctx._gamma_upper_int(z, a) / ctx.gamma(z) finally: ctx.prec = orig else: return ctx._gamma_upper_int(z, a) except NotImplementedError: pass # hypercomb is unable to detect the exact zeros, so handle them here if z == 2 and a == -1: return (z+a)*0 if z == 3 and (a == -1-1j or a == -1+1j): return (z+a)*0 nega = ctx.fneg(a, exact=True) G = [z] * regularized # Use 2F0 series when possible; fall back to lower gamma representation try: def h(z): r = z-1 return [([ctx.exp(nega), a], [1, r], [], G, [1, -r], [], 1/nega)] return ctx.hypercomb(h, [z], force_series=True) except ctx.NoConvergence: def h(z): T1 = [], [1, z-1], [z], G, [], [], 0 T2 = [-ctx.exp(nega), a, z], [1, z, -1], [], G, [1], [1+z], a return T1, T2 return ctx.hypercomb(h, [z]) @defun def _gamma3(ctx, z, a, b, regularized=False): pole = ctx.isnpint(z) if regularized and pole: return ctx.zero try: ctx.prec += 15 # We don't know in advance whether it's better to write as a difference # of lower or upper gamma functions, so try both T1 = ctx.gammainc(z, a, regularized=regularized) T2 = ctx.gammainc(z, b, regularized=regularized) R = T1 - T2 if ctx.mag(R) - max(ctx.mag(T1), ctx.mag(T2)) > -10: return R if not pole: T1 = ctx.gammainc(z, 0, b, regularized=regularized) T2 = ctx.gammainc(z, 0, a, regularized=regularized) R = T1 - T2 # May be ok, but should probably at least print a warning # about possible cancellation if 1: #ctx.mag(R) - max(ctx.mag(T1), ctx.mag(T2)) > -10: return R finally: ctx.prec -= 15 raise NotImplementedError @defun_wrapped def expint(ctx, n, z): if ctx.isint(n) and ctx._is_real_type(z): try: return ctx._expint_int(n, z) except NotImplementedError: pass if ctx.isnan(n) or ctx.isnan(z): return z*n if z == ctx.inf: return 1/z if z == 0: # integral from 1 to infinity of t^n if ctx.re(n) <= 1: # TODO: reasonable sign of infinity return type(z)(ctx.inf) else: return ctx.one/(n-1) if n == 0: return ctx.exp(-z)/z if n == -1: return ctx.exp(-z)*(z+1)/z**2 return z**(n-1) * ctx.gammainc(1-n, z) @defun_wrapped def li(ctx, z, offset=False): if offset: if z == 2: return ctx.zero return ctx.ei(ctx.ln(z)) - ctx.ei(ctx.ln2) if not z: return z if z == 1: return ctx.ninf return ctx.ei(ctx.ln(z)) @defun def ei(ctx, z): try: return ctx._ei(z) except NotImplementedError: return ctx._ei_generic(z) @defun_wrapped def _ei_generic(ctx, z): # Note: the following is currently untested because mp and fp # both use special-case ei code if z == ctx.inf: return z if z == ctx.ninf: return ctx.zero if ctx.mag(z) > 1: try: r = ctx.one/z v = ctx.exp(z)*ctx.hyper([1,1],[],r, maxterms=ctx.prec, force_series=True)/z im = ctx._im(z) if im > 0: v += ctx.pi*ctx.j if im < 0: v -= ctx.pi*ctx.j return v except ctx.NoConvergence: pass v = z*ctx.hyp2f2(1,1,2,2,z) + ctx.euler if ctx._im(z): v += 0.5*(ctx.log(z) - ctx.log(ctx.one/z)) else: v += ctx.log(abs(z)) return v @defun def e1(ctx, z): try: return ctx._e1(z) except NotImplementedError: return ctx.expint(1, z) @defun def ci(ctx, z): try: return ctx._ci(z) except NotImplementedError: return ctx._ci_generic(z) @defun_wrapped def _ci_generic(ctx, z): if ctx.isinf(z): if z == ctx.inf: return ctx.zero if z == ctx.ninf: return ctx.pi*1j jz = ctx.fmul(ctx.j,z,exact=True) njz = ctx.fneg(jz,exact=True) v = 0.5*(ctx.ei(jz) + ctx.ei(njz)) zreal = ctx._re(z) zimag = ctx._im(z) if zreal == 0: if zimag > 0: v += ctx.pi*0.5j if zimag < 0: v -= ctx.pi*0.5j if zreal < 0: if zimag >= 0: v += ctx.pi*1j if zimag < 0: v -= ctx.pi*1j if ctx._is_real_type(z) and zreal > 0: v = ctx._re(v) return v @defun def si(ctx, z): try: return ctx._si(z) except NotImplementedError: return ctx._si_generic(z) @defun_wrapped def _si_generic(ctx, z): if ctx.isinf(z): if z == ctx.inf: return 0.5*ctx.pi if z == ctx.ninf: return -0.5*ctx.pi # Suffers from cancellation near 0 if ctx.mag(z) >= -1: jz = ctx.fmul(ctx.j,z,exact=True) njz = ctx.fneg(jz,exact=True) v = (-0.5j)*(ctx.ei(jz) - ctx.ei(njz)) zreal = ctx._re(z) if zreal > 0: v -= 0.5*ctx.pi if zreal < 0: v += 0.5*ctx.pi if ctx._is_real_type(z): v = ctx._re(v) return v else: return z*ctx.hyp1f2((1,2),(3,2),(3,2),-0.25*z*z) @defun_wrapped def chi(ctx, z): nz = ctx.fneg(z, exact=True) v = 0.5*(ctx.ei(z) + ctx.ei(nz)) zreal = ctx._re(z) zimag = ctx._im(z) if zimag > 0: v += ctx.pi*0.5j elif zimag < 0: v -= ctx.pi*0.5j elif zreal < 0: v += ctx.pi*1j return v @defun_wrapped def shi(ctx, z): # Suffers from cancellation near 0 if ctx.mag(z) >= -1: nz = ctx.fneg(z, exact=True) v = 0.5*(ctx.ei(z) - ctx.ei(nz)) zimag = ctx._im(z) if zimag > 0: v -= 0.5j*ctx.pi if zimag < 0: v += 0.5j*ctx.pi return v else: return z * ctx.hyp1f2((1,2),(3,2),(3,2),0.25*z*z) @defun_wrapped def fresnels(ctx, z): if z == ctx.inf: return ctx.mpf(0.5) if z == ctx.ninf: return ctx.mpf(-0.5) return ctx.pi*z**3/6*ctx.hyp1f2((3,4),(3,2),(7,4),-ctx.pi**2*z**4/16) @defun_wrapped def fresnelc(ctx, z): if z == ctx.inf: return ctx.mpf(0.5) if z == ctx.ninf: return ctx.mpf(-0.5) return z*ctx.hyp1f2((1,4),(1,2),(5,4),-ctx.pi**2*z**4/16) mpmath-1.1.0/mpmath/functions/factorials.py000066400000000000000000000131231340375245600210070ustar00rootroot00000000000000from ..libmp.backend import xrange from .functions import defun, defun_wrapped @defun def gammaprod(ctx, a, b, _infsign=False): a = [ctx.convert(x) for x in a] b = [ctx.convert(x) for x in b] poles_num = [] poles_den = [] regular_num = [] regular_den = [] for x in a: [regular_num, poles_num][ctx.isnpint(x)].append(x) for x in b: [regular_den, poles_den][ctx.isnpint(x)].append(x) # One more pole in numerator or denominator gives 0 or inf if len(poles_num) < len(poles_den): return ctx.zero if len(poles_num) > len(poles_den): # Get correct sign of infinity for x+h, h -> 0 from above # XXX: hack, this should be done properly if _infsign: a = [x and x*(1+ctx.eps) or x+ctx.eps for x in poles_num] b = [x and x*(1+ctx.eps) or x+ctx.eps for x in poles_den] return ctx.sign(ctx.gammaprod(a+regular_num,b+regular_den)) * ctx.inf else: return ctx.inf # All poles cancel # lim G(i)/G(j) = (-1)**(i+j) * gamma(1-j) / gamma(1-i) p = ctx.one orig = ctx.prec try: ctx.prec = orig + 15 while poles_num: i = poles_num.pop() j = poles_den.pop() p *= (-1)**(i+j) * ctx.gamma(1-j) / ctx.gamma(1-i) for x in regular_num: p *= ctx.gamma(x) for x in regular_den: p /= ctx.gamma(x) finally: ctx.prec = orig return +p @defun def beta(ctx, x, y): x = ctx.convert(x) y = ctx.convert(y) if ctx.isinf(y): x, y = y, x if ctx.isinf(x): if x == ctx.inf and not ctx._im(y): if y == ctx.ninf: return ctx.nan if y > 0: return ctx.zero if ctx.isint(y): return ctx.nan if y < 0: return ctx.sign(ctx.gamma(y)) * ctx.inf return ctx.nan xy = ctx.fadd(x, y, prec=2*ctx.prec) return ctx.gammaprod([x, y], [xy]) @defun def binomial(ctx, n, k): n1 = ctx.fadd(n, 1, prec=2*ctx.prec) k1 = ctx.fadd(k, 1, prec=2*ctx.prec) nk1 = ctx.fsub(n1, k, prec=2*ctx.prec) return ctx.gammaprod([n1], [k1, nk1]) @defun def rf(ctx, x, n): xn = ctx.fadd(x, n, prec=2*ctx.prec) return ctx.gammaprod([xn], [x]) @defun def ff(ctx, x, n): x1 = ctx.fadd(x, 1, prec=2*ctx.prec) xn1 = ctx.fadd(ctx.fsub(x, n, prec=2*ctx.prec), 1, prec=2*ctx.prec) return ctx.gammaprod([x1], [xn1]) @defun_wrapped def fac2(ctx, x): if ctx.isinf(x): if x == ctx.inf: return x return ctx.nan return 2**(x/2)*(ctx.pi/2)**((ctx.cospi(x)-1)/4)*ctx.gamma(x/2+1) @defun_wrapped def barnesg(ctx, z): if ctx.isinf(z): if z == ctx.inf: return z return ctx.nan if ctx.isnan(z): return z if (not ctx._im(z)) and ctx._re(z) <= 0 and ctx.isint(ctx._re(z)): return z*0 # Account for size (would not be needed if computing log(G)) if abs(z) > 5: ctx.dps += 2*ctx.log(abs(z),2) # Reflection formula if ctx.re(z) < -ctx.dps: w = 1-z pi2 = 2*ctx.pi u = ctx.expjpi(2*w) v = ctx.j*ctx.pi/12 - ctx.j*ctx.pi*w**2/2 + w*ctx.ln(1-u) - \ ctx.j*ctx.polylog(2, u)/pi2 v = ctx.barnesg(2-z)*ctx.exp(v)/pi2**w if ctx._is_real_type(z): v = ctx._re(v) return v # Estimate terms for asymptotic expansion # TODO: fixme, obviously N = ctx.dps // 2 + 5 G = 1 while abs(z) < N or ctx.re(z) < 1: G /= ctx.gamma(z) z += 1 z -= 1 s = ctx.mpf(1)/12 s -= ctx.log(ctx.glaisher) s += z*ctx.log(2*ctx.pi)/2 s += (z**2/2-ctx.mpf(1)/12)*ctx.log(z) s -= 3*z**2/4 z2k = z2 = z**2 for k in xrange(1, N+1): t = ctx.bernoulli(2*k+2) / (4*k*(k+1)*z2k) if abs(t) < ctx.eps: #print k, N # check how many terms were needed break z2k *= z2 s += t #if k == N: # print "warning: series for barnesg failed to converge", ctx.dps return G*ctx.exp(s) @defun def superfac(ctx, z): return ctx.barnesg(z+2) @defun_wrapped def hyperfac(ctx, z): # XXX: estimate needed extra bits accurately if z == ctx.inf: return z if abs(z) > 5: extra = 4*int(ctx.log(abs(z),2)) else: extra = 0 ctx.prec += extra if not ctx._im(z) and ctx._re(z) < 0 and ctx.isint(ctx._re(z)): n = int(ctx.re(z)) h = ctx.hyperfac(-n-1) if ((n+1)//2) & 1: h = -h if ctx._is_complex_type(z): return h + 0j return h zp1 = z+1 # Wrong branch cut #v = ctx.gamma(zp1)**z #ctx.prec -= extra #return v / ctx.barnesg(zp1) v = ctx.exp(z*ctx.loggamma(zp1)) ctx.prec -= extra return v / ctx.barnesg(zp1) @defun_wrapped def loggamma_old(ctx, z): a = ctx._re(z) b = ctx._im(z) if not b and a > 0: return ctx.ln(ctx.gamma_old(z)) u = ctx.arg(z) w = ctx.ln(ctx.gamma_old(z)) if b: gi = -b - u/2 + a*u + b*ctx.ln(abs(z)) n = ctx.floor((gi-ctx._im(w))/(2*ctx.pi)+0.5) * (2*ctx.pi) return w + n*ctx.j elif a < 0: n = int(ctx.floor(a)) w += (n-(n%2))*ctx.pi*ctx.j return w ''' @defun def psi0(ctx, z): """Shortcut for psi(0,z) (the digamma function)""" return ctx.psi(0, z) @defun def psi1(ctx, z): """Shortcut for psi(1,z) (the trigamma function)""" return ctx.psi(1, z) @defun def psi2(ctx, z): """Shortcut for psi(2,z) (the tetragamma function)""" return ctx.psi(2, z) @defun def psi3(ctx, z): """Shortcut for psi(3,z) (the pentagamma function)""" return ctx.psi(3, z) ''' mpmath-1.1.0/mpmath/functions/functions.py000066400000000000000000000432151340375245600206750ustar00rootroot00000000000000from ..libmp.backend import xrange class SpecialFunctions(object): """ This class implements special functions using high-level code. Elementary and some other functions (e.g. gamma function, basecase hypergeometric series) are assumed to be predefined by the context as "builtins" or "low-level" functions. """ defined_functions = {} # The series for the Jacobi theta functions converge for |q| < 1; # in the current implementation they throw a ValueError for # abs(q) > THETA_Q_LIM THETA_Q_LIM = 1 - 10**-7 def __init__(self): cls = self.__class__ for name in cls.defined_functions: f, wrap = cls.defined_functions[name] cls._wrap_specfun(name, f, wrap) self.mpq_1 = self._mpq((1,1)) self.mpq_0 = self._mpq((0,1)) self.mpq_1_2 = self._mpq((1,2)) self.mpq_3_2 = self._mpq((3,2)) self.mpq_1_4 = self._mpq((1,4)) self.mpq_1_16 = self._mpq((1,16)) self.mpq_3_16 = self._mpq((3,16)) self.mpq_5_2 = self._mpq((5,2)) self.mpq_3_4 = self._mpq((3,4)) self.mpq_7_4 = self._mpq((7,4)) self.mpq_5_4 = self._mpq((5,4)) self.mpq_1_3 = self._mpq((1,3)) self.mpq_2_3 = self._mpq((2,3)) self.mpq_4_3 = self._mpq((4,3)) self.mpq_1_6 = self._mpq((1,6)) self.mpq_5_6 = self._mpq((5,6)) self.mpq_5_3 = self._mpq((5,3)) self._misc_const_cache = {} self._aliases.update({ 'phase' : 'arg', 'conjugate' : 'conj', 'nthroot' : 'root', 'polygamma' : 'psi', 'hurwitz' : 'zeta', #'digamma' : 'psi0', #'trigamma' : 'psi1', #'tetragamma' : 'psi2', #'pentagamma' : 'psi3', 'fibonacci' : 'fib', 'factorial' : 'fac', }) self.zetazero_memoized = self.memoize(self.zetazero) # Default -- do nothing @classmethod def _wrap_specfun(cls, name, f, wrap): setattr(cls, name, f) # Optional fast versions of common functions in common cases. # If not overridden, default (generic hypergeometric series) # implementations will be used def _besselj(ctx, n, z): raise NotImplementedError def _erf(ctx, z): raise NotImplementedError def _erfc(ctx, z): raise NotImplementedError def _gamma_upper_int(ctx, z, a): raise NotImplementedError def _expint_int(ctx, n, z): raise NotImplementedError def _zeta(ctx, s): raise NotImplementedError def _zetasum_fast(ctx, s, a, n, derivatives, reflect): raise NotImplementedError def _ei(ctx, z): raise NotImplementedError def _e1(ctx, z): raise NotImplementedError def _ci(ctx, z): raise NotImplementedError def _si(ctx, z): raise NotImplementedError def _altzeta(ctx, s): raise NotImplementedError def defun_wrapped(f): SpecialFunctions.defined_functions[f.__name__] = f, True def defun(f): SpecialFunctions.defined_functions[f.__name__] = f, False def defun_static(f): setattr(SpecialFunctions, f.__name__, f) @defun_wrapped def cot(ctx, z): return ctx.one / ctx.tan(z) @defun_wrapped def sec(ctx, z): return ctx.one / ctx.cos(z) @defun_wrapped def csc(ctx, z): return ctx.one / ctx.sin(z) @defun_wrapped def coth(ctx, z): return ctx.one / ctx.tanh(z) @defun_wrapped def sech(ctx, z): return ctx.one / ctx.cosh(z) @defun_wrapped def csch(ctx, z): return ctx.one / ctx.sinh(z) @defun_wrapped def acot(ctx, z): if not z: return ctx.pi * 0.5 else: return ctx.atan(ctx.one / z) @defun_wrapped def asec(ctx, z): return ctx.acos(ctx.one / z) @defun_wrapped def acsc(ctx, z): return ctx.asin(ctx.one / z) @defun_wrapped def acoth(ctx, z): if not z: return ctx.pi * 0.5j else: return ctx.atanh(ctx.one / z) @defun_wrapped def asech(ctx, z): return ctx.acosh(ctx.one / z) @defun_wrapped def acsch(ctx, z): return ctx.asinh(ctx.one / z) @defun def sign(ctx, x): x = ctx.convert(x) if not x or ctx.isnan(x): return x if ctx._is_real_type(x): if x > 0: return ctx.one else: return -ctx.one return x / abs(x) @defun def agm(ctx, a, b=1): if b == 1: return ctx.agm1(a) a = ctx.convert(a) b = ctx.convert(b) return ctx._agm(a, b) @defun_wrapped def sinc(ctx, x): if ctx.isinf(x): return 1/x if not x: return x+1 return ctx.sin(x)/x @defun_wrapped def sincpi(ctx, x): if ctx.isinf(x): return 1/x if not x: return x+1 return ctx.sinpi(x)/(ctx.pi*x) # TODO: tests; improve implementation @defun_wrapped def expm1(ctx, x): if not x: return ctx.zero # exp(x) - 1 ~ x if ctx.mag(x) < -ctx.prec: return x + 0.5*x**2 # TODO: accurately eval the smaller of the real/imag parts return ctx.sum_accurately(lambda: iter([ctx.exp(x),-1]),1) @defun_wrapped def log1p(ctx, x): if not x: return ctx.zero if ctx.mag(x) < -ctx.prec: return x - 0.5*x**2 return ctx.log(ctx.fadd(1, x, prec=2*ctx.prec)) @defun_wrapped def powm1(ctx, x, y): mag = ctx.mag one = ctx.one w = x**y - one M = mag(w) # Only moderate cancellation if M > -8: return w # Check for the only possible exact cases if not w: if (not y) or (x in (1, -1, 1j, -1j) and ctx.isint(y)): return w x1 = x - one magy = mag(y) lnx = ctx.ln(x) # Small y: x^y - 1 ~ log(x)*y + O(log(x)^2 * y^2) if magy + mag(lnx) < -ctx.prec: return lnx*y + (lnx*y)**2/2 # TODO: accurately eval the smaller of the real/imag part return ctx.sum_accurately(lambda: iter([x**y, -1]), 1) @defun def _rootof1(ctx, k, n): k = int(k) n = int(n) k %= n if not k: return ctx.one elif 2*k == n: return -ctx.one elif 4*k == n: return ctx.j elif 4*k == 3*n: return -ctx.j return ctx.expjpi(2*ctx.mpf(k)/n) @defun def root(ctx, x, n, k=0): n = int(n) x = ctx.convert(x) if k: # Special case: there is an exact real root if (n & 1 and 2*k == n-1) and (not ctx.im(x)) and (ctx.re(x) < 0): return -ctx.root(-x, n) # Multiply by root of unity prec = ctx.prec try: ctx.prec += 10 v = ctx.root(x, n, 0) * ctx._rootof1(k, n) finally: ctx.prec = prec return +v return ctx._nthroot(x, n) @defun def unitroots(ctx, n, primitive=False): gcd = ctx._gcd prec = ctx.prec try: ctx.prec += 10 if primitive: v = [ctx._rootof1(k,n) for k in range(n) if gcd(k,n) == 1] else: # TODO: this can be done *much* faster v = [ctx._rootof1(k,n) for k in range(n)] finally: ctx.prec = prec return [+x for x in v] @defun def arg(ctx, x): x = ctx.convert(x) re = ctx._re(x) im = ctx._im(x) return ctx.atan2(im, re) @defun def fabs(ctx, x): return abs(ctx.convert(x)) @defun def re(ctx, x): x = ctx.convert(x) if hasattr(x, "real"): # py2.5 doesn't have .real/.imag for all numbers return x.real return x @defun def im(ctx, x): x = ctx.convert(x) if hasattr(x, "imag"): # py2.5 doesn't have .real/.imag for all numbers return x.imag return ctx.zero @defun def conj(ctx, x): x = ctx.convert(x) try: return x.conjugate() except AttributeError: return x @defun def polar(ctx, z): return (ctx.fabs(z), ctx.arg(z)) @defun_wrapped def rect(ctx, r, phi): return r * ctx.mpc(*ctx.cos_sin(phi)) @defun def log(ctx, x, b=None): if b is None: return ctx.ln(x) wp = ctx.prec + 20 return ctx.ln(x, prec=wp) / ctx.ln(b, prec=wp) @defun def log10(ctx, x): return ctx.log(x, 10) @defun def fmod(ctx, x, y): return ctx.convert(x) % ctx.convert(y) @defun def degrees(ctx, x): return x / ctx.degree @defun def radians(ctx, x): return x * ctx.degree def _lambertw_special(ctx, z, k): # W(0,0) = 0; all other branches are singular if not z: if not k: return z return ctx.ninf + z if z == ctx.inf: if k == 0: return z else: return z + 2*k*ctx.pi*ctx.j if z == ctx.ninf: return (-z) + (2*k+1)*ctx.pi*ctx.j # Some kind of nan or complex inf/nan? return ctx.ln(z) import math import cmath def _lambertw_approx_hybrid(z, k): imag_sign = 0 if hasattr(z, "imag"): x = float(z.real) y = z.imag if y: imag_sign = (-1) ** (y < 0) y = float(y) else: x = float(z) y = 0.0 imag_sign = 0 # hack to work regardless of whether Python supports -0.0 if not y: y = 0.0 z = complex(x,y) if k == 0: if -4.0 < y < 4.0 and -1.0 < x < 2.5: if imag_sign: # Taylor series in upper/lower half-plane if y > 1.00: return (0.876+0.645j) + (0.118-0.174j)*(z-(0.75+2.5j)) if y > 0.25: return (0.505+0.204j) + (0.375-0.132j)*(z-(0.75+0.5j)) if y < -1.00: return (0.876-0.645j) + (0.118+0.174j)*(z-(0.75-2.5j)) if y < -0.25: return (0.505-0.204j) + (0.375+0.132j)*(z-(0.75-0.5j)) # Taylor series near -1 if x < -0.5: if imag_sign >= 0: return (-0.318+1.34j) + (-0.697-0.593j)*(z+1) else: return (-0.318-1.34j) + (-0.697+0.593j)*(z+1) # return real type r = -0.367879441171442 if (not imag_sign) and x > r: z = x # Singularity near -1/e if x < -0.2: return -1 + 2.33164398159712*(z-r)**0.5 - 1.81218788563936*(z-r) # Taylor series near 0 if x < 0.5: return z # Simple linear approximation return 0.2 + 0.3*z if (not imag_sign) and x > 0.0: L1 = math.log(x); L2 = math.log(L1) else: L1 = cmath.log(z); L2 = cmath.log(L1) elif k == -1: # return real type r = -0.367879441171442 if (not imag_sign) and r < x < 0.0: z = x if (imag_sign >= 0) and y < 0.1 and -0.6 < x < -0.2: return -1 - 2.33164398159712*(z-r)**0.5 - 1.81218788563936*(z-r) if (not imag_sign) and -0.2 <= x < 0.0: L1 = math.log(-x) return L1 - math.log(-L1) else: if imag_sign == -1 and (not y) and x < 0.0: L1 = cmath.log(z) - 3.1415926535897932j else: L1 = cmath.log(z) - 6.2831853071795865j L2 = cmath.log(L1) return L1 - L2 + L2/L1 + L2*(L2-2)/(2*L1**2) def _lambertw_series(ctx, z, k, tol): """ Return rough approximation for W_k(z) from an asymptotic series, sufficiently accurate for the Halley iteration to converge to the correct value. """ magz = ctx.mag(z) if (-10 < magz < 900) and (-1000 < k < 1000): # Near the branch point at -1/e if magz < 1 and abs(z+0.36787944117144) < 0.05: if k == 0 or (k == -1 and ctx._im(z) >= 0) or \ (k == 1 and ctx._im(z) < 0): delta = ctx.sum_accurately(lambda: [z, ctx.exp(-1)]) cancellation = -ctx.mag(delta) ctx.prec += cancellation # Use series given in Corless et al. p = ctx.sqrt(2*(ctx.e*z+1)) ctx.prec -= cancellation u = {0:ctx.mpf(-1), 1:ctx.mpf(1)} a = {0:ctx.mpf(2), 1:ctx.mpf(-1)} if k != 0: p = -p s = ctx.zero # The series converges, so we could use it directly, but unless # *extremely* close, it is better to just use the first few # terms to get a good approximation for the iteration for l in xrange(max(2,cancellation)): if l not in u: a[l] = ctx.fsum(u[j]*u[l+1-j] for j in xrange(2,l)) u[l] = (l-1)*(u[l-2]/2+a[l-2]/4)/(l+1)-a[l]/2-u[l-1]/(l+1) term = u[l] * p**l s += term if ctx.mag(term) < -tol: return s, True l += 1 ctx.prec += cancellation//2 return s, False if k == 0 or k == -1: return _lambertw_approx_hybrid(z, k), False if k == 0: if magz < -1: return z*(1-z), False L1 = ctx.ln(z) L2 = ctx.ln(L1) elif k == -1 and (not ctx._im(z)) and (-0.36787944117144 < ctx._re(z) < 0): L1 = ctx.ln(-z) return L1 - ctx.ln(-L1), False else: # This holds both as z -> 0 and z -> inf. # Relative error is O(1/log(z)). L1 = ctx.ln(z) + 2j*ctx.pi*k L2 = ctx.ln(L1) return L1 - L2 + L2/L1 + L2*(L2-2)/(2*L1**2), False @defun def lambertw(ctx, z, k=0): z = ctx.convert(z) k = int(k) if not ctx.isnormal(z): return _lambertw_special(ctx, z, k) prec = ctx.prec ctx.prec += 20 + ctx.mag(k or 1) wp = ctx.prec tol = wp - 5 w, done = _lambertw_series(ctx, z, k, tol) if not done: # Use Halley iteration to solve w*exp(w) = z two = ctx.mpf(2) for i in xrange(100): ew = ctx.exp(w) wew = w*ew wewz = wew-z wn = w - wewz/(wew+ew-(w+two)*wewz/(two*w+two)) if ctx.mag(wn-w) <= ctx.mag(wn) - tol: w = wn break else: w = wn if i == 100: ctx.warn("Lambert W iteration failed to converge for z = %s" % z) ctx.prec = prec return +w @defun_wrapped def bell(ctx, n, x=1): x = ctx.convert(x) if not n: if ctx.isnan(x): return x return type(x)(1) if ctx.isinf(x) or ctx.isinf(n) or ctx.isnan(x) or ctx.isnan(n): return x**n if n == 1: return x if n == 2: return x*(x+1) if x == 0: return ctx.sincpi(n) return _polyexp(ctx, n, x, True) / ctx.exp(x) def _polyexp(ctx, n, x, extra=False): def _terms(): if extra: yield ctx.sincpi(n) t = x k = 1 while 1: yield k**n * t k += 1 t = t*x/k return ctx.sum_accurately(_terms, check_step=4) @defun_wrapped def polyexp(ctx, s, z): if ctx.isinf(z) or ctx.isinf(s) or ctx.isnan(z) or ctx.isnan(s): return z**s if z == 0: return z*s if s == 0: return ctx.expm1(z) if s == 1: return ctx.exp(z)*z if s == 2: return ctx.exp(z)*z*(z+1) return _polyexp(ctx, s, z) @defun_wrapped def cyclotomic(ctx, n, z): n = int(n) if n < 0: raise ValueError("n cannot be negative") p = ctx.one if n == 0: return p if n == 1: return z - p if n == 2: return z + p # Use divisor product representation. Unfortunately, this sometimes # includes singularities for roots of unity, which we have to cancel out. # Matching zeros/poles pairwise, we have (1-z^a)/(1-z^b) ~ a/b + O(z-1). a_prod = 1 b_prod = 1 num_zeros = 0 num_poles = 0 for d in range(1,n+1): if not n % d: w = ctx.moebius(n//d) # Use powm1 because it is important that we get 0 only # if it really is exactly 0 b = -ctx.powm1(z, d) if b: p *= b**w else: if w == 1: a_prod *= d num_zeros += 1 elif w == -1: b_prod *= d num_poles += 1 #print n, num_zeros, num_poles if num_zeros: if num_zeros > num_poles: p *= 0 else: p *= a_prod p /= b_prod return p @defun def mangoldt(ctx, n): r""" Evaluates the von Mangoldt function `\Lambda(n) = \log p` if `n = p^k` a power of a prime, and `\Lambda(n) = 0` otherwise. **Examples** >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> [mangoldt(n) for n in range(-2,3)] [0.0, 0.0, 0.0, 0.0, 0.6931471805599453094172321] >>> mangoldt(6) 0.0 >>> mangoldt(7) 1.945910149055313305105353 >>> mangoldt(8) 0.6931471805599453094172321 >>> fsum(mangoldt(n) for n in range(101)) 94.04531122935739224600493 >>> fsum(mangoldt(n) for n in range(10001)) 10013.39669326311478372032 """ n = int(n) if n < 2: return ctx.zero if n % 2 == 0: # Must be a power of two if n & (n-1) == 0: return +ctx.ln2 else: return ctx.zero # TODO: the following could be generalized into a perfect # power testing function # --- # Look for a small factor for p in (3,5,7,11,13,17,19,23,29,31): if not n % p: q, r = n // p, 0 while q > 1: q, r = divmod(q, p) if r: return ctx.zero return ctx.ln(p) if ctx.isprime(n): return ctx.ln(n) # Obviously, we could use arbitrary-precision arithmetic for this... if n > 10**30: raise NotImplementedError k = 2 while 1: p = int(n**(1./k) + 0.5) if p < 2: return ctx.zero if p ** k == n: if ctx.isprime(p): return ctx.ln(p) k += 1 @defun def stirling1(ctx, n, k, exact=False): v = ctx._stirling1(int(n), int(k)) if exact: return int(v) else: return ctx.mpf(v) @defun def stirling2(ctx, n, k, exact=False): v = ctx._stirling2(int(n), int(k)) if exact: return int(v) else: return ctx.mpf(v) mpmath-1.1.0/mpmath/functions/hypergeometric.py000066400000000000000000001445621340375245600217220ustar00rootroot00000000000000from ..libmp.backend import xrange from .functions import defun, defun_wrapped def _check_need_perturb(ctx, terms, prec, discard_known_zeros): perturb = recompute = False extraprec = 0 discard = [] for term_index, term in enumerate(terms): w_s, c_s, alpha_s, beta_s, a_s, b_s, z = term have_singular_nongamma_weight = False # Avoid division by zero in leading factors (TODO: # also check for near division by zero?) for k, w in enumerate(w_s): if not w: if ctx.re(c_s[k]) <= 0 and c_s[k]: perturb = recompute = True have_singular_nongamma_weight = True pole_count = [0, 0, 0] # Check for gamma and series poles and near-poles for data_index, data in enumerate([alpha_s, beta_s, b_s]): for i, x in enumerate(data): n, d = ctx.nint_distance(x) # Poles if n > 0: continue if d == ctx.ninf: # OK if we have a polynomial # ------------------------------ ok = False if data_index == 2: for u in a_s: if ctx.isnpint(u) and u >= int(n): ok = True break if ok: continue pole_count[data_index] += 1 # ------------------------------ #perturb = recompute = True #return perturb, recompute, extraprec elif d < -4: extraprec += -d recompute = True if discard_known_zeros and pole_count[1] > pole_count[0] + pole_count[2] \ and not have_singular_nongamma_weight: discard.append(term_index) elif sum(pole_count): perturb = recompute = True return perturb, recompute, extraprec, discard _hypercomb_msg = """ hypercomb() failed to converge to the requested %i bits of accuracy using a working precision of %i bits. The function value may be zero or infinite; try passing zeroprec=N or infprec=M to bound finite values between 2^(-N) and 2^M. Otherwise try a higher maxprec or maxterms. """ @defun def hypercomb(ctx, function, params=[], discard_known_zeros=True, **kwargs): orig = ctx.prec sumvalue = ctx.zero dist = ctx.nint_distance ninf = ctx.ninf orig_params = params[:] verbose = kwargs.get('verbose', False) maxprec = kwargs.get('maxprec', ctx._default_hyper_maxprec(orig)) kwargs['maxprec'] = maxprec # For calls to hypsum zeroprec = kwargs.get('zeroprec') infprec = kwargs.get('infprec') perturbed_reference_value = None hextra = 0 try: while 1: ctx.prec += 10 if ctx.prec > maxprec: raise ValueError(_hypercomb_msg % (orig, ctx.prec)) orig2 = ctx.prec params = orig_params[:] terms = function(*params) if verbose: print() print("ENTERING hypercomb main loop") print("prec =", ctx.prec) print("hextra", hextra) perturb, recompute, extraprec, discard = \ _check_need_perturb(ctx, terms, orig, discard_known_zeros) ctx.prec += extraprec if perturb: if "hmag" in kwargs: hmag = kwargs["hmag"] elif ctx._fixed_precision: hmag = int(ctx.prec*0.3) else: hmag = orig + 10 + hextra h = ctx.ldexp(ctx.one, -hmag) ctx.prec = orig2 + 10 + hmag + 10 for k in range(len(params)): params[k] += h # Heuristically ensure that the perturbations # are "independent" so that two perturbations # don't accidentally cancel each other out # in a subtraction. h += h/(k+1) if recompute: terms = function(*params) if discard_known_zeros: terms = [term for (i, term) in enumerate(terms) if i not in discard] if not terms: return ctx.zero evaluated_terms = [] for term_index, term_data in enumerate(terms): w_s, c_s, alpha_s, beta_s, a_s, b_s, z = term_data if verbose: print() print(" Evaluating term %i/%i : %iF%i" % \ (term_index+1, len(terms), len(a_s), len(b_s))) print(" powers", ctx.nstr(w_s), ctx.nstr(c_s)) print(" gamma", ctx.nstr(alpha_s), ctx.nstr(beta_s)) print(" hyper", ctx.nstr(a_s), ctx.nstr(b_s)) print(" z", ctx.nstr(z)) #v = ctx.hyper(a_s, b_s, z, **kwargs) #for a in alpha_s: v *= ctx.gamma(a) #for b in beta_s: v *= ctx.rgamma(b) #for w, c in zip(w_s, c_s): v *= ctx.power(w, c) v = ctx.fprod([ctx.hyper(a_s, b_s, z, **kwargs)] + \ [ctx.gamma(a) for a in alpha_s] + \ [ctx.rgamma(b) for b in beta_s] + \ [ctx.power(w,c) for (w,c) in zip(w_s,c_s)]) if verbose: print(" Value:", v) evaluated_terms.append(v) if len(terms) == 1 and (not perturb): sumvalue = evaluated_terms[0] break if ctx._fixed_precision: sumvalue = ctx.fsum(evaluated_terms) break sumvalue = ctx.fsum(evaluated_terms) term_magnitudes = [ctx.mag(x) for x in evaluated_terms] max_magnitude = max(term_magnitudes) sum_magnitude = ctx.mag(sumvalue) cancellation = max_magnitude - sum_magnitude if verbose: print() print(" Cancellation:", cancellation, "bits") print(" Increased precision:", ctx.prec - orig, "bits") precision_ok = cancellation < ctx.prec - orig if zeroprec is None: zero_ok = False else: zero_ok = max_magnitude - ctx.prec < -zeroprec if infprec is None: inf_ok = False else: inf_ok = max_magnitude > infprec if precision_ok and (not perturb) or ctx.isnan(cancellation): break elif precision_ok: if perturbed_reference_value is None: hextra += 20 perturbed_reference_value = sumvalue continue elif ctx.mag(sumvalue - perturbed_reference_value) <= \ ctx.mag(sumvalue) - orig: break elif zero_ok: sumvalue = ctx.zero break elif inf_ok: sumvalue = ctx.inf break elif 'hmag' in kwargs: break else: hextra *= 2 perturbed_reference_value = sumvalue # Increase precision else: increment = min(max(cancellation, orig//2), max(extraprec,orig)) ctx.prec += increment if verbose: print(" Must start over with increased precision") continue finally: ctx.prec = orig return +sumvalue @defun def hyper(ctx, a_s, b_s, z, **kwargs): """ Hypergeometric function, general case. """ z = ctx.convert(z) p = len(a_s) q = len(b_s) a_s = [ctx._convert_param(a) for a in a_s] b_s = [ctx._convert_param(b) for b in b_s] # Reduce degree by eliminating common parameters if kwargs.get('eliminate', True): elim_nonpositive = kwargs.get('eliminate_all', False) i = 0 while i < q and a_s: b = b_s[i] if b in a_s and (elim_nonpositive or not ctx.isnpint(b[0])): a_s.remove(b) b_s.remove(b) p -= 1 q -= 1 else: i += 1 # Handle special cases if p == 0: if q == 1: return ctx._hyp0f1(b_s, z, **kwargs) elif q == 0: return ctx.exp(z) elif p == 1: if q == 1: return ctx._hyp1f1(a_s, b_s, z, **kwargs) elif q == 2: return ctx._hyp1f2(a_s, b_s, z, **kwargs) elif q == 0: return ctx._hyp1f0(a_s[0][0], z) elif p == 2: if q == 1: return ctx._hyp2f1(a_s, b_s, z, **kwargs) elif q == 2: return ctx._hyp2f2(a_s, b_s, z, **kwargs) elif q == 3: return ctx._hyp2f3(a_s, b_s, z, **kwargs) elif q == 0: return ctx._hyp2f0(a_s, b_s, z, **kwargs) elif p == q+1: return ctx._hypq1fq(p, q, a_s, b_s, z, **kwargs) elif p > q+1 and not kwargs.get('force_series'): return ctx._hyp_borel(p, q, a_s, b_s, z, **kwargs) coeffs, types = zip(*(a_s+b_s)) return ctx.hypsum(p, q, types, coeffs, z, **kwargs) @defun def hyp0f1(ctx,b,z,**kwargs): return ctx.hyper([],[b],z,**kwargs) @defun def hyp1f1(ctx,a,b,z,**kwargs): return ctx.hyper([a],[b],z,**kwargs) @defun def hyp1f2(ctx,a1,b1,b2,z,**kwargs): return ctx.hyper([a1],[b1,b2],z,**kwargs) @defun def hyp2f1(ctx,a,b,c,z,**kwargs): return ctx.hyper([a,b],[c],z,**kwargs) @defun def hyp2f2(ctx,a1,a2,b1,b2,z,**kwargs): return ctx.hyper([a1,a2],[b1,b2],z,**kwargs) @defun def hyp2f3(ctx,a1,a2,b1,b2,b3,z,**kwargs): return ctx.hyper([a1,a2],[b1,b2,b3],z,**kwargs) @defun def hyp2f0(ctx,a,b,z,**kwargs): return ctx.hyper([a,b],[],z,**kwargs) @defun def hyp3f2(ctx,a1,a2,a3,b1,b2,z,**kwargs): return ctx.hyper([a1,a2,a3],[b1,b2],z,**kwargs) @defun_wrapped def _hyp1f0(ctx, a, z): return (1-z) ** (-a) @defun def _hyp0f1(ctx, b_s, z, **kwargs): (b, btype), = b_s if z: magz = ctx.mag(z) else: magz = 0 if magz >= 8 and not kwargs.get('force_series'): try: # http://functions.wolfram.com/HypergeometricFunctions/ # Hypergeometric0F1/06/02/03/0004/ # TODO: handle the all-real case more efficiently! # TODO: figure out how much precision is needed (exponential growth) orig = ctx.prec try: ctx.prec += 12 + magz//2 def h(): w = ctx.sqrt(-z) jw = ctx.j*w u = 1/(4*jw) c = ctx.mpq_1_2 - b E = ctx.exp(2*jw) T1 = ([-jw,E], [c,-1], [], [], [b-ctx.mpq_1_2, ctx.mpq_3_2-b], [], -u) T2 = ([jw,E], [c,1], [], [], [b-ctx.mpq_1_2, ctx.mpq_3_2-b], [], u) return T1, T2 v = ctx.hypercomb(h, [], force_series=True) v = ctx.gamma(b)/(2*ctx.sqrt(ctx.pi))*v finally: ctx.prec = orig if ctx._is_real_type(b) and ctx._is_real_type(z): v = ctx._re(v) return +v except ctx.NoConvergence: pass return ctx.hypsum(0, 1, (btype,), [b], z, **kwargs) @defun def _hyp1f1(ctx, a_s, b_s, z, **kwargs): (a, atype), = a_s (b, btype), = b_s if not z: return ctx.one+z magz = ctx.mag(z) if magz >= 7 and not (ctx.isint(a) and ctx.re(a) <= 0): if ctx.isinf(z): if ctx.sign(a) == ctx.sign(b) == ctx.sign(z) == 1: return ctx.inf return ctx.nan * z try: try: ctx.prec += magz sector = ctx._im(z) < 0 def h(a,b): if sector: E = ctx.expjpi(ctx.fneg(a, exact=True)) else: E = ctx.expjpi(a) rz = 1/z T1 = ([E,z], [1,-a], [b], [b-a], [a, 1+a-b], [], -rz) T2 = ([ctx.exp(z),z], [1,a-b], [b], [a], [b-a, 1-a], [], rz) return T1, T2 v = ctx.hypercomb(h, [a,b], force_series=True) if ctx._is_real_type(a) and ctx._is_real_type(b) and ctx._is_real_type(z): v = ctx._re(v) return +v except ctx.NoConvergence: pass finally: ctx.prec -= magz v = ctx.hypsum(1, 1, (atype, btype), [a, b], z, **kwargs) return v def _hyp2f1_gosper(ctx,a,b,c,z,**kwargs): # Use Gosper's recurrence # See http://www.math.utexas.edu/pipermail/maxima/2006/000126.html _a,_b,_c,_z = a, b, c, z orig = ctx.prec maxprec = kwargs.get('maxprec', 100*orig) extra = 10 while 1: ctx.prec = orig + extra #a = ctx.convert(_a) #b = ctx.convert(_b) #c = ctx.convert(_c) z = ctx.convert(_z) d = ctx.mpf(0) e = ctx.mpf(1) f = ctx.mpf(0) k = 0 # Common subexpression elimination, unfortunately making # things a bit unreadable. The formula is quite messy to begin # with, though... abz = a*b*z ch = c * ctx.mpq_1_2 c1h = (c+1) * ctx.mpq_1_2 nz = 1-z g = z/nz abg = a*b*g cba = c-b-a z2 = z-2 tol = -ctx.prec - 10 nstr = ctx.nstr nprint = ctx.nprint mag = ctx.mag maxmag = ctx.ninf while 1: kch = k+ch kakbz = (k+a)*(k+b)*z / (4*(k+1)*kch*(k+c1h)) d1 = kakbz*(e-(k+cba)*d*g) e1 = kakbz*(d*abg+(k+c)*e) ft = d*(k*(cba*z+k*z2-c)-abz)/(2*kch*nz) f1 = f + e - ft maxmag = max(maxmag, mag(f1)) if mag(f1-f) < tol: break d, e, f = d1, e1, f1 k += 1 cancellation = maxmag - mag(f1) if cancellation < extra: break else: extra += cancellation if extra > maxprec: raise ctx.NoConvergence return f1 @defun def _hyp2f1(ctx, a_s, b_s, z, **kwargs): (a, atype), (b, btype) = a_s (c, ctype), = b_s if z == 1: # TODO: the following logic can be simplified convergent = ctx.re(c-a-b) > 0 finite = (ctx.isint(a) and a <= 0) or (ctx.isint(b) and b <= 0) zerodiv = ctx.isint(c) and c <= 0 and not \ ((ctx.isint(a) and c <= a <= 0) or (ctx.isint(b) and c <= b <= 0)) #print "bz", a, b, c, z, convergent, finite, zerodiv # Gauss's theorem gives the value if convergent if (convergent or finite) and not zerodiv: return ctx.gammaprod([c, c-a-b], [c-a, c-b], _infsign=True) # Otherwise, there is a pole and we take the # sign to be that when approaching from below # XXX: this evaluation is not necessarily correct in all cases return ctx.hyp2f1(a,b,c,1-ctx.eps*2) * ctx.inf # Equal to 1 (first term), unless there is a subsequent # division by zero if not z: # Division by zero but power of z is higher than # first order so cancels if c or a == 0 or b == 0: return 1+z # Indeterminate return ctx.nan # Hit zero denominator unless numerator goes to 0 first if ctx.isint(c) and c <= 0: if (ctx.isint(a) and c <= a <= 0) or \ (ctx.isint(b) and c <= b <= 0): pass else: # Pole in series return ctx.inf absz = abs(z) # Fast case: standard series converges rapidly, # possibly in finitely many terms if absz <= 0.8 or (ctx.isint(a) and a <= 0 and a >= -1000) or \ (ctx.isint(b) and b <= 0 and b >= -1000): return ctx.hypsum(2, 1, (atype, btype, ctype), [a, b, c], z, **kwargs) orig = ctx.prec try: ctx.prec += 10 # Use 1/z transformation if absz >= 1.3: def h(a,b): t = ctx.mpq_1-c; ab = a-b; rz = 1/z T1 = ([-z],[-a], [c,-ab],[b,c-a], [a,t+a],[ctx.mpq_1+ab], rz) T2 = ([-z],[-b], [c,ab],[a,c-b], [b,t+b],[ctx.mpq_1-ab], rz) return T1, T2 v = ctx.hypercomb(h, [a,b], **kwargs) # Use 1-z transformation elif abs(1-z) <= 0.75: def h(a,b): t = c-a-b; ca = c-a; cb = c-b; rz = 1-z T1 = [], [], [c,t], [ca,cb], [a,b], [1-t], rz T2 = [rz], [t], [c,a+b-c], [a,b], [ca,cb], [1+t], rz return T1, T2 v = ctx.hypercomb(h, [a,b], **kwargs) # Use z/(z-1) transformation elif abs(z/(z-1)) <= 0.75: v = ctx.hyp2f1(a, c-b, c, z/(z-1)) / (1-z)**a # Remaining part of unit circle else: v = _hyp2f1_gosper(ctx,a,b,c,z,**kwargs) finally: ctx.prec = orig return +v @defun def _hypq1fq(ctx, p, q, a_s, b_s, z, **kwargs): r""" Evaluates 3F2, 4F3, 5F4, ... """ a_s, a_types = zip(*a_s) b_s, b_types = zip(*b_s) a_s = list(a_s) b_s = list(b_s) absz = abs(z) ispoly = False for a in a_s: if ctx.isint(a) and a <= 0: ispoly = True break # Direct summation if absz < 1 or ispoly: try: return ctx.hypsum(p, q, a_types+b_types, a_s+b_s, z, **kwargs) except ctx.NoConvergence: if absz > 1.1 or ispoly: raise # Use expansion at |z-1| -> 0. # Reference: Wolfgang Buhring, "Generalized Hypergeometric Functions at # Unit Argument", Proc. Amer. Math. Soc., Vol. 114, No. 1 (Jan. 1992), # pp.145-153 # The current implementation has several problems: # 1. We only implement it for 3F2. The expansion coefficients are # given by extremely messy nested sums in the higher degree cases # (see reference). Is efficient sequential generation of the coefficients # possible in the > 3F2 case? # 2. Although the series converges, it may do so slowly, so we need # convergence acceleration. The acceleration implemented by # nsum does not always help, so results returned are sometimes # inaccurate! Can we do better? # 3. We should check conditions for convergence, and possibly # do a better job of cancelling out gamma poles if possible. if z == 1: # XXX: should also check for division by zero in the # denominator of the series (cf. hyp2f1) S = ctx.re(sum(b_s)-sum(a_s)) if S <= 0: #return ctx.hyper(a_s, b_s, 1-ctx.eps*2, **kwargs) * ctx.inf return ctx.hyper(a_s, b_s, 0.9, **kwargs) * ctx.inf if (p,q) == (3,2) and abs(z-1) < 0.05: # and kwargs.get('sum1') #print "Using alternate summation (experimental)" a1,a2,a3 = a_s b1,b2 = b_s u = b1+b2-a3 initial = ctx.gammaprod([b2-a3,b1-a3,a1,a2],[b2-a3,b1-a3,1,u]) def term(k, _cache={0:initial}): u = b1+b2-a3+k if k in _cache: t = _cache[k] else: t = _cache[k-1] t *= (b1+k-a3-1)*(b2+k-a3-1) t /= k*(u-1) _cache[k] = t return t * ctx.hyp2f1(a1,a2,u,z) try: S = ctx.nsum(term, [0,ctx.inf], verbose=kwargs.get('verbose'), strict=kwargs.get('strict', True)) return S * ctx.gammaprod([b1,b2],[a1,a2,a3]) except ctx.NoConvergence: pass # Try to use convergence acceleration on and close to the unit circle. # Problem: the convergence acceleration degenerates as |z-1| -> 0, # except for special cases. Everywhere else, the Shanks transformation # is very efficient. if absz < 1.1 and ctx._re(z) <= 1: def term(kk, _cache={0:ctx.one}): k = int(kk) if k != kk: t = z ** ctx.mpf(kk) / ctx.fac(kk) for a in a_s: t *= ctx.rf(a,kk) for b in b_s: t /= ctx.rf(b,kk) return t if k in _cache: return _cache[k] t = term(k-1) m = k-1 for j in xrange(p): t *= (a_s[j]+m) for j in xrange(q): t /= (b_s[j]+m) t *= z t /= k _cache[k] = t return t sum_method = kwargs.get('sum_method', 'r+s+e') try: return ctx.nsum(term, [0,ctx.inf], verbose=kwargs.get('verbose'), strict=kwargs.get('strict', True), method=sum_method.replace('e','')) except ctx.NoConvergence: if 'e' not in sum_method: raise pass if kwargs.get('verbose'): print("Attempting Euler-Maclaurin summation") """ Somewhat slower version (one diffs_exp for each factor). However, this would be faster with fast direct derivatives of the gamma function. def power_diffs(k0): r = 0 l = ctx.log(z) while 1: yield z**ctx.mpf(k0) * l**r r += 1 def loggamma_diffs(x, reciprocal=False): sign = (-1) ** reciprocal yield sign * ctx.loggamma(x) i = 0 while 1: yield sign * ctx.psi(i,x) i += 1 def hyper_diffs(k0): b2 = b_s + [1] A = [ctx.diffs_exp(loggamma_diffs(a+k0)) for a in a_s] B = [ctx.diffs_exp(loggamma_diffs(b+k0,True)) for b in b2] Z = [power_diffs(k0)] C = ctx.gammaprod([b for b in b2], [a for a in a_s]) for d in ctx.diffs_prod(A + B + Z): v = C * d yield v """ def log_diffs(k0): b2 = b_s + [1] yield sum(ctx.loggamma(a+k0) for a in a_s) - \ sum(ctx.loggamma(b+k0) for b in b2) + k0*ctx.log(z) i = 0 while 1: v = sum(ctx.psi(i,a+k0) for a in a_s) - \ sum(ctx.psi(i,b+k0) for b in b2) if i == 0: v += ctx.log(z) yield v i += 1 def hyper_diffs(k0): C = ctx.gammaprod([b for b in b_s], [a for a in a_s]) for d in ctx.diffs_exp(log_diffs(k0)): v = C * d yield v tol = ctx.eps / 1024 prec = ctx.prec try: trunc = 50 * ctx.dps ctx.prec += 20 for i in xrange(5): head = ctx.fsum(term(k) for k in xrange(trunc)) tail, err = ctx.sumem(term, [trunc, ctx.inf], tol=tol, adiffs=hyper_diffs(trunc), verbose=kwargs.get('verbose'), error=True, _fast_abort=True) if err < tol: v = head + tail break trunc *= 2 # Need to increase precision because calculation of # derivatives may be inaccurate ctx.prec += ctx.prec//2 if i == 4: raise ctx.NoConvergence(\ "Euler-Maclaurin summation did not converge") finally: ctx.prec = prec return +v # Use 1/z transformation # http://functions.wolfram.com/HypergeometricFunctions/ # HypergeometricPFQ/06/01/05/02/0004/ def h(*args): a_s = list(args[:p]) b_s = list(args[p:]) Ts = [] recz = ctx.one/z negz = ctx.fneg(z, exact=True) for k in range(q+1): ak = a_s[k] C = [negz] Cp = [-ak] Gn = b_s + [ak] + [a_s[j]-ak for j in range(q+1) if j != k] Gd = a_s + [b_s[j]-ak for j in range(q)] Fn = [ak] + [ak-b_s[j]+1 for j in range(q)] Fd = [1-a_s[j]+ak for j in range(q+1) if j != k] Ts.append((C, Cp, Gn, Gd, Fn, Fd, recz)) return Ts return ctx.hypercomb(h, a_s+b_s, **kwargs) @defun def _hyp_borel(ctx, p, q, a_s, b_s, z, **kwargs): if a_s: a_s, a_types = zip(*a_s) a_s = list(a_s) else: a_s, a_types = [], () if b_s: b_s, b_types = zip(*b_s) b_s = list(b_s) else: b_s, b_types = [], () kwargs['maxterms'] = kwargs.get('maxterms', ctx.prec) try: return ctx.hypsum(p, q, a_types+b_types, a_s+b_s, z, **kwargs) except ctx.NoConvergence: pass prec = ctx.prec try: tol = kwargs.get('asymp_tol', ctx.eps/4) ctx.prec += 10 # hypsum is has a conservative tolerance. So we try again: def term(k, cache={0:ctx.one}): if k in cache: return cache[k] t = term(k-1) for a in a_s: t *= (a+(k-1)) for b in b_s: t /= (b+(k-1)) t *= z t /= k cache[k] = t return t s = ctx.one for k in xrange(1, ctx.prec): t = term(k) s += t if abs(t) <= tol: return s finally: ctx.prec = prec if p <= q+3: contour = kwargs.get('contour') if not contour: if ctx.arg(z) < 0.25: u = z / max(1, abs(z)) if ctx.arg(z) >= 0: contour = [0, 2j, (2j+2)/u, 2/u, ctx.inf] else: contour = [0, -2j, (-2j+2)/u, 2/u, ctx.inf] #contour = [0, 2j/z, 2/z, ctx.inf] #contour = [0, 2j, 2/z, ctx.inf] #contour = [0, 2j, ctx.inf] else: contour = [0, ctx.inf] quad_kwargs = kwargs.get('quad_kwargs', {}) def g(t): return ctx.exp(-t)*ctx.hyper(a_s, b_s+[1], t*z) I, err = ctx.quad(g, contour, error=True, **quad_kwargs) if err <= abs(I)*ctx.eps*8: return I raise ctx.NoConvergence @defun def _hyp2f2(ctx, a_s, b_s, z, **kwargs): (a1, a1type), (a2, a2type) = a_s (b1, b1type), (b2, b2type) = b_s absz = abs(z) magz = ctx.mag(z) orig = ctx.prec # Asymptotic expansion is ~ exp(z) asymp_extraprec = magz # Asymptotic series is in terms of 3F1 can_use_asymptotic = (not kwargs.get('force_series')) and \ (ctx.mag(absz) > 3) # TODO: much of the following could be shared with 2F3 instead of # copypasted if can_use_asymptotic: #print "using asymp" try: try: ctx.prec += asymp_extraprec # http://functions.wolfram.com/HypergeometricFunctions/ # Hypergeometric2F2/06/02/02/0002/ def h(a1,a2,b1,b2): X = a1+a2-b1-b2 A2 = a1+a2 B2 = b1+b2 c = {} c[0] = ctx.one c[1] = (A2-1)*X+b1*b2-a1*a2 s1 = 0 k = 0 tprev = 0 while 1: if k not in c: 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 uu2 = (k-A2+b1-1)*(k-A2+b2-1)*(k-X-2) c[k] = ctx.one/k * (uu1*c[k-1]-uu2*c[k-2]) t1 = c[k] * z**(-k) if abs(t1) < 0.1*ctx.eps: #print "Convergence :)" break # Quit if the series doesn't converge quickly enough if k > 5 and abs(tprev) / abs(t1) < 1.5: #print "No convergence :(" raise ctx.NoConvergence s1 += t1 tprev = t1 k += 1 S = ctx.exp(z)*s1 T1 = [z,S], [X,1], [b1,b2],[a1,a2],[],[],0 T2 = [-z],[-a1],[b1,b2,a2-a1],[a2,b1-a1,b2-a1],[a1,a1-b1+1,a1-b2+1],[a1-a2+1],-1/z T3 = [-z],[-a2],[b1,b2,a1-a2],[a1,b1-a2,b2-a2],[a2,a2-b1+1,a2-b2+1],[-a1+a2+1],-1/z return T1, T2, T3 v = ctx.hypercomb(h, [a1,a2,b1,b2], force_series=True, maxterms=4*ctx.prec) if sum(ctx._is_real_type(u) for u in [a1,a2,b1,b2,z]) == 5: v = ctx.re(v) return v except ctx.NoConvergence: pass finally: ctx.prec = orig return ctx.hypsum(2, 2, (a1type, a2type, b1type, b2type), [a1, a2, b1, b2], z, **kwargs) @defun def _hyp1f2(ctx, a_s, b_s, z, **kwargs): (a1, a1type), = a_s (b1, b1type), (b2, b2type) = b_s absz = abs(z) magz = ctx.mag(z) orig = ctx.prec # Asymptotic expansion is ~ exp(sqrt(z)) asymp_extraprec = z and magz//2 # Asymptotic series is in terms of 3F0 can_use_asymptotic = (not kwargs.get('force_series')) and \ (ctx.mag(absz) > 19) and \ (ctx.sqrt(absz) > 1.5*orig) # and \ # ctx._hyp_check_convergence([a1, a1-b1+1, a1-b2+1], [], # 1/absz, orig+40+asymp_extraprec) # TODO: much of the following could be shared with 2F3 instead of # copypasted if can_use_asymptotic: #print "using asymp" try: try: ctx.prec += asymp_extraprec # http://functions.wolfram.com/HypergeometricFunctions/ # Hypergeometric1F2/06/02/03/ def h(a1,b1,b2): X = ctx.mpq_1_2*(a1-b1-b2+ctx.mpq_1_2) c = {} c[0] = ctx.one c[1] = 2*(ctx.mpq_1_4*(3*a1+b1+b2-2)*(a1-b1-b2)+b1*b2-ctx.mpq_3_16) c[2] = 2*(b1*b2+ctx.mpq_1_4*(a1-b1-b2)*(3*a1+b1+b2-2)-ctx.mpq_3_16)**2+\ ctx.mpq_1_16*(-16*(2*a1-3)*b1*b2 + \ 4*(a1-b1-b2)*(-8*a1**2+11*a1+b1+b2-2)-3) s1 = 0 s2 = 0 k = 0 tprev = 0 while 1: if k not in c: uu1 = (3*k**2+(-6*a1+2*b1+2*b2-4)*k + 3*a1**2 - \ (b1-b2)**2 - 2*a1*(b1+b2-2) + ctx.mpq_1_4) uu2 = (k-a1+b1-b2-ctx.mpq_1_2)*(k-a1-b1+b2-ctx.mpq_1_2)*\ (k-a1+b1+b2-ctx.mpq_5_2) c[k] = ctx.one/(2*k)*(uu1*c[k-1]-uu2*c[k-2]) w = c[k] * (-z)**(-0.5*k) t1 = (-ctx.j)**k * ctx.mpf(2)**(-k) * w t2 = ctx.j**k * ctx.mpf(2)**(-k) * w if abs(t1) < 0.1*ctx.eps: #print "Convergence :)" break # Quit if the series doesn't converge quickly enough if k > 5 and abs(tprev) / abs(t1) < 1.5: #print "No convergence :(" raise ctx.NoConvergence s1 += t1 s2 += t2 tprev = t1 k += 1 S = ctx.expj(ctx.pi*X+2*ctx.sqrt(-z))*s1 + \ ctx.expj(-(ctx.pi*X+2*ctx.sqrt(-z)))*s2 T1 = [0.5*S, ctx.pi, -z], [1, -0.5, X], [b1, b2], [a1],\ [], [], 0 T2 = [-z], [-a1], [b1,b2],[b1-a1,b2-a1], \ [a1,a1-b1+1,a1-b2+1], [], 1/z return T1, T2 v = ctx.hypercomb(h, [a1,b1,b2], force_series=True, maxterms=4*ctx.prec) if sum(ctx._is_real_type(u) for u in [a1,b1,b2,z]) == 4: v = ctx.re(v) return v except ctx.NoConvergence: pass finally: ctx.prec = orig #print "not using asymp" return ctx.hypsum(1, 2, (a1type, b1type, b2type), [a1, b1, b2], z, **kwargs) @defun def _hyp2f3(ctx, a_s, b_s, z, **kwargs): (a1, a1type), (a2, a2type) = a_s (b1, b1type), (b2, b2type), (b3, b3type) = b_s absz = abs(z) magz = ctx.mag(z) # Asymptotic expansion is ~ exp(sqrt(z)) asymp_extraprec = z and magz//2 orig = ctx.prec # Asymptotic series is in terms of 4F1 # The square root below empirically provides a plausible criterion # for the leading series to converge can_use_asymptotic = (not kwargs.get('force_series')) and \ (ctx.mag(absz) > 19) and (ctx.sqrt(absz) > 1.5*orig) if can_use_asymptotic: #print "using asymp" try: try: ctx.prec += asymp_extraprec # http://functions.wolfram.com/HypergeometricFunctions/ # Hypergeometric2F3/06/02/03/01/0002/ def h(a1,a2,b1,b2,b3): X = ctx.mpq_1_2*(a1+a2-b1-b2-b3+ctx.mpq_1_2) A2 = a1+a2 B3 = b1+b2+b3 A = a1*a2 B = b1*b2+b3*b2+b1*b3 R = b1*b2*b3 c = {} c[0] = ctx.one c[1] = 2*(B - A + ctx.mpq_1_4*(3*A2+B3-2)*(A2-B3) - ctx.mpq_3_16) c[2] = ctx.mpq_1_2*c[1]**2 + ctx.mpq_1_16*(-16*(2*A2-3)*(B-A) + 32*R +\ 4*(-8*A2**2 + 11*A2 + 8*A + B3 - 2)*(A2-B3)-3) s1 = 0 s2 = 0 k = 0 tprev = 0 while 1: if k not in c: uu1 = (k-2*X-3)*(k-2*X-2*b1-1)*(k-2*X-2*b2-1)*\ (k-2*X-2*b3-1) uu2 = (4*(k-1)**3 - 6*(4*X+B3)*(k-1)**2 + \ 2*(24*X**2+12*B3*X+4*B+B3-1)*(k-1) - 32*X**3 - \ 24*B3*X**2 - 4*B - 8*R - 4*(4*B+B3-1)*X + 2*B3-1) uu3 = (5*(k-1)**2+2*(-10*X+A2-3*B3+3)*(k-1)+2*c[1]) c[k] = ctx.one/(2*k)*(uu1*c[k-3]-uu2*c[k-2]+uu3*c[k-1]) w = c[k] * ctx.power(-z, -0.5*k) t1 = (-ctx.j)**k * ctx.mpf(2)**(-k) * w t2 = ctx.j**k * ctx.mpf(2)**(-k) * w if abs(t1) < 0.1*ctx.eps: break # Quit if the series doesn't converge quickly enough if k > 5 and abs(tprev) / abs(t1) < 1.5: raise ctx.NoConvergence s1 += t1 s2 += t2 tprev = t1 k += 1 S = ctx.expj(ctx.pi*X+2*ctx.sqrt(-z))*s1 + \ ctx.expj(-(ctx.pi*X+2*ctx.sqrt(-z)))*s2 T1 = [0.5*S, ctx.pi, -z], [1, -0.5, X], [b1, b2, b3], [a1, a2],\ [], [], 0 T2 = [-z], [-a1], [b1,b2,b3,a2-a1],[a2,b1-a1,b2-a1,b3-a1], \ [a1,a1-b1+1,a1-b2+1,a1-b3+1], [a1-a2+1], 1/z T3 = [-z], [-a2], [b1,b2,b3,a1-a2],[a1,b1-a2,b2-a2,b3-a2], \ [a2,a2-b1+1,a2-b2+1,a2-b3+1],[-a1+a2+1], 1/z return T1, T2, T3 v = ctx.hypercomb(h, [a1,a2,b1,b2,b3], force_series=True, maxterms=4*ctx.prec) if sum(ctx._is_real_type(u) for u in [a1,a2,b1,b2,b3,z]) == 6: v = ctx.re(v) return v except ctx.NoConvergence: pass finally: ctx.prec = orig return ctx.hypsum(2, 3, (a1type, a2type, b1type, b2type, b3type), [a1, a2, b1, b2, b3], z, **kwargs) @defun def _hyp2f0(ctx, a_s, b_s, z, **kwargs): (a, atype), (b, btype) = a_s # We want to try aggressively to use the asymptotic expansion, # and fall back only when absolutely necessary try: kwargsb = kwargs.copy() kwargsb['maxterms'] = kwargsb.get('maxterms', ctx.prec) return ctx.hypsum(2, 0, (atype,btype), [a,b], z, **kwargsb) except ctx.NoConvergence: if kwargs.get('force_series'): raise pass def h(a, b): w = ctx.sinpi(b) rz = -1/z T1 = ([ctx.pi,w,rz],[1,-1,a],[],[a-b+1,b],[a],[b],rz) T2 = ([-ctx.pi,w,rz],[1,-1,1+a-b],[],[a,2-b],[a-b+1],[2-b],rz) return T1, T2 return ctx.hypercomb(h, [a, 1+a-b], **kwargs) @defun def meijerg(ctx, a_s, b_s, z, r=1, series=None, **kwargs): an, ap = a_s bm, bq = b_s n = len(an) p = n + len(ap) m = len(bm) q = m + len(bq) a = an+ap b = bm+bq a = [ctx.convert(_) for _ in a] b = [ctx.convert(_) for _ in b] z = ctx.convert(z) if series is None: if p < q: series = 1 if p > q: series = 2 if p == q: if m+n == p and abs(z) > 1: series = 2 else: series = 1 if kwargs.get('verbose'): print("Meijer G m,n,p,q,series =", m,n,p,q,series) if series == 1: def h(*args): a = args[:p] b = args[p:] terms = [] for k in range(m): bases = [z] expts = [b[k]/r] gn = [b[j]-b[k] for j in range(m) if j != k] gn += [1-a[j]+b[k] for j in range(n)] gd = [a[j]-b[k] for j in range(n,p)] gd += [1-b[j]+b[k] for j in range(m,q)] hn = [1-a[j]+b[k] for j in range(p)] hd = [1-b[j]+b[k] for j in range(q) if j != k] hz = (-ctx.one)**(p-m-n) * z**(ctx.one/r) terms.append((bases, expts, gn, gd, hn, hd, hz)) return terms else: def h(*args): a = args[:p] b = args[p:] terms = [] for k in range(n): bases = [z] if r == 1: expts = [a[k]-1] else: expts = [(a[k]-1)/ctx.convert(r)] gn = [a[k]-a[j] for j in range(n) if j != k] gn += [1-a[k]+b[j] for j in range(m)] gd = [a[k]-b[j] for j in range(m,q)] gd += [1-a[k]+a[j] for j in range(n,p)] hn = [1-a[k]+b[j] for j in range(q)] hd = [1+a[j]-a[k] for j in range(p) if j != k] hz = (-ctx.one)**(q-m-n) / z**(ctx.one/r) terms.append((bases, expts, gn, gd, hn, hd, hz)) return terms return ctx.hypercomb(h, a+b, **kwargs) @defun_wrapped def appellf1(ctx,a,b1,b2,c,x,y,**kwargs): # Assume x smaller # We will use x for the outer loop if abs(x) > abs(y): x, y = y, x b1, b2 = b2, b1 def ok(x): return abs(x) < 0.99 # Finite cases if ctx.isnpint(a): pass elif ctx.isnpint(b1): pass elif ctx.isnpint(b2): x, y, b1, b2 = y, x, b2, b1 else: #print x, y # Note: ok if |y| > 1, because # 2F1 implements analytic continuation if not ok(x): u1 = (x-y)/(x-1) if not ok(u1): raise ValueError("Analytic continuation not implemented") #print "Using analytic continuation" return (1-x)**(-b1)*(1-y)**(c-a-b2)*\ ctx.appellf1(c-a,b1,c-b1-b2,c,u1,y,**kwargs) return ctx.hyper2d({'m+n':[a],'m':[b1],'n':[b2]}, {'m+n':[c]}, x,y, **kwargs) @defun def appellf2(ctx,a,b1,b2,c1,c2,x,y,**kwargs): # TODO: continuation return ctx.hyper2d({'m+n':[a],'m':[b1],'n':[b2]}, {'m':[c1],'n':[c2]}, x,y, **kwargs) @defun def appellf3(ctx,a1,a2,b1,b2,c,x,y,**kwargs): outer_polynomial = ctx.isnpint(a1) or ctx.isnpint(b1) inner_polynomial = ctx.isnpint(a2) or ctx.isnpint(b2) if not outer_polynomial: if inner_polynomial or abs(x) > abs(y): x, y = y, x a1,a2,b1,b2 = a2,a1,b2,b1 return ctx.hyper2d({'m':[a1,b1],'n':[a2,b2]}, {'m+n':[c]},x,y,**kwargs) @defun def appellf4(ctx,a,b,c1,c2,x,y,**kwargs): # TODO: continuation return ctx.hyper2d({'m+n':[a,b]}, {'m':[c1],'n':[c2]},x,y,**kwargs) @defun def hyper2d(ctx, a, b, x, y, **kwargs): r""" Sums the generalized 2D hypergeometric series .. math :: \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{P((a),m,n)}{Q((b),m,n)} \frac{x^m y^n} {m! n!} where `(a) = (a_1,\ldots,a_r)`, `(b) = (b_1,\ldots,b_s)` and where `P` and `Q` are products of rising factorials such as `(a_j)_n` or `(a_j)_{m+n}`. `P` and `Q` are specified in the form of dicts, with the `m` and `n` dependence as keys and parameter lists as values. The supported rising factorials are given in the following table (note that only a few are supported in `Q`): +------------+-------------------+--------+ | Key | Rising factorial | `Q` | +============+===================+========+ | ``'m'`` | `(a_j)_m` | Yes | +------------+-------------------+--------+ | ``'n'`` | `(a_j)_n` | Yes | +------------+-------------------+--------+ | ``'m+n'`` | `(a_j)_{m+n}` | Yes | +------------+-------------------+--------+ | ``'m-n'`` | `(a_j)_{m-n}` | No | +------------+-------------------+--------+ | ``'n-m'`` | `(a_j)_{n-m}` | No | +------------+-------------------+--------+ | ``'2m+n'`` | `(a_j)_{2m+n}` | No | +------------+-------------------+--------+ | ``'2m-n'`` | `(a_j)_{2m-n}` | No | +------------+-------------------+--------+ | ``'2n-m'`` | `(a_j)_{2n-m}` | No | +------------+-------------------+--------+ For example, the Appell F1 and F4 functions .. math :: F_1 = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{(a)_{m+n} (b)_m (c)_n}{(d)_{m+n}} \frac{x^m y^n}{m! n!} F_4 = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} \frac{(a)_{m+n} (b)_{m+n}}{(c)_m (d)_{n}} \frac{x^m y^n}{m! n!} can be represented respectively as ``hyper2d({'m+n':[a], 'm':[b], 'n':[c]}, {'m+n':[d]}, x, y)`` ``hyper2d({'m+n':[a,b]}, {'m':[c], 'n':[d]}, x, y)`` More generally, :func:`~mpmath.hyper2d` can evaluate any of the 34 distinct convergent second-order (generalized Gaussian) hypergeometric series enumerated by Horn, as well as the Kampe de Feriet function. The series is computed by rewriting it so that the inner series (i.e. the series containing `n` and `y`) has the form of an ordinary generalized hypergeometric series and thereby can be evaluated efficiently using :func:`~mpmath.hyper`. If possible, manually swapping `x` and `y` and the corresponding parameters can sometimes give better results. **Examples** Two separable cases: a product of two geometric series, and a product of two Gaussian hypergeometric functions:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> x, y = mpf(0.25), mpf(0.5) >>> hyper2d({'m':1,'n':1}, {}, x,y) 2.666666666666666666666667 >>> 1/(1-x)/(1-y) 2.666666666666666666666667 >>> hyper2d({'m':[1,2],'n':[3,4]}, {'m':[5],'n':[6]}, x,y) 4.164358531238938319669856 >>> hyp2f1(1,2,5,x)*hyp2f1(3,4,6,y) 4.164358531238938319669856 Some more series that can be done in closed form:: >>> hyper2d({'m':1,'n':1},{'m+n':1},x,y) 2.013417124712514809623881 >>> (exp(x)*x-exp(y)*y)/(x-y) 2.013417124712514809623881 Six of the 34 Horn functions, G1-G3 and H1-H3:: >>> from mpmath import * >>> mp.dps = 10; mp.pretty = True >>> x, y = 0.0625, 0.125 >>> a1,a2,b1,b2,c1,c2,d = 1.1,-1.2,-1.3,-1.4,1.5,-1.6,1.7 >>> hyper2d({'m+n':a1,'n-m':b1,'m-n':b2},{},x,y) # G1 1.139090746 >>> nsum(lambda m,n: rf(a1,m+n)*rf(b1,n-m)*rf(b2,m-n)*\ ... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf]) 1.139090746 >>> hyper2d({'m':a1,'n':a2,'n-m':b1,'m-n':b2},{},x,y) # G2 0.9503682696 >>> nsum(lambda m,n: rf(a1,m)*rf(a2,n)*rf(b1,n-m)*rf(b2,m-n)*\ ... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf]) 0.9503682696 >>> hyper2d({'2n-m':a1,'2m-n':a2},{},x,y) # G3 1.029372029 >>> nsum(lambda m,n: rf(a1,2*n-m)*rf(a2,2*m-n)*\ ... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf]) 1.029372029 >>> hyper2d({'m-n':a1,'m+n':b1,'n':c1},{'m':d},x,y) # H1 -1.605331256 >>> nsum(lambda m,n: rf(a1,m-n)*rf(b1,m+n)*rf(c1,n)/rf(d,m)*\ ... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf]) -1.605331256 >>> hyper2d({'m-n':a1,'m':b1,'n':[c1,c2]},{'m':d},x,y) # H2 -2.35405404 >>> nsum(lambda m,n: rf(a1,m-n)*rf(b1,m)*rf(c1,n)*rf(c2,n)/rf(d,m)*\ ... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf]) -2.35405404 >>> hyper2d({'2m+n':a1,'n':b1},{'m+n':c1},x,y) # H3 0.974479074 >>> nsum(lambda m,n: rf(a1,2*m+n)*rf(b1,n)/rf(c1,m+n)*\ ... x**m*y**n/fac(m)/fac(n), [0,inf], [0,inf]) 0.974479074 **References** 1. [SrivastavaKarlsson]_ 2. [Weisstein]_ http://mathworld.wolfram.com/HornFunction.html 3. [Weisstein]_ http://mathworld.wolfram.com/AppellHypergeometricFunction.html """ x = ctx.convert(x) y = ctx.convert(y) def parse(dct, key): args = dct.pop(key, []) try: args = list(args) except TypeError: args = [args] return [ctx.convert(arg) for arg in args] a_s = dict(a) b_s = dict(b) a_m = parse(a, 'm') a_n = parse(a, 'n') a_m_add_n = parse(a, 'm+n') a_m_sub_n = parse(a, 'm-n') a_n_sub_m = parse(a, 'n-m') a_2m_add_n = parse(a, '2m+n') a_2m_sub_n = parse(a, '2m-n') a_2n_sub_m = parse(a, '2n-m') b_m = parse(b, 'm') b_n = parse(b, 'n') b_m_add_n = parse(b, 'm+n') if a: raise ValueError("unsupported key: %r" % a.keys()[0]) if b: raise ValueError("unsupported key: %r" % b.keys()[0]) s = 0 outer = ctx.one m = ctx.mpf(0) ok_count = 0 prec = ctx.prec maxterms = kwargs.get('maxterms', 20*prec) try: ctx.prec += 10 tol = +ctx.eps while 1: inner_sign = 1 outer_sign = 1 inner_a = list(a_n) inner_b = list(b_n) outer_a = [a+m for a in a_m] outer_b = [b+m for b in b_m] # (a)_{m+n} = (a)_m (a+m)_n for a in a_m_add_n: a = a+m inner_a.append(a) outer_a.append(a) # (b)_{m+n} = (b)_m (b+m)_n for b in b_m_add_n: b = b+m inner_b.append(b) outer_b.append(b) # (a)_{n-m} = (a-m)_n / (a-m)_m for a in a_n_sub_m: inner_a.append(a-m) outer_b.append(a-m-1) # (a)_{m-n} = (-1)^(m+n) (1-a-m)_m / (1-a-m)_n for a in a_m_sub_n: inner_sign *= (-1) outer_sign *= (-1)**(m) inner_b.append(1-a-m) outer_a.append(-a-m) # (a)_{2m+n} = (a)_{2m} (a+2m)_n for a in a_2m_add_n: inner_a.append(a+2*m) outer_a.append((a+2*m)*(1+a+2*m)) # (a)_{2m-n} = (-1)^(2m+n) (1-a-2m)_{2m} / (1-a-2m)_n for a in a_2m_sub_n: inner_sign *= (-1) inner_b.append(1-a-2*m) outer_a.append((a+2*m)*(1+a+2*m)) # (a)_{2n-m} = 4^n ((a-m)/2)_n ((a-m+1)/2)_n / (a-m)_m for a in a_2n_sub_m: inner_sign *= 4 inner_a.append(0.5*(a-m)) inner_a.append(0.5*(a-m+1)) outer_b.append(a-m-1) inner = ctx.hyper(inner_a, inner_b, inner_sign*y, zeroprec=ctx.prec, **kwargs) term = outer * inner * outer_sign if abs(term) < tol: ok_count += 1 else: ok_count = 0 if ok_count >= 3 or not outer: break s += term for a in outer_a: outer *= a for b in outer_b: outer /= b m += 1 outer = outer * x / m if m > maxterms: raise ctx.NoConvergence("maxterms exceeded in hyper2d") finally: ctx.prec = prec return +s """ @defun def kampe_de_feriet(ctx,a,b,c,d,e,f,x,y,**kwargs): return ctx.hyper2d({'m+n':a,'m':b,'n':c}, {'m+n':d,'m':e,'n':f}, x,y, **kwargs) """ @defun def bihyper(ctx, a_s, b_s, z, **kwargs): r""" Evaluates the bilateral hypergeometric series .. math :: \,_AH_B(a_1, \ldots, a_k; b_1, \ldots, b_B; z) = \sum_{n=-\infty}^{\infty} \frac{(a_1)_n \ldots (a_A)_n} {(b_1)_n \ldots (b_B)_n} \, z^n where, for direct convergence, `A = B` and `|z| = 1`, although a regularized sum exists more generally by considering the bilateral series as a sum of two ordinary hypergeometric functions. In order for the series to make sense, none of the parameters may be integers. **Examples** The value of `\,_2H_2` at `z = 1` is given by Dougall's formula:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a,b,c,d = 0.5, 1.5, 2.25, 3.25 >>> bihyper([a,b],[c,d],1) -14.49118026212345786148847 >>> gammaprod([c,d,1-a,1-b,c+d-a-b-1],[c-a,d-a,c-b,d-b]) -14.49118026212345786148847 The regularized function `\,_1H_0` can be expressed as the sum of one `\,_2F_0` function and one `\,_1F_1` function:: >>> a = mpf(0.25) >>> z = mpf(0.75) >>> bihyper([a], [], z) (0.2454393389657273841385582 + 0.2454393389657273841385582j) >>> hyper([a,1],[],z) + (hyper([1],[1-a],-1/z)-1) (0.2454393389657273841385582 + 0.2454393389657273841385582j) >>> hyper([a,1],[],z) + hyper([1],[2-a],-1/z)/z/(a-1) (0.2454393389657273841385582 + 0.2454393389657273841385582j) **References** 1. [Slater]_ (chapter 6: "Bilateral Series", pp. 180-189) 2. [Wikipedia]_ http://en.wikipedia.org/wiki/Bilateral_hypergeometric_series """ z = ctx.convert(z) c_s = a_s + b_s p = len(a_s) q = len(b_s) if (p, q) == (0,0) or (p, q) == (1,1): return ctx.zero * z neg = (p-q) % 2 def h(*c_s): a_s = list(c_s[:p]) b_s = list(c_s[p:]) aa_s = [2-b for b in b_s] bb_s = [2-a for a in a_s] rp = [(-1)**neg * z] + [1-b for b in b_s] + [1-a for a in a_s] rc = [-1] + [1]*len(b_s) + [-1]*len(a_s) T1 = [], [], [], [], a_s + [1], b_s, z T2 = rp, rc, [], [], aa_s + [1], bb_s, (-1)**neg / z return T1, T2 return ctx.hypercomb(h, c_s, **kwargs) mpmath-1.1.0/mpmath/functions/orthogonal.py000066400000000000000000000373411340375245600210440ustar00rootroot00000000000000from .functions import defun, defun_wrapped def _hermite_param(ctx, n, z, parabolic_cylinder): """ Combined calculation of the Hermite polynomial H_n(z) (and its generalization to complex n) and the parabolic cylinder function D. """ n, ntyp = ctx._convert_param(n) z = ctx.convert(z) q = -ctx.mpq_1_2 # For re(z) > 0, 2F0 -- http://functions.wolfram.com/ # HypergeometricFunctions/HermiteHGeneral/06/02/0009/ # Otherwise, there is a reflection formula # 2F0 + http://functions.wolfram.com/HypergeometricFunctions/ # HermiteHGeneral/16/01/01/0006/ # # TODO: # An alternative would be to use # http://functions.wolfram.com/HypergeometricFunctions/ # HermiteHGeneral/06/02/0006/ # # Also, the 1F1 expansion # http://functions.wolfram.com/HypergeometricFunctions/ # HermiteHGeneral/26/01/02/0001/ # should probably be used for tiny z if not z: T1 = [2, ctx.pi], [n, 0.5], [], [q*(n-1)], [], [], 0 if parabolic_cylinder: T1[1][0] += q*n return T1, can_use_2f0 = ctx.isnpint(-n) or ctx.re(z) > 0 or \ (ctx.re(z) == 0 and ctx.im(z) > 0) expprec = ctx.prec*4 + 20 if parabolic_cylinder: u = ctx.fmul(ctx.fmul(z,z,prec=expprec), -0.25, exact=True) w = ctx.fmul(z, ctx.sqrt(0.5,prec=expprec), prec=expprec) else: w = z w2 = ctx.fmul(w, w, prec=expprec) rw2 = ctx.fdiv(1, w2, prec=expprec) nrw2 = ctx.fneg(rw2, exact=True) nw = ctx.fneg(w, exact=True) if can_use_2f0: T1 = [2, w], [n, n], [], [], [q*n, q*(n-1)], [], nrw2 terms = [T1] else: T1 = [2, nw], [n, n], [], [], [q*n, q*(n-1)], [], nrw2 T2 = [2, ctx.pi, nw], [n+2, 0.5, 1], [], [q*n], [q*(n-1)], [1-q], w2 terms = [T1,T2] # Multiply by prefactor for D_n if parabolic_cylinder: expu = ctx.exp(u) for i in range(len(terms)): terms[i][1][0] += q*n terms[i][0].append(expu) terms[i][1].append(1) return tuple(terms) @defun def hermite(ctx, n, z, **kwargs): return ctx.hypercomb(lambda: _hermite_param(ctx, n, z, 0), [], **kwargs) @defun def pcfd(ctx, n, z, **kwargs): r""" Gives the parabolic cylinder function in Whittaker's notation `D_n(z) = U(-n-1/2, z)` (see :func:`~mpmath.pcfu`). It solves the differential equation .. math :: y'' + \left(n + \frac{1}{2} - \frac{1}{4} z^2\right) y = 0. and can be represented in terms of Hermite polynomials (see :func:`~mpmath.hermite`) as .. math :: D_n(z) = 2^{-n/2} e^{-z^2/4} H_n\left(\frac{z}{\sqrt{2}}\right). **Plots** .. literalinclude :: /plots/pcfd.py .. image :: /plots/pcfd.png **Examples** >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> pcfd(0,0); pcfd(1,0); pcfd(2,0); pcfd(3,0) 1.0 0.0 -1.0 0.0 >>> pcfd(4,0); pcfd(-3,0) 3.0 0.6266570686577501256039413 >>> pcfd('1/2', 2+3j) (-5.363331161232920734849056 - 3.858877821790010714163487j) >>> pcfd(2, -10) 1.374906442631438038871515e-9 Verifying the differential equation:: >>> n = mpf(2.5) >>> y = lambda z: pcfd(n,z) >>> z = 1.75 >>> chop(diff(y,z,2) + (n+0.5-0.25*z**2)*y(z)) 0.0 Rational Taylor series expansion when `n` is an integer:: >>> taylor(lambda z: pcfd(5,z), 0, 7) [0.0, 15.0, 0.0, -13.75, 0.0, 3.96875, 0.0, -0.6015625] """ return ctx.hypercomb(lambda: _hermite_param(ctx, n, z, 1), [], **kwargs) @defun def pcfu(ctx, a, z, **kwargs): r""" Gives the parabolic cylinder function `U(a,z)`, which may be defined for `\Re(z) > 0` in terms of the confluent U-function (see :func:`~mpmath.hyperu`) by .. math :: U(a,z) = 2^{-\frac{1}{4}-\frac{a}{2}} e^{-\frac{1}{4} z^2} U\left(\frac{a}{2}+\frac{1}{4}, \frac{1}{2}, \frac{1}{2}z^2\right) or, for arbitrary `z`, .. math :: e^{-\frac{1}{4}z^2} U(a,z) = U(a,0) \,_1F_1\left(-\tfrac{a}{2}+\tfrac{1}{4}; \tfrac{1}{2}; -\tfrac{1}{2}z^2\right) + U'(a,0) z \,_1F_1\left(-\tfrac{a}{2}+\tfrac{3}{4}; \tfrac{3}{2}; -\tfrac{1}{2}z^2\right). **Examples** Connection to other functions:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> z = mpf(3) >>> pcfu(0.5,z) 0.03210358129311151450551963 >>> sqrt(pi/2)*exp(z**2/4)*erfc(z/sqrt(2)) 0.03210358129311151450551963 >>> pcfu(0.5,-z) 23.75012332835297233711255 >>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2)) 23.75012332835297233711255 >>> pcfu(0.5,-z) 23.75012332835297233711255 >>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2)) 23.75012332835297233711255 """ n, _ = ctx._convert_param(a) return ctx.pcfd(-n-ctx.mpq_1_2, z) @defun def pcfv(ctx, a, z, **kwargs): r""" Gives the parabolic cylinder function `V(a,z)`, which can be represented in terms of :func:`~mpmath.pcfu` as .. math :: V(a,z) = \frac{\Gamma(a+\tfrac{1}{2}) (U(a,-z)-\sin(\pi a) U(a,z)}{\pi}. **Examples** Wronskian relation between `U` and `V`:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a, z = 2, 3 >>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z) 0.7978845608028653558798921 >>> sqrt(2/pi) 0.7978845608028653558798921 >>> a, z = 2.5, 3 >>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z) 0.7978845608028653558798921 >>> a, z = 0.25, -1 >>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z) 0.7978845608028653558798921 >>> a, z = 2+1j, 2+3j >>> chop(pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)) 0.7978845608028653558798921 """ n, ntype = ctx._convert_param(a) z = ctx.convert(z) q = ctx.mpq_1_2 r = ctx.mpq_1_4 if ntype == 'Q' and ctx.isint(n*2): # Faster for half-integers def h(): jz = ctx.fmul(z, -1j, exact=True) T1terms = _hermite_param(ctx, -n-q, z, 1) T2terms = _hermite_param(ctx, n-q, jz, 1) for T in T1terms: T[0].append(1j) T[1].append(1) T[3].append(q-n) u = ctx.expjpi((q*n-r)) * ctx.sqrt(2/ctx.pi) for T in T2terms: T[0].append(u) T[1].append(1) return T1terms + T2terms v = ctx.hypercomb(h, [], **kwargs) if ctx._is_real_type(n) and ctx._is_real_type(z): v = ctx._re(v) return v else: def h(n): w = ctx.square_exp_arg(z, -0.25) u = ctx.square_exp_arg(z, 0.5) e = ctx.exp(w) l = [ctx.pi, q, ctx.exp(w)] Y1 = l, [-q, n*q+r, 1], [r-q*n], [], [q*n+r], [q], u Y2 = l + [z], [-q, n*q-r, 1, 1], [1-r-q*n], [], [q*n+1-r], [1+q], u c, s = ctx.cospi_sinpi(r+q*n) Y1[0].append(s) Y2[0].append(c) for Y in (Y1, Y2): Y[1].append(1) Y[3].append(q-n) return Y1, Y2 return ctx.hypercomb(h, [n], **kwargs) @defun def pcfw(ctx, a, z, **kwargs): r""" Gives the parabolic cylinder function `W(a,z)` defined in (DLMF 12.14). **Examples** Value at the origin:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a = mpf(0.25) >>> pcfw(a,0) 0.9722833245718180765617104 >>> power(2,-0.75)*sqrt(abs(gamma(0.25+0.5j*a)/gamma(0.75+0.5j*a))) 0.9722833245718180765617104 >>> diff(pcfw,(a,0),(0,1)) -0.5142533944210078966003624 >>> -power(2,-0.25)*sqrt(abs(gamma(0.75+0.5j*a)/gamma(0.25+0.5j*a))) -0.5142533944210078966003624 """ n, _ = ctx._convert_param(a) z = ctx.convert(z) def terms(): phi2 = ctx.arg(ctx.gamma(0.5 + ctx.j*n)) phi2 = (ctx.loggamma(0.5+ctx.j*n) - ctx.loggamma(0.5-ctx.j*n))/2j rho = ctx.pi/8 + 0.5*phi2 # XXX: cancellation computing k k = ctx.sqrt(1 + ctx.exp(2*ctx.pi*n)) - ctx.exp(ctx.pi*n) C = ctx.sqrt(k/2) * ctx.exp(0.25*ctx.pi*n) yield C * ctx.expj(rho) * ctx.pcfu(ctx.j*n, z*ctx.expjpi(-0.25)) yield C * ctx.expj(-rho) * ctx.pcfu(-ctx.j*n, z*ctx.expjpi(0.25)) v = ctx.sum_accurately(terms) if ctx._is_real_type(n) and ctx._is_real_type(z): v = ctx._re(v) return v """ Even/odd PCFs. Useful? @defun def pcfy1(ctx, a, z, **kwargs): a, _ = ctx._convert_param(n) z = ctx.convert(z) def h(): w = ctx.square_exp_arg(z) w1 = ctx.fmul(w, -0.25, exact=True) w2 = ctx.fmul(w, 0.5, exact=True) e = ctx.exp(w1) return [e], [1], [], [], [ctx.mpq_1_2*a+ctx.mpq_1_4], [ctx.mpq_1_2], w2 return ctx.hypercomb(h, [], **kwargs) @defun def pcfy2(ctx, a, z, **kwargs): a, _ = ctx._convert_param(n) z = ctx.convert(z) def h(): w = ctx.square_exp_arg(z) w1 = ctx.fmul(w, -0.25, exact=True) w2 = ctx.fmul(w, 0.5, exact=True) e = ctx.exp(w1) return [e, z], [1, 1], [], [], [ctx.mpq_1_2*a+ctx.mpq_3_4], \ [ctx.mpq_3_2], w2 return ctx.hypercomb(h, [], **kwargs) """ @defun_wrapped def gegenbauer(ctx, n, a, z, **kwargs): # Special cases: a+0.5, a*2 poles if ctx.isnpint(a): return 0*(z+n) if ctx.isnpint(a+0.5): # TODO: something else is required here # E.g.: gegenbauer(-2, -0.5, 3) == -12 if ctx.isnpint(n+1): raise NotImplementedError("Gegenbauer function with two limits") def h(a): a2 = 2*a T = [], [], [n+a2], [n+1, a2], [-n, n+a2], [a+0.5], 0.5*(1-z) return [T] return ctx.hypercomb(h, [a], **kwargs) def h(n): a2 = 2*a T = [], [], [n+a2], [n+1, a2], [-n, n+a2], [a+0.5], 0.5*(1-z) return [T] return ctx.hypercomb(h, [n], **kwargs) @defun_wrapped def jacobi(ctx, n, a, b, x, **kwargs): if not ctx.isnpint(a): def h(n): return (([], [], [a+n+1], [n+1, a+1], [-n, a+b+n+1], [a+1], (1-x)*0.5),) return ctx.hypercomb(h, [n], **kwargs) if not ctx.isint(b): def h(n, a): return (([], [], [-b], [n+1, -b-n], [-n, a+b+n+1], [b+1], (x+1)*0.5),) return ctx.hypercomb(h, [n, a], **kwargs) # XXX: determine appropriate limit return ctx.binomial(n+a,n) * ctx.hyp2f1(-n,1+n+a+b,a+1,(1-x)/2, **kwargs) @defun_wrapped def laguerre(ctx, n, a, z, **kwargs): # XXX: limits, poles #if ctx.isnpint(n): # return 0*(a+z) def h(a): return (([], [], [a+n+1], [a+1, n+1], [-n], [a+1], z),) return ctx.hypercomb(h, [a], **kwargs) @defun_wrapped def legendre(ctx, n, x, **kwargs): if ctx.isint(n): n = int(n) # Accuracy near zeros if (n + (n < 0)) & 1: if not x: return x mag = ctx.mag(x) if mag < -2*ctx.prec-10: return x if mag < -5: ctx.prec += -mag return ctx.hyp2f1(-n,n+1,1,(1-x)/2, **kwargs) @defun def legenp(ctx, n, m, z, type=2, **kwargs): # Legendre function, 1st kind n = ctx.convert(n) m = ctx.convert(m) # Faster if not m: return ctx.legendre(n, z, **kwargs) # TODO: correct evaluation at singularities if type == 2: def h(n,m): g = m*0.5 T = [1+z, 1-z], [g, -g], [], [1-m], [-n, n+1], [1-m], 0.5*(1-z) return (T,) return ctx.hypercomb(h, [n,m], **kwargs) if type == 3: def h(n,m): g = m*0.5 T = [z+1, z-1], [g, -g], [], [1-m], [-n, n+1], [1-m], 0.5*(1-z) return (T,) return ctx.hypercomb(h, [n,m], **kwargs) raise ValueError("requires type=2 or type=3") @defun def legenq(ctx, n, m, z, type=2, **kwargs): # Legendre function, 2nd kind n = ctx.convert(n) m = ctx.convert(m) z = ctx.convert(z) if z in (1, -1): #if ctx.isint(m): # return ctx.nan #return ctx.inf # unsigned return ctx.nan if type == 2: def h(n, m): cos, sin = ctx.cospi_sinpi(m) s = 2 * sin / ctx.pi c = cos a = 1+z b = 1-z u = m/2 w = (1-z)/2 T1 = [s, c, a, b], [-1, 1, u, -u], [], [1-m], \ [-n, n+1], [1-m], w T2 = [-s, a, b], [-1, -u, u], [n+m+1], [n-m+1, m+1], \ [-n, n+1], [m+1], w return T1, T2 return ctx.hypercomb(h, [n, m], **kwargs) if type == 3: # The following is faster when there only is a single series # Note: not valid for -1 < z < 0 (?) if abs(z) > 1: def h(n, m): T1 = [ctx.expjpi(m), 2, ctx.pi, z, z-1, z+1], \ [1, -n-1, 0.5, -n-m-1, 0.5*m, 0.5*m], \ [n+m+1], [n+1.5], \ [0.5*(2+n+m), 0.5*(1+n+m)], [n+1.5], z**(-2) return [T1] return ctx.hypercomb(h, [n, m], **kwargs) else: # not valid for 1 < z < inf ? def h(n, m): s = 2 * ctx.sinpi(m) / ctx.pi c = ctx.expjpi(m) a = 1+z b = z-1 u = m/2 w = (1-z)/2 T1 = [s, c, a, b], [-1, 1, u, -u], [], [1-m], \ [-n, n+1], [1-m], w T2 = [-s, c, a, b], [-1, 1, -u, u], [n+m+1], [n-m+1, m+1], \ [-n, n+1], [m+1], w return T1, T2 return ctx.hypercomb(h, [n, m], **kwargs) raise ValueError("requires type=2 or type=3") @defun_wrapped def chebyt(ctx, n, x, **kwargs): if (not x) and ctx.isint(n) and int(ctx._re(n)) % 2 == 1: return x * 0 return ctx.hyp2f1(-n,n,(1,2),(1-x)/2, **kwargs) @defun_wrapped def chebyu(ctx, n, x, **kwargs): if (not x) and ctx.isint(n) and int(ctx._re(n)) % 2 == 1: return x * 0 return (n+1) * ctx.hyp2f1(-n, n+2, (3,2), (1-x)/2, **kwargs) @defun def spherharm(ctx, l, m, theta, phi, **kwargs): l = ctx.convert(l) m = ctx.convert(m) theta = ctx.convert(theta) phi = ctx.convert(phi) l_isint = ctx.isint(l) l_natural = l_isint and l >= 0 m_isint = ctx.isint(m) if l_isint and l < 0 and m_isint: return ctx.spherharm(-(l+1), m, theta, phi, **kwargs) if theta == 0 and m_isint and m < 0: return ctx.zero * 1j if l_natural and m_isint: if abs(m) > l: return ctx.zero * 1j # http://functions.wolfram.com/Polynomials/ # SphericalHarmonicY/26/01/02/0004/ def h(l,m): absm = abs(m) C = [-1, ctx.expj(m*phi), (2*l+1)*ctx.fac(l+absm)/ctx.pi/ctx.fac(l-absm), ctx.sin(theta)**2, ctx.fac(absm), 2] P = [0.5*m*(ctx.sign(m)+1), 1, 0.5, 0.5*absm, -1, -absm-1] return ((C, P, [], [], [absm-l, l+absm+1], [absm+1], ctx.sin(0.5*theta)**2),) else: # http://functions.wolfram.com/HypergeometricFunctions/ # SphericalHarmonicYGeneral/26/01/02/0001/ def h(l,m): if ctx.isnpint(l-m+1) or ctx.isnpint(l+m+1) or ctx.isnpint(1-m): return (([0], [-1], [], [], [], [], 0),) cos, sin = ctx.cos_sin(0.5*theta) C = [0.5*ctx.expj(m*phi), (2*l+1)/ctx.pi, ctx.gamma(l-m+1), ctx.gamma(l+m+1), cos**2, sin**2] P = [1, 0.5, 0.5, -0.5, 0.5*m, -0.5*m] return ((C, P, [], [1-m], [-l,l+1], [1-m], sin**2),) return ctx.hypercomb(h, [l,m], **kwargs) mpmath-1.1.0/mpmath/functions/qfunctions.py000066400000000000000000000167211340375245600210600ustar00rootroot00000000000000from .functions import defun, defun_wrapped @defun def qp(ctx, a, q=None, n=None, **kwargs): r""" Evaluates the q-Pochhammer symbol (or q-rising factorial) .. math :: (a; q)_n = \prod_{k=0}^{n-1} (1-a q^k) where `n = \infty` is permitted if `|q| < 1`. Called with two arguments, ``qp(a,q)`` computes `(a;q)_{\infty}`; with a single argument, ``qp(q)`` computes `(q;q)_{\infty}`. The special case .. math :: \phi(q) = (q; q)_{\infty} = \prod_{k=1}^{\infty} (1-q^k) = \sum_{k=-\infty}^{\infty} (-1)^k q^{(3k^2-k)/2} is also known as the Euler function, or (up to a factor `q^{-1/24}`) the Dedekind eta function. **Examples** If `n` is a positive integer, the function amounts to a finite product:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> qp(2,3,5) -725305.0 >>> fprod(1-2*3**k for k in range(5)) -725305.0 >>> qp(2,3,0) 1.0 Complex arguments are allowed:: >>> qp(2-1j, 0.75j) (0.4628842231660149089976379 + 4.481821753552703090628793j) The regular Pochhammer symbol `(a)_n` is obtained in the following limit as `q \to 1`:: >>> a, n = 4, 7 >>> limit(lambda q: qp(q**a,q,n) / (1-q)**n, 1) 604800.0 >>> rf(a,n) 604800.0 The Taylor series of the reciprocal Euler function gives the partition function `P(n)`, i.e. the number of ways of writing `n` as a sum of positive integers:: >>> taylor(lambda q: 1/qp(q), 0, 10) [1.0, 1.0, 2.0, 3.0, 5.0, 7.0, 11.0, 15.0, 22.0, 30.0, 42.0] Special values include:: >>> qp(0) 1.0 >>> findroot(diffun(qp), -0.4) # location of maximum -0.4112484791779547734440257 >>> qp(_) 1.228348867038575112586878 The q-Pochhammer symbol is related to the Jacobi theta functions. For example, the following identity holds:: >>> q = mpf(0.5) # arbitrary >>> qp(q) 0.2887880950866024212788997 >>> root(3,-2)*root(q,-24)*jtheta(2,pi/6,root(q,6)) 0.2887880950866024212788997 """ a = ctx.convert(a) if n is None: n = ctx.inf else: n = ctx.convert(n) if n < 0: raise ValueError("n cannot be negative") if q is None: q = a else: q = ctx.convert(q) if n == 0: return ctx.one + 0*(a+q) infinite = (n == ctx.inf) same = (a == q) if infinite: if abs(q) >= 1: if same and (q == -1 or q == 1): return ctx.zero * q raise ValueError("q-function only defined for |q| < 1") elif q == 0: return ctx.one - a maxterms = kwargs.get('maxterms', 50*ctx.prec) if infinite and same: # Euler's pentagonal theorem def terms(): t = 1 yield t k = 1 x1 = q x2 = q**2 while 1: yield (-1)**k * x1 yield (-1)**k * x2 x1 *= q**(3*k+1) x2 *= q**(3*k+2) k += 1 if k > maxterms: raise ctx.NoConvergence return ctx.sum_accurately(terms) # return ctx.nprod(lambda k: 1-a*q**k, [0,n-1]) def factors(): k = 0 r = ctx.one while 1: yield 1 - a*r r *= q k += 1 if k >= n: return if k > maxterms: raise ctx.NoConvergence return ctx.mul_accurately(factors) @defun_wrapped def qgamma(ctx, z, q, **kwargs): r""" Evaluates the q-gamma function .. math :: \Gamma_q(z) = \frac{(q; q)_{\infty}}{(q^z; q)_{\infty}} (1-q)^{1-z}. **Examples** Evaluation for real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> qgamma(4,0.75) 4.046875 >>> qgamma(6,6) 121226245.0 >>> qgamma(3+4j, 0.5j) (0.1663082382255199834630088 + 0.01952474576025952984418217j) The q-gamma function satisfies a functional equation similar to that of the ordinary gamma function:: >>> q = mpf(0.25) >>> z = mpf(2.5) >>> qgamma(z+1,q) 1.428277424823760954685912 >>> (1-q**z)/(1-q)*qgamma(z,q) 1.428277424823760954685912 """ if abs(q) > 1: return ctx.qgamma(z,1/q)*q**((z-2)*(z-1)*0.5) return ctx.qp(q, q, None, **kwargs) / \ ctx.qp(q**z, q, None, **kwargs) * (1-q)**(1-z) @defun_wrapped def qfac(ctx, z, q, **kwargs): r""" Evaluates the q-factorial, .. math :: [n]_q! = (1+q)(1+q+q^2)\cdots(1+q+\cdots+q^{n-1}) or more generally .. math :: [z]_q! = \frac{(q;q)_z}{(1-q)^z}. **Examples** >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> qfac(0,0) 1.0 >>> qfac(4,3) 2080.0 >>> qfac(5,6) 121226245.0 >>> qfac(1+1j, 2+1j) (0.4370556551322672478613695 + 0.2609739839216039203708921j) """ if ctx.isint(z) and ctx._re(z) > 0: n = int(ctx._re(z)) return ctx.qp(q, q, n, **kwargs) / (1-q)**n return ctx.qgamma(z+1, q, **kwargs) @defun def qhyper(ctx, a_s, b_s, q, z, **kwargs): r""" Evaluates the basic hypergeometric series or hypergeometric q-series .. math :: \,_r\phi_s \left[\begin{matrix} a_1 & a_2 & \ldots & a_r \\ b_1 & b_2 & \ldots & b_s \end{matrix} ; q,z \right] = \sum_{n=0}^\infty \frac{(a_1;q)_n, \ldots, (a_r;q)_n} {(b_1;q)_n, \ldots, (b_s;q)_n} \left((-1)^n q^{n\choose 2}\right)^{1+s-r} \frac{z^n}{(q;q)_n} where `(a;q)_n` denotes the q-Pochhammer symbol (see :func:`~mpmath.qp`). **Examples** Evaluation works for real and complex arguments:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> qhyper([0.5], [2.25], 0.25, 4) -0.1975849091263356009534385 >>> qhyper([0.5], [2.25], 0.25-0.25j, 4) (2.806330244925716649839237 + 3.568997623337943121769938j) >>> qhyper([1+j], [2,3+0.5j], 0.25, 3+4j) (9.112885171773400017270226 - 1.272756997166375050700388j) Comparing with a summation of the defining series, using :func:`~mpmath.nsum`:: >>> b, q, z = 3, 0.25, 0.5 >>> qhyper([], [b], q, z) 0.6221136748254495583228324 >>> nsum(lambda n: z**n / qp(q,q,n)/qp(b,q,n) * q**(n*(n-1)), [0,inf]) 0.6221136748254495583228324 """ #a_s = [ctx._convert_param(a)[0] for a in a_s] #b_s = [ctx._convert_param(b)[0] for b in b_s] #q = ctx._convert_param(q)[0] a_s = [ctx.convert(a) for a in a_s] b_s = [ctx.convert(b) for b in b_s] q = ctx.convert(q) z = ctx.convert(z) r = len(a_s) s = len(b_s) d = 1+s-r maxterms = kwargs.get('maxterms', 50*ctx.prec) def terms(): t = ctx.one yield t qk = 1 k = 0 x = 1 while 1: for a in a_s: p = 1 - a*qk t *= p for b in b_s: p = 1 - b*qk if not p: raise ValueError t /= p t *= z x *= (-1)**d * qk ** d qk *= q t /= (1 - qk) k += 1 yield t * x if k > maxterms: raise ctx.NoConvergence return ctx.sum_accurately(terms) mpmath-1.1.0/mpmath/functions/rszeta.py000066400000000000000000001321501340375245600201720ustar00rootroot00000000000000""" --------------------------------------------------------------------- .. sectionauthor:: Juan Arias de Reyna This module implements zeta-related functions using the Riemann-Siegel expansion: zeta_offline(s,k=0) * coef(J, eps): Need in the computation of Rzeta(s,k) * Rzeta_simul(s, der=0) computes Rzeta^(k)(s) and Rzeta^(k)(1-s) simultaneously for 0 <= k <= der. Used by zeta_offline and z_offline * Rzeta_set(s, derivatives) computes Rzeta^(k)(s) for given derivatives, used by z_half(t,k) and zeta_half * z_offline(w,k): Z(w) and its derivatives of order k <= 4 * z_half(t,k): Z(t) (Riemann Siegel function) and its derivatives of order k <= 4 * zeta_offline(s): zeta(s) and its derivatives of order k<= 4 * zeta_half(1/2+it,k): zeta(s) and its derivatives of order k<= 4 * rs_zeta(s,k=0) Computes zeta^(k)(s) Unifies zeta_half and zeta_offline * rs_z(w,k=0) Computes Z^(k)(w) Unifies z_offline and z_half ---------------------------------------------------------------------- This program uses Riemann-Siegel expansion even to compute zeta(s) on points s = sigma + i t with sigma arbitrary not necessarily equal to 1/2. It is founded on a new deduction of the formula, with rigorous and sharp bounds for the terms and rest of this expansion. More information on the papers: J. Arias de Reyna, High Precision Computation of Riemann's Zeta Function by the Riemann-Siegel Formula I, II We refer to them as I, II. In them we shall find detailed explanation of all the procedure. The program uses Riemann-Siegel expansion. This is useful when t is big, ( say t > 10000 ). The precision is limited, roughly it can compute zeta(sigma+it) with an error less than exp(-c t) for some constant c depending on sigma. The program gives an error when the Riemann-Siegel formula can not compute to the wanted precision. """ import math class RSCache(object): def __init__(ctx): ctx._rs_cache = [0, 10, {}, {}] from .functions import defun #-------------------------------------------------------------------------------# # # # coef(ctx, J, eps, _cache=[0, 10, {} ] ) # # # #-------------------------------------------------------------------------------# # This function computes the coefficients c[n] defined on (I, equation (47)) # but see also (II, section 3.14). # # Since these coefficients are very difficult to compute we save the values # in a cache. So if we compute several values of the functions Rzeta(s) for # near values of s, we do not recompute these coefficients. # # c[n] are the Taylor coefficients of the function: # # F(z):= (exp(pi*j*(z*z/2+3/8))-j* sqrt(2) cos(pi*z/2))/(2*cos(pi *z)) # # def _coef(ctx, J, eps): r""" Computes the coefficients `c_n` for `0\le n\le 2J` with error less than eps **Definition** The coefficients c_n are defined by .. math :: \begin{equation} F(z)=\frac{e^{\pi i \bigl(\frac{z^2}{2}+\frac38\bigr)}-i\sqrt{2}\cos\frac{\pi}{2}z}{2\cos\pi z}=\sum_{n=0}^\infty c_{2n} z^{2n} \end{equation} they are computed applying the relation .. math :: \begin{multline} c_{2n}=-\frac{i}{\sqrt{2}}\Bigl(\frac{\pi}{2}\Bigr)^{2n} \sum_{k=0}^n\frac{(-1)^k}{(2k)!} 2^{2n-2k}\frac{(-1)^{n-k}E_{2n-2k}}{(2n-2k)!}+\\ +e^{3\pi i/8}\sum_{j=0}^n(-1)^j\frac{ E_{2j}}{(2j)!}\frac{i^{n-j}\pi^{n+j}}{(n-j)!2^{n-j+1}}. \end{multline} """ newJ = J+2 # compute more coefficients that are needed neweps6 = eps/2. # compute with a slight more precision that are needed # PREPARATION FOR THE COMPUTATION OF V(N) AND W(N) # See II Section 3.16 # # Computing the exponent wpvw of the error II equation (81) wpvw = max(ctx.mag(10*(newJ+3)), 4*newJ+5-ctx.mag(neweps6)) # Preparation of Euler numbers (we need until the 2*RS_NEWJ) E = ctx._eulernum(2*newJ) # Now we have in the cache all the needed Euler numbers. # # Computing the powers of pi # # We need to compute the powers pi**n for 1<= n <= 2*J # with relative error less than 2**(-wpvw) # it is easy to show that this is obtained # taking wppi as the least d with # 2**d>40*J and 2**d> 4.24 *newJ + 2**wpvw # In II Section 3.9 we need also that # wppi > wptcoef[0], and that the powers # here computed 0<= k <= 2*newJ are more # than those needed there that are 2*L-2. # so we need J >= L this will be checked # before computing tcoef[] wppi = max(ctx.mag(40*newJ), ctx.mag(newJ)+3 +wpvw) ctx.prec = wppi pipower = {} pipower[0] = ctx.one pipower[1] = ctx.pi for n in range(2,2*newJ+1): pipower[n] = pipower[n-1]*ctx.pi # COMPUTING THE COEFFICIENTS v(n) AND w(n) # see II equation (61) and equations (81) and (82) ctx.prec = wpvw+2 v={} w={} for n in range(0,newJ+1): va = (-1)**n * ctx._eulernum(2*n) va = ctx.mpf(va)/ctx.fac(2*n) v[n]=va*pipower[2*n] for n in range(0,2*newJ+1): wa = ctx.one/ctx.fac(n) wa=wa/(2**n) w[n]=wa*pipower[n] # COMPUTATION OF THE CONVOLUTIONS RS_P1 AND RS_P2 # See II Section 3.16 ctx.prec = 15 wpp1a = 9 - ctx.mag(neweps6) P1 = {} for n in range(0,newJ+1): ctx.prec = 15 wpp1 = max(ctx.mag(10*(n+4)),4*n+wpp1a) ctx.prec = wpp1 sump = 0 for k in range(0,n+1): sump += ((-1)**k) * v[k]*w[2*n-2*k] P1[n]=((-1)**(n+1))*ctx.j*sump P2={} for n in range(0,newJ+1): ctx.prec = 15 wpp2 = max(ctx.mag(10*(n+4)),4*n+wpp1a) ctx.prec = wpp2 sump = 0 for k in range(0,n+1): sump += (ctx.j**(n-k)) * v[k]*w[n-k] P2[n]=sump # COMPUTING THE COEFFICIENTS c[2n] # See II Section 3.14 ctx.prec = 15 wpc0 = 5 - ctx.mag(neweps6) wpc = max(6,4*newJ+wpc0) ctx.prec = wpc mu = ctx.sqrt(ctx.mpf('2'))/2 nu = ctx.expjpi(3./8)/2 c={} for n in range(0,newJ): ctx.prec = 15 wpc = max(6,4*n+wpc0) ctx.prec = wpc c[2*n] = mu*P1[n]+nu*P2[n] for n in range(1,2*newJ,2): c[n] = 0 return [newJ, neweps6, c, pipower] def coef(ctx, J, eps): _cache = ctx._rs_cache if J <= _cache[0] and eps >= _cache[1]: return _cache[2], _cache[3] orig = ctx._mp.prec try: data = _coef(ctx._mp, J, eps) finally: ctx._mp.prec = orig if ctx is not ctx._mp: data[2] = dict((k,ctx.convert(v)) for (k,v) in data[2].items()) data[3] = dict((k,ctx.convert(v)) for (k,v) in data[3].items()) ctx._rs_cache[:] = data return ctx._rs_cache[2], ctx._rs_cache[3] #-------------------------------------------------------------------------------# # # # Rzeta_simul(s,k=0) # # # #-------------------------------------------------------------------------------# # This function return a list with the values: # Rzeta(sigma+it), conj(Rzeta(1-sigma+it)),Rzeta'(sigma+it), conj(Rzeta'(1-sigma+it)), # .... , Rzeta^{(k)}(sigma+it), conj(Rzeta^{(k)}(1-sigma+it)) # # Useful to compute the function zeta(s) and Z(w) or its derivatives. # def aux_M_Fp(ctx, xA, xeps4, a, xB1, xL): # COMPUTING M NUMBER OF DERIVATIVES Fp[m] TO COMPUTE # See II Section 3.11 equations (47) and (48) aux1 = 126.0657606*xA/xeps4 # 126.06.. = 316/sqrt(2*pi) aux1 = ctx.ln(aux1) aux2 = (2*ctx.ln(ctx.pi)+ctx.ln(xB1)+ctx.ln(a))/3 -ctx.ln(2*ctx.pi)/2 m = 3*xL-3 aux3= (ctx.loggamma(m+1)-ctx.loggamma(m/3.0+2))/2 -ctx.loggamma((m+1)/2.) while((aux1 < m*aux2+ aux3)and (m>1)): m = m - 1 aux3 = (ctx.loggamma(m+1)-ctx.loggamma(m/3.0+2))/2 -ctx.loggamma((m+1)/2.) xM = m return xM def aux_J_needed(ctx, xA, xeps4, a, xB1, xM): # DETERMINATION OF J THE NUMBER OF TERMS NEEDED # IN THE TAYLOR SERIES OF F. # See II Section 3.11 equation (49)) # Only determine one h1 = xeps4/(632*xA) h2 = xB1*a * 126.31337419529260248 # = pi^2*e^2*sqrt(3) h2 = h1 * ctx.power((h2/xM**2),(xM-1)/3) / xM h3 = min(h1,h2) return h3 def Rzeta_simul(ctx, s, der=0): # First we take the value of ctx.prec wpinitial = ctx.prec # INITIALIZATION # Take the real and imaginary part of s t = ctx._im(s) xsigma = ctx._re(s) ysigma = 1 - xsigma # Now compute several parameter that appear on the program ctx.prec = 15 a = ctx.sqrt(t/(2*ctx.pi)) xasigma = a ** xsigma yasigma = a ** ysigma # We need a simple bound A1 < asigma (see II Section 3.1 and 3.3) xA1=ctx.power(2, ctx.mag(xasigma)-1) yA1=ctx.power(2, ctx.mag(yasigma)-1) # We compute various epsilon's (see II end of Section 3.1) eps = ctx.power(2, -wpinitial) eps1 = eps/6. xeps2 = eps * xA1/3. yeps2 = eps * yA1/3. # COMPUTING SOME COEFFICIENTS THAT DEPENDS # ON sigma # constant b and c (see I Theorem 2 formula (26) ) # coefficients A and B1 (see I Section 6.1 equation (50)) # # here we not need high precision ctx.prec = 15 if xsigma > 0: xb = 2. xc = math.pow(9,xsigma)/4.44288 # 4.44288 =(math.sqrt(2)*math.pi) xA = math.pow(9,xsigma) xB1 = 1 else: xb = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi ) xc = math.pow(2,-xsigma)/4.44288 xA = math.pow(2,-xsigma) xB1 = 1.10789 # = 2*sqrt(1-log(2)) if(ysigma > 0): yb = 2. yc = math.pow(9,ysigma)/4.44288 # 4.44288 =(math.sqrt(2)*math.pi) yA = math.pow(9,ysigma) yB1 = 1 else: yb = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi ) yc = math.pow(2,-ysigma)/4.44288 yA = math.pow(2,-ysigma) yB1 = 1.10789 # = 2*sqrt(1-log(2)) # COMPUTING L THE NUMBER OF TERMS NEEDED IN THE RIEMANN-SIEGEL # CORRECTION # See II Section 3.2 ctx.prec = 15 xL = 1 while 3*xc*ctx.gamma(xL*0.5) * ctx.power(xb*a,-xL) >= xeps2: xL = xL+1 xL = max(2,xL) yL = 1 while 3*yc*ctx.gamma(yL*0.5) * ctx.power(yb*a,-yL) >= yeps2: yL = yL+1 yL = max(2,yL) # The number L has to satify some conditions. # If not RS can not compute Rzeta(s) with the prescribed precision # (see II, Section 3.2 condition (20) ) and # (II, Section 3.3 condition (22) ). Also we have added # an additional technical condition in Section 3.17 Proposition 17 if ((3*xL >= 2*a*a/25.) or (3*xL+2+xsigma<0) or (abs(xsigma) > a/2.) or \ (3*yL >= 2*a*a/25.) or (3*yL+2+ysigma<0) or (abs(ysigma) > a/2.)): ctx.prec = wpinitial raise NotImplementedError("Riemann-Siegel can not compute with such precision") # We take the maximum of the two values L = max(xL, yL) # INITIALIZATION (CONTINUATION) # # eps3 is the constant defined on (II, Section 3.5 equation (27) ) # each term of the RS correction must be computed with error <= eps3 xeps3 = xeps2/(4*xL) yeps3 = yeps2/(4*yL) # eps4 is defined on (II Section 3.6 equation (30) ) # each component of the formula (II Section 3.6 equation (29) ) # must be computed with error <= eps4 xeps4 = xeps3/(3*xL) yeps4 = yeps3/(3*yL) # COMPUTING M NUMBER OF DERIVATIVES Fp[m] TO COMPUTE xM = aux_M_Fp(ctx, xA, xeps4, a, xB1, xL) yM = aux_M_Fp(ctx, yA, yeps4, a, yB1, yL) M = max(xM, yM) # COMPUTING NUMBER OF TERMS J NEEDED h3 = aux_J_needed(ctx, xA, xeps4, a, xB1, xM) h4 = aux_J_needed(ctx, yA, yeps4, a, yB1, yM) h3 = min(h3,h4) J = 12 jvalue = (2*ctx.pi)**J / ctx.gamma(J+1) while jvalue > h3: J = J+1 jvalue = (2*ctx.pi)*jvalue/J # COMPUTING eps5[m] for 1 <= m <= 21 # See II Section 10 equation (43) # We choose the minimum of the two possibilities eps5={} xforeps5 = math.pi*math.pi*xB1*a yforeps5 = math.pi*math.pi*yB1*a for m in range(0,22): xaux1 = math.pow(xforeps5, m/3)/(316.*xA) yaux1 = math.pow(yforeps5, m/3)/(316.*yA) aux1 = min(xaux1, yaux1) aux2 = ctx.gamma(m+1)/ctx.gamma(m/3.0+0.5) aux2 = math.sqrt(aux2) eps5[m] = (aux1*aux2*min(xeps4,yeps4)) # COMPUTING wpfp # See II Section 3.13 equation (59) twenty = min(3*L-3, 21)+1 aux = 6812*J wpfp = ctx.mag(44*J) for m in range(0,twenty): wpfp = max(wpfp, ctx.mag(aux*ctx.gamma(m+1)/eps5[m])) # COMPUTING N AND p # See II Section ctx.prec = wpfp + ctx.mag(t)+20 a = ctx.sqrt(t/(2*ctx.pi)) N = ctx.floor(a) p = 1-2*(a-N) # now we get a rounded version of p # to the precision wpfp # this possibly is not necessary num=ctx.floor(p*(ctx.mpf('2')**wpfp)) difference = p * (ctx.mpf('2')**wpfp)-num if (difference < 0.5): num = num else: num = num+1 p = ctx.convert(num * (ctx.mpf('2')**(-wpfp))) # COMPUTING THE COEFFICIENTS c[n] = cc[n] # We shall use the notation cc[n], since there is # a constant that is called c # See II Section 3.14 # We compute the coefficients and also save then in a # cache. The bulk of the computation is passed to # the function coef() # # eps6 is defined in II Section 3.13 equation (58) eps6 = ctx.power(ctx.convert(2*ctx.pi), J)/(ctx.gamma(J+1)*3*J) # Now we compute the coefficients cc = {} cont = {} cont, pipowers = coef(ctx, J, eps6) cc=cont.copy() # we need a copy since we have to change his values. Fp={} # this is the adequate locus of this for n in range(M, 3*L-2): Fp[n] = 0 Fp={} ctx.prec = wpfp for m in range(0,M+1): sumP = 0 for k in range(2*J-m-1,-1,-1): sumP = (sumP * p)+ cc[k] Fp[m] = sumP # preparation of the new coefficients for k in range(0,2*J-m-1): cc[k] = (k+1)* cc[k+1] # COMPUTING THE NUMBERS xd[u,n,k], yd[u,n,k] # See II Section 3.17 # # First we compute the working precisions xwpd[k] # Se II equation (92) xwpd={} d1 = max(6,ctx.mag(40*L*L)) xd2 = 13+ctx.mag((1+abs(xsigma))*xA)-ctx.mag(xeps4)-1 xconst = ctx.ln(8/(ctx.pi*ctx.pi*a*a*xB1*xB1)) /2 for n in range(0,L): xd3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*xconst)+xd2 xwpd[n]=max(xd3,d1) # procedure of II Section 3.17 ctx.prec = xwpd[1]+10 xpsigma = 1-(2*xsigma) xd = {} xd[0,0,-2]=0; xd[0,0,-1]=0; xd[0,0,0]=1; xd[0,0,1]=0 xd[0,-1,-2]=0; xd[0,-1,-1]=0; xd[0,-1,0]=1; xd[0,-1,1]=0 for n in range(1,L): ctx.prec = xwpd[n]+10 for k in range(0,3*n//2+1): m = 3*n-2*k if(m!=0): m1 = ctx.one/m c1= m1/4 c2=(xpsigma*m1)/2 c3=-(m+1) xd[0,n,k]=c3*xd[0,n-1,k-2]+c1*xd[0,n-1,k]+c2*xd[0,n-1,k-1] else: xd[0,n,k]=0 for r in range(0,k): add=xd[0,n,r]*(ctx.mpf('1.0')*ctx.fac(2*k-2*r)/ctx.fac(k-r)) xd[0,n,k] -= ((-1)**(k-r))*add xd[0,n,-2]=0; xd[0,n,-1]=0; xd[0,n,3*n//2+1]=0 for mu in range(-2,der+1): for n in range(-2,L): for k in range(-3,max(1,3*n//2+2)): if( (mu<0)or (n<0) or(k<0)or (k>3*n//2)): xd[mu,n,k] = 0 for mu in range(1,der+1): for n in range(0,L): ctx.prec = xwpd[n]+10 for k in range(0,3*n//2+1): aux=(2*mu-2)*xd[mu-2,n-2,k-3]+2*(xsigma+n-2)*xd[mu-1,n-2,k-3] xd[mu,n,k] = aux - xd[mu-1,n-1,k-1] # Now we compute the working precisions ywpd[k] # Se II equation (92) ywpd={} d1 = max(6,ctx.mag(40*L*L)) yd2 = 13+ctx.mag((1+abs(ysigma))*yA)-ctx.mag(yeps4)-1 yconst = ctx.ln(8/(ctx.pi*ctx.pi*a*a*yB1*yB1)) /2 for n in range(0,L): yd3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*yconst)+yd2 ywpd[n]=max(yd3,d1) # procedure of II Section 3.17 ctx.prec = ywpd[1]+10 ypsigma = 1-(2*ysigma) yd = {} yd[0,0,-2]=0; yd[0,0,-1]=0; yd[0,0,0]=1; yd[0,0,1]=0 yd[0,-1,-2]=0; yd[0,-1,-1]=0; yd[0,-1,0]=1; yd[0,-1,1]=0 for n in range(1,L): ctx.prec = ywpd[n]+10 for k in range(0,3*n//2+1): m = 3*n-2*k if(m!=0): m1 = ctx.one/m c1= m1/4 c2=(ypsigma*m1)/2 c3=-(m+1) yd[0,n,k]=c3*yd[0,n-1,k-2]+c1*yd[0,n-1,k]+c2*yd[0,n-1,k-1] else: yd[0,n,k]=0 for r in range(0,k): add=yd[0,n,r]*(ctx.mpf('1.0')*ctx.fac(2*k-2*r)/ctx.fac(k-r)) yd[0,n,k] -= ((-1)**(k-r))*add yd[0,n,-2]=0; yd[0,n,-1]=0; yd[0,n,3*n//2+1]=0 for mu in range(-2,der+1): for n in range(-2,L): for k in range(-3,max(1,3*n//2+2)): if( (mu<0)or (n<0) or(k<0)or (k>3*n//2)): yd[mu,n,k] = 0 for mu in range(1,der+1): for n in range(0,L): ctx.prec = ywpd[n]+10 for k in range(0,3*n//2+1): aux=(2*mu-2)*yd[mu-2,n-2,k-3]+2*(ysigma+n-2)*yd[mu-1,n-2,k-3] yd[mu,n,k] = aux - yd[mu-1,n-1,k-1] # COMPUTING THE COEFFICIENTS xtcoef[k,l] # See II Section 3.9 # # computing the needed wp xwptcoef={} xwpterm={} ctx.prec = 15 c1 = ctx.mag(40*(L+2)) xc2 = ctx.mag(68*(L+2)*xA) xc4 = ctx.mag(xB1*a*math.sqrt(ctx.pi))-1 for k in range(0,L): xc3 = xc2 - k*xc4+ctx.mag(ctx.fac(k+0.5))/2. xwptcoef[k] = (max(c1,xc3-ctx.mag(xeps4)+1)+1 +20)*1.5 xwpterm[k] = (max(c1,ctx.mag(L+2)+xc3-ctx.mag(xeps3)+1)+1 +20) ywptcoef={} ywpterm={} ctx.prec = 15 c1 = ctx.mag(40*(L+2)) yc2 = ctx.mag(68*(L+2)*yA) yc4 = ctx.mag(yB1*a*math.sqrt(ctx.pi))-1 for k in range(0,L): yc3 = yc2 - k*yc4+ctx.mag(ctx.fac(k+0.5))/2. ywptcoef[k] = ((max(c1,yc3-ctx.mag(yeps4)+1))+10)*1.5 ywpterm[k] = (max(c1,ctx.mag(L+2)+yc3-ctx.mag(yeps3)+1)+1)+10 # check of power of pi # computing the fortcoef[mu,k,ell] xfortcoef={} for mu in range(0,der+1): for k in range(0,L): for ell in range(-2,3*k//2+1): xfortcoef[mu,k,ell]=0 for mu in range(0,der+1): for k in range(0,L): ctx.prec = xwptcoef[k] for ell in range(0,3*k//2+1): xfortcoef[mu,k,ell]=xd[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell] xfortcoef[mu,k,ell]=xfortcoef[mu,k,ell]/((2*ctx.j)**ell) def trunc_a(t): wp = ctx.prec ctx.prec = wp + 2 aa = ctx.sqrt(t/(2*ctx.pi)) ctx.prec = wp return aa # computing the tcoef[k,ell] xtcoef={} for mu in range(0,der+1): for k in range(0,L): for ell in range(-2,3*k//2+1): xtcoef[mu,k,ell]=0 ctx.prec = max(xwptcoef[0],ywptcoef[0])+3 aa= trunc_a(t) la = -ctx.ln(aa) for chi in range(0,der+1): for k in range(0,L): ctx.prec = xwptcoef[k] for ell in range(0,3*k//2+1): xtcoef[chi,k,ell] =0 for mu in range(0, chi+1): tcoefter=ctx.binomial(chi,mu)*ctx.power(la,mu)*xfortcoef[chi-mu,k,ell] xtcoef[chi,k,ell] += tcoefter # COMPUTING THE COEFFICIENTS ytcoef[k,l] # See II Section 3.9 # # computing the needed wp # check of power of pi # computing the fortcoef[mu,k,ell] yfortcoef={} for mu in range(0,der+1): for k in range(0,L): for ell in range(-2,3*k//2+1): yfortcoef[mu,k,ell]=0 for mu in range(0,der+1): for k in range(0,L): ctx.prec = ywptcoef[k] for ell in range(0,3*k//2+1): yfortcoef[mu,k,ell]=yd[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell] yfortcoef[mu,k,ell]=yfortcoef[mu,k,ell]/((2*ctx.j)**ell) # computing the tcoef[k,ell] ytcoef={} for chi in range(0,der+1): for k in range(0,L): for ell in range(-2,3*k//2+1): ytcoef[chi,k,ell]=0 for chi in range(0,der+1): for k in range(0,L): ctx.prec = ywptcoef[k] for ell in range(0,3*k//2+1): ytcoef[chi,k,ell] =0 for mu in range(0, chi+1): tcoefter=ctx.binomial(chi,mu)*ctx.power(la,mu)*yfortcoef[chi-mu,k,ell] ytcoef[chi,k,ell] += tcoefter # COMPUTING tv[k,ell] # See II Section 3.8 # # a has a good value ctx.prec = max(xwptcoef[0], ywptcoef[0])+2 av = {} av[0] = 1 av[1] = av[0]/a ctx.prec = max(xwptcoef[0],ywptcoef[0]) for k in range(2,L): av[k] = av[k-1] * av[1] # Computing the quotients xtv = {} for chi in range(0,der+1): for k in range(0,L): ctx.prec = xwptcoef[k] for ell in range(0,3*k//2+1): xtv[chi,k,ell] = xtcoef[chi,k,ell]* av[k] # Computing the quotients ytv = {} for chi in range(0,der+1): for k in range(0,L): ctx.prec = ywptcoef[k] for ell in range(0,3*k//2+1): ytv[chi,k,ell] = ytcoef[chi,k,ell]* av[k] # COMPUTING THE TERMS xterm[k] # See II Section 3.6 xterm = {} for chi in range(0,der+1): for n in range(0,L): ctx.prec = xwpterm[n] te = 0 for k in range(0, 3*n//2+1): te += xtv[chi,n,k] xterm[chi,n] = te # COMPUTING THE TERMS yterm[k] # See II Section 3.6 yterm = {} for chi in range(0,der+1): for n in range(0,L): ctx.prec = ywpterm[n] te = 0 for k in range(0, 3*n//2+1): te += ytv[chi,n,k] yterm[chi,n] = te # COMPUTING rssum # See II Section 3.5 xrssum={} ctx.prec=15 xrsbound = math.sqrt(ctx.pi) * xc /(xb*a) ctx.prec=15 xwprssum = ctx.mag(4.4*((L+3)**2)*xrsbound / xeps2) xwprssum = max(xwprssum, ctx.mag(10*(L+1))) ctx.prec = xwprssum for chi in range(0,der+1): xrssum[chi] = 0 for k in range(1,L+1): xrssum[chi] += xterm[chi,L-k] yrssum={} ctx.prec=15 yrsbound = math.sqrt(ctx.pi) * yc /(yb*a) ctx.prec=15 ywprssum = ctx.mag(4.4*((L+3)**2)*yrsbound / yeps2) ywprssum = max(ywprssum, ctx.mag(10*(L+1))) ctx.prec = ywprssum for chi in range(0,der+1): yrssum[chi] = 0 for k in range(1,L+1): yrssum[chi] += yterm[chi,L-k] # COMPUTING S3 # See II Section 3.19 ctx.prec = 15 A2 = 2**(max(ctx.mag(abs(xrssum[0])), ctx.mag(abs(yrssum[0])))) eps8 = eps/(3*A2) T = t *ctx.ln(t/(2*ctx.pi)) xwps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-xsigma))*T) ywps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-ysigma))*T) ctx.prec = max(xwps3, ywps3) tpi = t/(2*ctx.pi) arg = (t/2)*ctx.ln(tpi)-(t/2)-ctx.pi/8 U = ctx.expj(-arg) a = trunc_a(t) xasigma = ctx.power(a, -xsigma) yasigma = ctx.power(a, -ysigma) xS3 = ((-1)**(N-1)) * xasigma * U yS3 = ((-1)**(N-1)) * yasigma * U # COMPUTING S1 the zetasum # See II Section 3.18 ctx.prec = 15 xwpsum = 4+ ctx.mag((N+ctx.power(N,1-xsigma))*ctx.ln(N) /eps1) ywpsum = 4+ ctx.mag((N+ctx.power(N,1-ysigma))*ctx.ln(N) /eps1) wpsum = max(xwpsum, ywpsum) ctx.prec = wpsum +10 ''' # This can be improved xS1={} yS1={} for chi in range(0,der+1): xS1[chi] = 0 yS1[chi] = 0 for n in range(1,int(N)+1): ln = ctx.ln(n) xexpn = ctx.exp(-ln*(xsigma+ctx.j*t)) yexpn = ctx.conj(1/(n*xexpn)) for chi in range(0,der+1): pown = ctx.power(-ln, chi) xterm = pown*xexpn yterm = pown*yexpn xS1[chi] += xterm yS1[chi] += yterm ''' xS1, yS1 = ctx._zetasum(s, 1, int(N)-1, range(0,der+1), True) # END OF COMPUTATION of xrz, yrz # See II Section 3.1 ctx.prec = 15 xabsS1 = abs(xS1[der]) xabsS2 = abs(xrssum[der] * xS3) xwpend = max(6, wpinitial+ctx.mag(6*(3*xabsS1+7*xabsS2) ) ) ctx.prec = xwpend xrz={} for chi in range(0,der+1): xrz[chi] = xS1[chi]+xrssum[chi]*xS3 ctx.prec = 15 yabsS1 = abs(yS1[der]) yabsS2 = abs(yrssum[der] * yS3) ywpend = max(6, wpinitial+ctx.mag(6*(3*yabsS1+7*yabsS2) ) ) ctx.prec = ywpend yrz={} for chi in range(0,der+1): yrz[chi] = yS1[chi]+yrssum[chi]*yS3 yrz[chi] = ctx.conj(yrz[chi]) ctx.prec = wpinitial return xrz, yrz def Rzeta_set(ctx, s, derivatives=[0]): r""" Computes several derivatives of the auxiliary function of Riemann `R(s)`. **Definition** The function is defined by .. math :: \begin{equation} {\mathop{\mathcal R }\nolimits}(s)= \int_{0\swarrow1}\frac{x^{-s} e^{\pi i x^2}}{e^{\pi i x}- e^{-\pi i x}}\,dx \end{equation} To this function we apply the Riemann-Siegel expansion. """ der = max(derivatives) # First we take the value of ctx.prec # During the computation we will change ctx.prec, and finally we will # restaurate the initial value wpinitial = ctx.prec # Take the real and imaginary part of s t = ctx._im(s) sigma = ctx._re(s) # Now compute several parameter that appear on the program ctx.prec = 15 a = ctx.sqrt(t/(2*ctx.pi)) # Careful asigma = ctx.power(a, sigma) # Careful # We need a simple bound A1 < asigma (see II Section 3.1 and 3.3) A1 = ctx.power(2, ctx.mag(asigma)-1) # We compute various epsilon's (see II end of Section 3.1) eps = ctx.power(2, -wpinitial) eps1 = eps/6. eps2 = eps * A1/3. # COMPUTING SOME COEFFICIENTS THAT DEPENDS # ON sigma # constant b and c (see I Theorem 2 formula (26) ) # coefficients A and B1 (see I Section 6.1 equation (50)) # here we not need high precision ctx.prec = 15 if sigma > 0: b = 2. c = math.pow(9,sigma)/4.44288 # 4.44288 =(math.sqrt(2)*math.pi) A = math.pow(9,sigma) B1 = 1 else: b = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi ) c = math.pow(2,-sigma)/4.44288 A = math.pow(2,-sigma) B1 = 1.10789 # = 2*sqrt(1-log(2)) # COMPUTING L THE NUMBER OF TERMS NEEDED IN THE RIEMANN-SIEGEL # CORRECTION # See II Section 3.2 ctx.prec = 15 L = 1 while 3*c*ctx.gamma(L*0.5) * ctx.power(b*a,-L) >= eps2: L = L+1 L = max(2,L) # The number L has to satify some conditions. # If not RS can not compute Rzeta(s) with the prescribed precision # (see II, Section 3.2 condition (20) ) and # (II, Section 3.3 condition (22) ). Also we have added # an additional technical condition in Section 3.17 Proposition 17 if ((3*L >= 2*a*a/25.) or (3*L+2+sigma<0) or (abs(sigma)> a/2.)): #print 'Error Riemann-Siegel can not compute with such precision' ctx.prec = wpinitial raise NotImplementedError("Riemann-Siegel can not compute with such precision") # INITIALIZATION (CONTINUATION) # # eps3 is the constant defined on (II, Section 3.5 equation (27) ) # each term of the RS correction must be computed with error <= eps3 eps3 = eps2/(4*L) # eps4 is defined on (II Section 3.6 equation (30) ) # each component of the formula (II Section 3.6 equation (29) ) # must be computed with error <= eps4 eps4 = eps3/(3*L) # COMPUTING M. NUMBER OF DERIVATIVES Fp[m] TO COMPUTE M = aux_M_Fp(ctx, A, eps4, a, B1, L) Fp = {} for n in range(M, 3*L-2): Fp[n] = 0 # But I have not seen an instance of M != 3*L-3 # # DETERMINATION OF J THE NUMBER OF TERMS NEEDED # IN THE TAYLOR SERIES OF F. # See II Section 3.11 equation (49)) h1 = eps4/(632*A) h2 = ctx.pi*ctx.pi*B1*a *ctx.sqrt(3)*math.e*math.e h2 = h1 * ctx.power((h2/M**2),(M-1)/3) / M h3 = min(h1,h2) J=12 jvalue = (2*ctx.pi)**J / ctx.gamma(J+1) while jvalue > h3: J = J+1 jvalue = (2*ctx.pi)*jvalue/J # COMPUTING eps5[m] for 1 <= m <= 21 # See II Section 10 equation (43) eps5={} foreps5 = math.pi*math.pi*B1*a for m in range(0,22): aux1 = math.pow(foreps5, m/3)/(316.*A) aux2 = ctx.gamma(m+1)/ctx.gamma(m/3.0+0.5) aux2 = math.sqrt(aux2) eps5[m] = aux1*aux2*eps4 # COMPUTING wpfp # See II Section 3.13 equation (59) twenty = min(3*L-3, 21)+1 aux = 6812*J wpfp = ctx.mag(44*J) for m in range(0, twenty): wpfp = max(wpfp, ctx.mag(aux*ctx.gamma(m+1)/eps5[m])) # COMPUTING N AND p # See II Section ctx.prec = wpfp + ctx.mag(t) + 20 a = ctx.sqrt(t/(2*ctx.pi)) N = ctx.floor(a) p = 1-2*(a-N) # now we get a rounded version of p to the precision wpfp # this possibly is not necessary num = ctx.floor(p*(ctx.mpf(2)**wpfp)) difference = p * (ctx.mpf(2)**wpfp)-num if difference < 0.5: num = num else: num = num+1 p = ctx.convert(num * (ctx.mpf(2)**(-wpfp))) # COMPUTING THE COEFFICIENTS c[n] = cc[n] # We shall use the notation cc[n], since there is # a constant that is called c # See II Section 3.14 # We compute the coefficients and also save then in a # cache. The bulk of the computation is passed to # the function coef() # # eps6 is defined in II Section 3.13 equation (58) eps6 = ctx.power(2*ctx.pi, J)/(ctx.gamma(J+1)*3*J) # Now we compute the coefficients cc={} cont={} cont, pipowers = coef(ctx, J, eps6) cc = cont.copy() # we need a copy since we have Fp={} for n in range(M, 3*L-2): Fp[n] = 0 ctx.prec = wpfp for m in range(0,M+1): sumP = 0 for k in range(2*J-m-1,-1,-1): sumP = (sumP * p) + cc[k] Fp[m] = sumP # preparation of the new coefficients for k in range(0, 2*J-m-1): cc[k] = (k+1) * cc[k+1] # COMPUTING THE NUMBERS d[n,k] # See II Section 3.17 # First we compute the working precisions wpd[k] # Se II equation (92) wpd = {} d1 = max(6, ctx.mag(40*L*L)) d2 = 13+ctx.mag((1+abs(sigma))*A)-ctx.mag(eps4)-1 const = ctx.ln(8/(ctx.pi*ctx.pi*a*a*B1*B1)) /2 for n in range(0,L): d3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*const)+d2 wpd[n] = max(d3,d1) # procedure of II Section 3.17 ctx.prec = wpd[1]+10 psigma = 1-(2*sigma) d = {} d[0,0,-2]=0; d[0,0,-1]=0; d[0,0,0]=1; d[0,0,1]=0 d[0,-1,-2]=0; d[0,-1,-1]=0; d[0,-1,0]=1; d[0,-1,1]=0 for n in range(1,L): ctx.prec = wpd[n]+10 for k in range(0,3*n//2+1): m = 3*n-2*k if (m!=0): m1 = ctx.one/m c1 = m1/4 c2 = (psigma*m1)/2 c3 = -(m+1) d[0,n,k] = c3*d[0,n-1,k-2]+c1*d[0,n-1,k]+c2*d[0,n-1,k-1] else: d[0,n,k]=0 for r in range(0,k): add = d[0,n,r]*(ctx.one*ctx.fac(2*k-2*r)/ctx.fac(k-r)) d[0,n,k] -= ((-1)**(k-r))*add d[0,n,-2]=0; d[0,n,-1]=0; d[0,n,3*n//2+1]=0 for mu in range(-2,der+1): for n in range(-2,L): for k in range(-3,max(1,3*n//2+2)): if ((mu<0)or (n<0) or(k<0)or (k>3*n//2)): d[mu,n,k] = 0 for mu in range(1,der+1): for n in range(0,L): ctx.prec = wpd[n]+10 for k in range(0,3*n//2+1): aux=(2*mu-2)*d[mu-2,n-2,k-3]+2*(sigma+n-2)*d[mu-1,n-2,k-3] d[mu,n,k] = aux - d[mu-1,n-1,k-1] # COMPUTING THE COEFFICIENTS t[k,l] # See II Section 3.9 # # computing the needed wp wptcoef = {} wpterm = {} ctx.prec = 15 c1 = ctx.mag(40*(L+2)) c2 = ctx.mag(68*(L+2)*A) c4 = ctx.mag(B1*a*math.sqrt(ctx.pi))-1 for k in range(0,L): c3 = c2 - k*c4+ctx.mag(ctx.fac(k+0.5))/2. wptcoef[k] = max(c1,c3-ctx.mag(eps4)+1)+1 +10 wpterm[k] = max(c1,ctx.mag(L+2)+c3-ctx.mag(eps3)+1)+1 +10 # check of power of pi # computing the fortcoef[mu,k,ell] fortcoef={} for mu in derivatives: for k in range(0,L): for ell in range(-2,3*k//2+1): fortcoef[mu,k,ell]=0 for mu in derivatives: for k in range(0,L): ctx.prec = wptcoef[k] for ell in range(0,3*k//2+1): fortcoef[mu,k,ell]=d[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell] fortcoef[mu,k,ell]=fortcoef[mu,k,ell]/((2*ctx.j)**ell) def trunc_a(t): wp = ctx.prec ctx.prec = wp + 2 aa = ctx.sqrt(t/(2*ctx.pi)) ctx.prec = wp return aa # computing the tcoef[chi,k,ell] tcoef={} for chi in derivatives: for k in range(0,L): for ell in range(-2,3*k//2+1): tcoef[chi,k,ell]=0 ctx.prec = wptcoef[0]+3 aa = trunc_a(t) la = -ctx.ln(aa) for chi in derivatives: for k in range(0,L): ctx.prec = wptcoef[k] for ell in range(0,3*k//2+1): tcoef[chi,k,ell] = 0 for mu in range(0, chi+1): tcoefter = ctx.binomial(chi,mu) * la**mu * \ fortcoef[chi-mu,k,ell] tcoef[chi,k,ell] += tcoefter # COMPUTING tv[k,ell] # See II Section 3.8 # Computing the powers av[k] = a**(-k) ctx.prec = wptcoef[0] + 2 # a has a good value of a. # See II Section 3.6 av = {} av[0] = 1 av[1] = av[0]/a ctx.prec = wptcoef[0] for k in range(2,L): av[k] = av[k-1] * av[1] # Computing the quotients tv = {} for chi in derivatives: for k in range(0,L): ctx.prec = wptcoef[k] for ell in range(0,3*k//2+1): tv[chi,k,ell] = tcoef[chi,k,ell]* av[k] # COMPUTING THE TERMS term[k] # See II Section 3.6 term = {} for chi in derivatives: for n in range(0,L): ctx.prec = wpterm[n] te = 0 for k in range(0, 3*n//2+1): te += tv[chi,n,k] term[chi,n] = te # COMPUTING rssum # See II Section 3.5 rssum={} ctx.prec=15 rsbound = math.sqrt(ctx.pi) * c /(b*a) ctx.prec=15 wprssum = ctx.mag(4.4*((L+3)**2)*rsbound / eps2) wprssum = max(wprssum, ctx.mag(10*(L+1))) ctx.prec = wprssum for chi in derivatives: rssum[chi] = 0 for k in range(1,L+1): rssum[chi] += term[chi,L-k] # COMPUTING S3 # See II Section 3.19 ctx.prec = 15 A2 = 2**(ctx.mag(rssum[0])) eps8 = eps/(3* A2) T = t * ctx.ln(t/(2*ctx.pi)) wps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-sigma))*T) ctx.prec = wps3 tpi = t/(2*ctx.pi) arg = (t/2)*ctx.ln(tpi)-(t/2)-ctx.pi/8 U = ctx.expj(-arg) a = trunc_a(t) asigma = ctx.power(a, -sigma) S3 = ((-1)**(N-1)) * asigma * U # COMPUTING S1 the zetasum # See II Section 3.18 ctx.prec = 15 wpsum = 4 + ctx.mag((N+ctx.power(N,1-sigma))*ctx.ln(N)/eps1) ctx.prec = wpsum + 10 ''' # This can be improved S1 = {} for chi in derivatives: S1[chi] = 0 for n in range(1,int(N)+1): ln = ctx.ln(n) expn = ctx.exp(-ln*(sigma+ctx.j*t)) for chi in derivatives: term = ctx.power(-ln, chi)*expn S1[chi] += term ''' S1 = ctx._zetasum(s, 1, int(N)-1, derivatives)[0] # END OF COMPUTATION # See II Section 3.1 ctx.prec = 15 absS1 = abs(S1[der]) absS2 = abs(rssum[der] * S3) wpend = max(6, wpinitial + ctx.mag(6*(3*absS1+7*absS2))) ctx.prec = wpend rz = {} for chi in derivatives: rz[chi] = S1[chi]+rssum[chi]*S3 ctx.prec = wpinitial return rz def z_half(ctx,t,der=0): r""" z_half(t,der=0) Computes Z^(der)(t) """ s=ctx.mpf('0.5')+ctx.j*t wpinitial = ctx.prec ctx.prec = 15 tt = t/(2*ctx.pi) wptheta = wpinitial +1 + ctx.mag(3*(tt**1.5)*ctx.ln(tt)) wpz = wpinitial + 1 + ctx.mag(12*tt*ctx.ln(tt)) ctx.prec = wptheta theta = ctx.siegeltheta(t) ctx.prec = wpz rz = Rzeta_set(ctx,s, range(der+1)) if der > 0: ps1 = ctx._re(ctx.psi(0,s/2)/2 - ctx.ln(ctx.pi)/2) if der > 1: ps2 = ctx._re(ctx.j*ctx.psi(1,s/2)/4) if der > 2: ps3 = ctx._re(-ctx.psi(2,s/2)/8) if der > 3: ps4 = ctx._re(-ctx.j*ctx.psi(3,s/2)/16) exptheta = ctx.expj(theta) if der == 0: z = 2*exptheta*rz[0] if der == 1: zf = 2j*exptheta z = zf*(ps1*rz[0]+rz[1]) if der == 2: zf = 2 * exptheta z = -zf*(2*rz[1]*ps1+rz[0]*ps1**2+rz[2]-ctx.j*rz[0]*ps2) if der == 3: zf = -2j*exptheta z = 3*rz[1]*ps1**2+rz[0]*ps1**3+3*ps1*rz[2] z = zf*(z-3j*rz[1]*ps2-3j*rz[0]*ps1*ps2+rz[3]-rz[0]*ps3) if der == 4: zf = 2*exptheta z = 4*rz[1]*ps1**3+rz[0]*ps1**4+6*ps1**2*rz[2] z = z-12j*rz[1]*ps1*ps2-6j*rz[0]*ps1**2*ps2-6j*rz[2]*ps2-3*rz[0]*ps2*ps2 z = z + 4*ps1*rz[3]-4*rz[1]*ps3-4*rz[0]*ps1*ps3+rz[4]+ctx.j*rz[0]*ps4 z = zf*z ctx.prec = wpinitial return ctx._re(z) def zeta_half(ctx, s, k=0): """ zeta_half(s,k=0) Computes zeta^(k)(s) when Re s = 0.5 """ wpinitial = ctx.prec sigma = ctx._re(s) t = ctx._im(s) #--- compute wptheta, wpR, wpbasic --- ctx.prec = 53 # X see II Section 3.21 (109) and (110) if sigma > 0: X = ctx.sqrt(abs(s)) else: X = (2*ctx.pi)**(sigma-1) * abs(1-s)**(0.5-sigma) # M1 see II Section 3.21 (111) and (112) if sigma > 0: M1 = 2*ctx.sqrt(t/(2*ctx.pi)) else: M1 = 4 * t * X # T see II Section 3.21 (113) abst = abs(0.5-s) T = 2* abst*math.log(abst) # computing wpbasic, wptheta, wpR see II Section 3.21 wpbasic = max(6,3+ctx.mag(t)) wpbasic2 = 2+ctx.mag(2.12*M1+21.2*M1*X+1.3*M1*X*T)+wpinitial+1 wpbasic = max(wpbasic, wpbasic2) wptheta = max(4, 3+ctx.mag(2.7*M1*X)+wpinitial+1) wpR = 3+ctx.mag(1.1+2*X)+wpinitial+1 ctx.prec = wptheta theta = ctx.siegeltheta(t-ctx.j*(sigma-ctx.mpf('0.5'))) if k > 0: ps1 = (ctx._re(ctx.psi(0,s/2)))/2 - ctx.ln(ctx.pi)/2 if k > 1: ps2 = -(ctx._im(ctx.psi(1,s/2)))/4 if k > 2: ps3 = -(ctx._re(ctx.psi(2,s/2)))/8 if k > 3: ps4 = (ctx._im(ctx.psi(3,s/2)))/16 ctx.prec = wpR xrz = Rzeta_set(ctx,s,range(k+1)) yrz={} for chi in range(0,k+1): yrz[chi] = ctx.conj(xrz[chi]) ctx.prec = wpbasic exptheta = ctx.expj(-2*theta) if k==0: zv = xrz[0]+exptheta*yrz[0] if k==1: zv1 = -yrz[1] - 2*yrz[0]*ps1 zv = xrz[1] + exptheta*zv1 if k==2: zv1 = 4*yrz[1]*ps1+4*yrz[0]*(ps1**2)+yrz[2]+2j*yrz[0]*ps2 zv = xrz[2]+exptheta*zv1 if k==3: zv1 = -12*yrz[1]*ps1**2-8*yrz[0]*ps1**3-6*yrz[2]*ps1-6j*yrz[1]*ps2 zv1 = zv1 - 12j*yrz[0]*ps1*ps2-yrz[3]+2*yrz[0]*ps3 zv = xrz[3]+exptheta*zv1 if k == 4: zv1 = 32*yrz[1]*ps1**3 +16*yrz[0]*ps1**4+24*yrz[2]*ps1**2 zv1 = zv1 +48j*yrz[1]*ps1*ps2+48j*yrz[0]*(ps1**2)*ps2 zv1 = zv1+12j*yrz[2]*ps2-12*yrz[0]*ps2**2+8*yrz[3]*ps1-8*yrz[1]*ps3 zv1 = zv1-16*yrz[0]*ps1*ps3+yrz[4]-2j*yrz[0]*ps4 zv = xrz[4]+exptheta*zv1 ctx.prec = wpinitial return zv def zeta_offline(ctx, s, k=0): """ Computes zeta^(k)(s) off the line """ wpinitial = ctx.prec sigma = ctx._re(s) t = ctx._im(s) #--- compute wptheta, wpR, wpbasic --- ctx.prec = 53 # X see II Section 3.21 (109) and (110) if sigma > 0: X = ctx.power(abs(s), 0.5) else: X = ctx.power(2*ctx.pi, sigma-1)*ctx.power(abs(1-s),0.5-sigma) # M1 see II Section 3.21 (111) and (112) if (sigma > 0): M1 = 2*ctx.sqrt(t/(2*ctx.pi)) else: M1 = 4 * t * X # M2 see II Section 3.21 (111) and (112) if (1-sigma > 0): M2 = 2*ctx.sqrt(t/(2*ctx.pi)) else: M2 = 4*t*ctx.power(2*ctx.pi, -sigma)*ctx.power(abs(s),sigma-0.5) # T see II Section 3.21 (113) abst = abs(0.5-s) T = 2* abst*math.log(abst) # computing wpbasic, wptheta, wpR see II Section 3.21 wpbasic = max(6,3+ctx.mag(t)) wpbasic2 = 2+ctx.mag(2.12*M1+21.2*M2*X+1.3*M2*X*T)+wpinitial+1 wpbasic = max(wpbasic, wpbasic2) wptheta = max(4, 3+ctx.mag(2.7*M2*X)+wpinitial+1) wpR = 3+ctx.mag(1.1+2*X)+wpinitial+1 ctx.prec = wptheta theta = ctx.siegeltheta(t-ctx.j*(sigma-ctx.mpf('0.5'))) s1 = s s2 = ctx.conj(1-s1) ctx.prec = wpR xrz, yrz = Rzeta_simul(ctx, s, k) if k > 0: ps1 = (ctx.psi(0,s1/2)+ctx.psi(0,(1-s1)/2))/4 - ctx.ln(ctx.pi)/2 if k > 1: ps2 = ctx.j*(ctx.psi(1,s1/2)-ctx.psi(1,(1-s1)/2))/8 if k > 2: ps3 = -(ctx.psi(2,s1/2)+ctx.psi(2,(1-s1)/2))/16 if k > 3: ps4 = -ctx.j*(ctx.psi(3,s1/2)-ctx.psi(3,(1-s1)/2))/32 ctx.prec = wpbasic exptheta = ctx.expj(-2*theta) if k == 0: zv = xrz[0]+exptheta*yrz[0] if k == 1: zv1 = -yrz[1]-2*yrz[0]*ps1 zv = xrz[1]+exptheta*zv1 if k == 2: zv1 = 4*yrz[1]*ps1+4*yrz[0]*(ps1**2) +yrz[2]+2j*yrz[0]*ps2 zv = xrz[2]+exptheta*zv1 if k == 3: zv1 = -12*yrz[1]*ps1**2 -8*yrz[0]*ps1**3-6*yrz[2]*ps1-6j*yrz[1]*ps2 zv1 = zv1 - 12j*yrz[0]*ps1*ps2-yrz[3]+2*yrz[0]*ps3 zv = xrz[3]+exptheta*zv1 if k == 4: zv1 = 32*yrz[1]*ps1**3 +16*yrz[0]*ps1**4+24*yrz[2]*ps1**2 zv1 = zv1 +48j*yrz[1]*ps1*ps2+48j*yrz[0]*(ps1**2)*ps2 zv1 = zv1+12j*yrz[2]*ps2-12*yrz[0]*ps2**2+8*yrz[3]*ps1-8*yrz[1]*ps3 zv1 = zv1-16*yrz[0]*ps1*ps3+yrz[4]-2j*yrz[0]*ps4 zv = xrz[4]+exptheta*zv1 ctx.prec = wpinitial return zv def z_offline(ctx, w, k=0): r""" Computes Z(w) and its derivatives off the line """ s = ctx.mpf('0.5')+ctx.j*w s1 = s s2 = ctx.conj(1-s1) wpinitial = ctx.prec ctx.prec = 35 # X see II Section 3.21 (109) and (110) # M1 see II Section 3.21 (111) and (112) if (ctx._re(s1) >= 0): M1 = 2*ctx.sqrt(ctx._im(s1)/(2 * ctx.pi)) X = ctx.sqrt(abs(s1)) else: X = (2*ctx.pi)**(ctx._re(s1)-1) * abs(1-s1)**(0.5-ctx._re(s1)) M1 = 4 * ctx._im(s1)*X # M2 see II Section 3.21 (111) and (112) if (ctx._re(s2) >= 0): M2 = 2*ctx.sqrt(ctx._im(s2)/(2 * ctx.pi)) else: M2 = 4 * ctx._im(s2)*(2*ctx.pi)**(ctx._re(s2)-1)*abs(1-s2)**(0.5-ctx._re(s2)) # T see II Section 3.21 Prop. 27 T = 2*abs(ctx.siegeltheta(w)) # defining some precisions # see II Section 3.22 (115), (116), (117) aux1 = ctx.sqrt(X) aux2 = aux1*(M1+M2) aux3 = 3 +wpinitial wpbasic = max(6, 3+ctx.mag(T), ctx.mag(aux2*(26+2*T))+aux3) wptheta = max(4,ctx.mag(2.04*aux2)+aux3) wpR = ctx.mag(4*aux1)+aux3 # now the computations ctx.prec = wptheta theta = ctx.siegeltheta(w) ctx.prec = wpR xrz, yrz = Rzeta_simul(ctx,s,k) pta = 0.25 + 0.5j*w ptb = 0.25 - 0.5j*w if k > 0: ps1 = 0.25*(ctx.psi(0,pta)+ctx.psi(0,ptb)) - ctx.ln(ctx.pi)/2 if k > 1: ps2 = (1j/8)*(ctx.psi(1,pta)-ctx.psi(1,ptb)) if k > 2: ps3 = (-1./16)*(ctx.psi(2,pta)+ctx.psi(2,ptb)) if k > 3: ps4 = (-1j/32)*(ctx.psi(3,pta)-ctx.psi(3,ptb)) ctx.prec = wpbasic exptheta = ctx.expj(theta) if k == 0: zv = exptheta*xrz[0]+yrz[0]/exptheta j = ctx.j if k == 1: zv = j*exptheta*(xrz[1]+xrz[0]*ps1)-j*(yrz[1]+yrz[0]*ps1)/exptheta if k == 2: zv = exptheta*(-2*xrz[1]*ps1-xrz[0]*ps1**2-xrz[2]+j*xrz[0]*ps2) zv =zv + (-2*yrz[1]*ps1-yrz[0]*ps1**2-yrz[2]-j*yrz[0]*ps2)/exptheta if k == 3: zv1 = -3*xrz[1]*ps1**2-xrz[0]*ps1**3-3*xrz[2]*ps1+j*3*xrz[1]*ps2 zv1 = (zv1+ 3j*xrz[0]*ps1*ps2-xrz[3]+xrz[0]*ps3)*j*exptheta zv2 = 3*yrz[1]*ps1**2+yrz[0]*ps1**3+3*yrz[2]*ps1+j*3*yrz[1]*ps2 zv2 = j*(zv2 + 3j*yrz[0]*ps1*ps2+ yrz[3]-yrz[0]*ps3)/exptheta zv = zv1+zv2 if k == 4: zv1 = 4*xrz[1]*ps1**3+xrz[0]*ps1**4 + 6*xrz[2]*ps1**2 zv1 = zv1-12j*xrz[1]*ps1*ps2-6j*xrz[0]*ps1**2*ps2-6j*xrz[2]*ps2 zv1 = zv1-3*xrz[0]*ps2*ps2+4*xrz[3]*ps1-4*xrz[1]*ps3-4*xrz[0]*ps1*ps3 zv1 = zv1+xrz[4]+j*xrz[0]*ps4 zv2 = 4*yrz[1]*ps1**3+yrz[0]*ps1**4 + 6*yrz[2]*ps1**2 zv2 = zv2+12j*yrz[1]*ps1*ps2+6j*yrz[0]*ps1**2*ps2+6j*yrz[2]*ps2 zv2 = zv2-3*yrz[0]*ps2*ps2+4*yrz[3]*ps1-4*yrz[1]*ps3-4*yrz[0]*ps1*ps3 zv2 = zv2+yrz[4]-j*yrz[0]*ps4 zv = exptheta*zv1+zv2/exptheta ctx.prec = wpinitial return zv @defun def rs_zeta(ctx, s, derivative=0, **kwargs): if derivative > 4: raise NotImplementedError s = ctx.convert(s) re = ctx._re(s); im = ctx._im(s) if im < 0: z = ctx.conj(ctx.rs_zeta(ctx.conj(s), derivative)) return z critical_line = (re == 0.5) if critical_line: return zeta_half(ctx, s, derivative) else: return zeta_offline(ctx, s, derivative) @defun def rs_z(ctx, w, derivative=0): w = ctx.convert(w) re = ctx._re(w); im = ctx._im(w) if re < 0: return rs_z(ctx, -w, derivative) critical_line = (im == 0) if critical_line : return z_half(ctx, w, derivative) else: return z_offline(ctx, w, derivative) mpmath-1.1.0/mpmath/functions/theta.py000066400000000000000000001107101340375245600177650ustar00rootroot00000000000000from .functions import defun, defun_wrapped @defun def _jacobi_theta2(ctx, z, q): extra1 = 10 extra2 = 20 # the loops below break when the fixed precision quantities # a and b go to zero; # right shifting small negative numbers by wp one obtains -1, not zero, # so the condition a**2 + b**2 > MIN is used to break the loops. MIN = 2 if z == ctx.zero: if (not ctx._im(q)): wp = ctx.prec + extra1 x = ctx.to_fixed(ctx._re(q), wp) x2 = (x*x) >> wp a = b = x2 s = x2 while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp s += a s = (1 << (wp+1)) + (s << 1) s = ctx.ldexp(s, -wp) else: wp = ctx.prec + extra1 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp-1) are = bre = x2re aim = bim = x2im sre = (1< MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp sre += are sim += aim sre = (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) else: if (not ctx._im(q)) and (not ctx._im(z)): wp = ctx.prec + extra1 x = ctx.to_fixed(ctx._re(q), wp) x2 = (x*x) >> wp a = b = x2 c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp) cn = c1 = ctx.to_fixed(c1, wp) sn = s1 = ctx.to_fixed(s1, wp) c2 = (c1*c1 - s1*s1) >> wp s2 = (c1 * s1) >> (wp - 1) cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp s = c1 + ((a * cn) >> wp) while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp s += (a * cn) >> wp s = (s << 1) s = ctx.ldexp(s, -wp) s *= ctx.nthroot(q, 4) return s # case z real, q complex elif not ctx._im(z): wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = x2re aim = bim = x2im c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp) cn = c1 = ctx.to_fixed(c1, wp) sn = s1 = ctx.to_fixed(s1, wp) c2 = (c1*c1 - s1*s1) >> wp s2 = (c1 * s1) >> (wp - 1) cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp sre = c1 + ((are * cn) >> wp) sim = ((aim * cn) >> wp) while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp sre += ((are * cn) >> wp) sim += ((aim * cn) >> wp) sre = (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) #case z complex, q real elif not ctx._im(q): wp = ctx.prec + extra2 x = ctx.to_fixed(ctx._re(q), wp) x2 = (x*x) >> wp a = b = x2 prec0 = ctx.prec ctx.prec = wp c1, s1 = ctx.cos_sin(z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) #c2 = (c1*c1 - s1*s1) >> wp c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp c2im = (c1re*c1im - s1re*s1im) >> (wp - 1) #s2 = (c1 * s1) >> (wp - 1) s2re = (c1re*s1re - c1im*s1im) >> (wp - 1) s2im = (c1re*s1im + c1im*s1re) >> (wp - 1) #cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 sre = c1re + ((a * cnre) >> wp) sim = c1im + ((a * cnim) >> wp) while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 sre += ((a * cnre) >> wp) sim += ((a * cnim) >> wp) sre = (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) # case z and q complex else: wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = x2re aim = bim = x2im prec0 = ctx.prec ctx.prec = wp # cos(z), sin(z) with z complex c1, s1 = ctx.cos_sin(z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp c2im = (c1re*c1im - s1re*s1im) >> (wp - 1) s2re = (c1re*s1re - c1im*s1im) >> (wp - 1) s2im = (c1re*s1im + c1im*s1re) >> (wp - 1) t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 n = 1 termre = c1re termim = c1im sre = c1re + ((are * cnre - aim * cnim) >> wp) sim = c1im + ((are * cnim + aim * cnre) >> wp) n = 3 termre = ((are * cnre - aim * cnim) >> wp) termim = ((are * cnim + aim * cnre) >> wp) sre = c1re + ((are * cnre - aim * cnim) >> wp) sim = c1im + ((are * cnim + aim * cnre) >> wp) n = 5 while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp #cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 termre = ((are * cnre - aim * cnim) >> wp) termim = ((aim * cnre + are * cnim) >> wp) sre += ((are * cnre - aim * cnim) >> wp) sim += ((aim * cnre + are * cnim) >> wp) n += 2 sre = (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) s *= ctx.nthroot(q, 4) return s @defun def _djacobi_theta2(ctx, z, q, nd): MIN = 2 extra1 = 10 extra2 = 20 if (not ctx._im(q)) and (not ctx._im(z)): wp = ctx.prec + extra1 x = ctx.to_fixed(ctx._re(q), wp) x2 = (x*x) >> wp a = b = x2 c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp) cn = c1 = ctx.to_fixed(c1, wp) sn = s1 = ctx.to_fixed(s1, wp) c2 = (c1*c1 - s1*s1) >> wp s2 = (c1 * s1) >> (wp - 1) cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp if (nd&1): s = s1 + ((a * sn * 3**nd) >> wp) else: s = c1 + ((a * cn * 3**nd) >> wp) n = 2 while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp if nd&1: s += (a * sn * (2*n+1)**nd) >> wp else: s += (a * cn * (2*n+1)**nd) >> wp n += 1 s = -(s << 1) s = ctx.ldexp(s, -wp) # case z real, q complex elif not ctx._im(z): wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = x2re aim = bim = x2im c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp) cn = c1 = ctx.to_fixed(c1, wp) sn = s1 = ctx.to_fixed(s1, wp) c2 = (c1*c1 - s1*s1) >> wp s2 = (c1 * s1) >> (wp - 1) cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp if (nd&1): sre = s1 + ((are * sn * 3**nd) >> wp) sim = ((aim * sn * 3**nd) >> wp) else: sre = c1 + ((are * cn * 3**nd) >> wp) sim = ((aim * cn * 3**nd) >> wp) n = 5 while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp if (nd&1): sre += ((are * sn * n**nd) >> wp) sim += ((aim * sn * n**nd) >> wp) else: sre += ((are * cn * n**nd) >> wp) sim += ((aim * cn * n**nd) >> wp) n += 2 sre = -(sre << 1) sim = -(sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) #case z complex, q real elif not ctx._im(q): wp = ctx.prec + extra2 x = ctx.to_fixed(ctx._re(q), wp) x2 = (x*x) >> wp a = b = x2 prec0 = ctx.prec ctx.prec = wp c1, s1 = ctx.cos_sin(z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) #c2 = (c1*c1 - s1*s1) >> wp c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp c2im = (c1re*c1im - s1re*s1im) >> (wp - 1) #s2 = (c1 * s1) >> (wp - 1) s2re = (c1re*s1re - c1im*s1im) >> (wp - 1) s2im = (c1re*s1im + c1im*s1re) >> (wp - 1) #cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 if (nd&1): sre = s1re + ((a * snre * 3**nd) >> wp) sim = s1im + ((a * snim * 3**nd) >> wp) else: sre = c1re + ((a * cnre * 3**nd) >> wp) sim = c1im + ((a * cnim * 3**nd) >> wp) n = 5 while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 if (nd&1): sre += ((a * snre * n**nd) >> wp) sim += ((a * snim * n**nd) >> wp) else: sre += ((a * cnre * n**nd) >> wp) sim += ((a * cnim * n**nd) >> wp) n += 2 sre = -(sre << 1) sim = -(sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) # case z and q complex else: wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = x2re aim = bim = x2im prec0 = ctx.prec ctx.prec = wp # cos(2*z), sin(2*z) with z complex c1, s1 = ctx.cos_sin(z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp c2im = (c1re*c1im - s1re*s1im) >> (wp - 1) s2re = (c1re*s1re - c1im*s1im) >> (wp - 1) s2im = (c1re*s1im + c1im*s1re) >> (wp - 1) t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 if (nd&1): sre = s1re + (((are * snre - aim * snim) * 3**nd) >> wp) sim = s1im + (((are * snim + aim * snre)* 3**nd) >> wp) else: sre = c1re + (((are * cnre - aim * cnim) * 3**nd) >> wp) sim = c1im + (((are * cnim + aim * cnre)* 3**nd) >> wp) n = 5 while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp #cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 if (nd&1): sre += (((are * snre - aim * snim) * n**nd) >> wp) sim += (((aim * snre + are * snim) * n**nd) >> wp) else: sre += (((are * cnre - aim * cnim) * n**nd) >> wp) sim += (((aim * cnre + are * cnim) * n**nd) >> wp) n += 2 sre = -(sre << 1) sim = -(sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) s *= ctx.nthroot(q, 4) if (nd&1): return (-1)**(nd//2) * s else: return (-1)**(1 + nd//2) * s @defun def _jacobi_theta3(ctx, z, q): extra1 = 10 extra2 = 20 MIN = 2 if z == ctx.zero: if not ctx._im(q): wp = ctx.prec + extra1 x = ctx.to_fixed(ctx._re(q), wp) s = x a = b = x x2 = (x*x) >> wp while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp s += a s = (1 << wp) + (s << 1) s = ctx.ldexp(s, -wp) return s else: wp = ctx.prec + extra1 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) sre = are = bre = xre sim = aim = bim = xim while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp sre += are sim += aim sre = (1 << wp) + (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) return s else: if (not ctx._im(q)) and (not ctx._im(z)): s = 0 wp = ctx.prec + extra1 x = ctx.to_fixed(ctx._re(q), wp) a = b = x x2 = (x*x) >> wp c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp) c1 = ctx.to_fixed(c1, wp) s1 = ctx.to_fixed(s1, wp) cn = c1 sn = s1 s += (a * cn) >> wp while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp s += (a * cn) >> wp s = (1 << wp) + (s << 1) s = ctx.ldexp(s, -wp) return s # case z real, q complex elif not ctx._im(z): wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = xre aim = bim = xim c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp) c1 = ctx.to_fixed(c1, wp) s1 = ctx.to_fixed(s1, wp) cn = c1 sn = s1 sre = (are * cn) >> wp sim = (aim * cn) >> wp while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp sre += (are * cn) >> wp sim += (aim * cn) >> wp sre = (1 << wp) + (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) return s #case z complex, q real elif not ctx._im(q): wp = ctx.prec + extra2 x = ctx.to_fixed(ctx._re(q), wp) a = b = x x2 = (x*x) >> wp prec0 = ctx.prec ctx.prec = wp c1, s1 = ctx.cos_sin(2*z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) sre = (a * cnre) >> wp sim = (a * cnim) >> wp while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 sre += (a * cnre) >> wp sim += (a * cnim) >> wp sre = (1 << wp) + (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) return s # case z and q complex else: wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = xre aim = bim = xim prec0 = ctx.prec ctx.prec = wp # cos(2*z), sin(2*z) with z complex c1, s1 = ctx.cos_sin(2*z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) sre = (are * cnre - aim * cnim) >> wp sim = (aim * cnre + are * cnim) >> wp while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 sre += (are * cnre - aim * cnim) >> wp sim += (aim * cnre + are * cnim) >> wp sre = (1 << wp) + (sre << 1) sim = (sim << 1) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) return s @defun def _djacobi_theta3(ctx, z, q, nd): """nd=1,2,3 order of the derivative with respect to z""" MIN = 2 extra1 = 10 extra2 = 20 if (not ctx._im(q)) and (not ctx._im(z)): s = 0 wp = ctx.prec + extra1 x = ctx.to_fixed(ctx._re(q), wp) a = b = x x2 = (x*x) >> wp c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp) c1 = ctx.to_fixed(c1, wp) s1 = ctx.to_fixed(s1, wp) cn = c1 sn = s1 if (nd&1): s += (a * sn) >> wp else: s += (a * cn) >> wp n = 2 while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp if nd&1: s += (a * sn * n**nd) >> wp else: s += (a * cn * n**nd) >> wp n += 1 s = -(s << (nd+1)) s = ctx.ldexp(s, -wp) # case z real, q complex elif not ctx._im(z): wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = xre aim = bim = xim c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp) c1 = ctx.to_fixed(c1, wp) s1 = ctx.to_fixed(s1, wp) cn = c1 sn = s1 if (nd&1): sre = (are * sn) >> wp sim = (aim * sn) >> wp else: sre = (are * cn) >> wp sim = (aim * cn) >> wp n = 2 while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp if nd&1: sre += (are * sn * n**nd) >> wp sim += (aim * sn * n**nd) >> wp else: sre += (are * cn * n**nd) >> wp sim += (aim * cn * n**nd) >> wp n += 1 sre = -(sre << (nd+1)) sim = -(sim << (nd+1)) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) #case z complex, q real elif not ctx._im(q): wp = ctx.prec + extra2 x = ctx.to_fixed(ctx._re(q), wp) a = b = x x2 = (x*x) >> wp prec0 = ctx.prec ctx.prec = wp c1, s1 = ctx.cos_sin(2*z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) if (nd&1): sre = (a * snre) >> wp sim = (a * snim) >> wp else: sre = (a * cnre) >> wp sim = (a * cnim) >> wp n = 2 while abs(a) > MIN: b = (b*x2) >> wp a = (a*b) >> wp t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 if (nd&1): sre += (a * snre * n**nd) >> wp sim += (a * snim * n**nd) >> wp else: sre += (a * cnre * n**nd) >> wp sim += (a * cnim * n**nd) >> wp n += 1 sre = -(sre << (nd+1)) sim = -(sim << (nd+1)) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) # case z and q complex else: wp = ctx.prec + extra2 xre = ctx.to_fixed(ctx._re(q), wp) xim = ctx.to_fixed(ctx._im(q), wp) x2re = (xre*xre - xim*xim) >> wp x2im = (xre*xim) >> (wp - 1) are = bre = xre aim = bim = xim prec0 = ctx.prec ctx.prec = wp # cos(2*z), sin(2*z) with z complex c1, s1 = ctx.cos_sin(2*z) ctx.prec = prec0 cnre = c1re = ctx.to_fixed(ctx._re(c1), wp) cnim = c1im = ctx.to_fixed(ctx._im(c1), wp) snre = s1re = ctx.to_fixed(ctx._re(s1), wp) snim = s1im = ctx.to_fixed(ctx._im(s1), wp) if (nd&1): sre = (are * snre - aim * snim) >> wp sim = (aim * snre + are * snim) >> wp else: sre = (are * cnre - aim * cnim) >> wp sim = (aim * cnre + are * cnim) >> wp n = 2 while are**2 + aim**2 > MIN: bre, bim = (bre * x2re - bim * x2im) >> wp, \ (bre * x2im + bim * x2re) >> wp are, aim = (are * bre - aim * bim) >> wp, \ (are * bim + aim * bre) >> wp t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp cnre = t1 cnim = t2 snre = t3 snim = t4 if(nd&1): sre += ((are * snre - aim * snim) * n**nd) >> wp sim += ((aim * snre + are * snim) * n**nd) >> wp else: sre += ((are * cnre - aim * cnim) * n**nd) >> wp sim += ((aim * cnre + are * cnim) * n**nd) >> wp n += 1 sre = -(sre << (nd+1)) sim = -(sim << (nd+1)) sre = ctx.ldexp(sre, -wp) sim = ctx.ldexp(sim, -wp) s = ctx.mpc(sre, sim) if (nd&1): return (-1)**(nd//2) * s else: return (-1)**(1 + nd//2) * s @defun def _jacobi_theta2a(ctx, z, q): """ case ctx._im(z) != 0 theta(2, z, q) = q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n=-inf, inf) max term for minimum (2*n+1)*log(q).real - 2* ctx._im(z) n0 = int(ctx._im(z)/log(q).real - 1/2) theta(2, z, q) = q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n=n0, inf) + q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n, n0-1, -inf) """ n = n0 = int(ctx._im(z)/ctx._re(ctx.log(q)) - 1/2) e2 = ctx.expj(2*z) e = e0 = ctx.expj((2*n+1)*z) a = q**(n*n + n) # leading term term = a * e s = term eps1 = ctx.eps*abs(term) while 1: n += 1 e = e * e2 term = q**(n*n + n) * e if abs(term) < eps1: break s += term e = e0 e2 = ctx.expj(-2*z) n = n0 while 1: n -= 1 e = e * e2 term = q**(n*n + n) * e if abs(term) < eps1: break s += term s = s * ctx.nthroot(q, 4) return s @defun def _jacobi_theta3a(ctx, z, q): """ case ctx._im(z) != 0 theta3(z, q) = Sum(q**(n*n) * exp(j*2*n*z), n, -inf, inf) max term for n*abs(log(q).real) + ctx._im(z) ~= 0 n0 = int(- ctx._im(z)/abs(log(q).real)) """ n = n0 = int(-ctx._im(z)/abs(ctx._re(ctx.log(q)))) e2 = ctx.expj(2*z) e = e0 = ctx.expj(2*n*z) s = term = q**(n*n) * e eps1 = ctx.eps*abs(term) while 1: n += 1 e = e * e2 term = q**(n*n) * e if abs(term) < eps1: break s += term e = e0 e2 = ctx.expj(-2*z) n = n0 while 1: n -= 1 e = e * e2 term = q**(n*n) * e if abs(term) < eps1: break s += term return s @defun def _djacobi_theta2a(ctx, z, q, nd): """ case ctx._im(z) != 0 dtheta(2, z, q, nd) = j* q**1/4 * Sum(q**(n*n + n) * (2*n+1)*exp(j*(2*n + 1)*z), n=-inf, inf) max term for (2*n0+1)*log(q).real - 2* ctx._im(z) ~= 0 n0 = int(ctx._im(z)/log(q).real - 1/2) """ n = n0 = int(ctx._im(z)/ctx._re(ctx.log(q)) - 1/2) e2 = ctx.expj(2*z) e = e0 = ctx.expj((2*n + 1)*z) a = q**(n*n + n) # leading term term = (2*n+1)**nd * a * e s = term eps1 = ctx.eps*abs(term) while 1: n += 1 e = e * e2 term = (2*n+1)**nd * q**(n*n + n) * e if abs(term) < eps1: break s += term e = e0 e2 = ctx.expj(-2*z) n = n0 while 1: n -= 1 e = e * e2 term = (2*n+1)**nd * q**(n*n + n) * e if abs(term) < eps1: break s += term return ctx.j**nd * s * ctx.nthroot(q, 4) @defun def _djacobi_theta3a(ctx, z, q, nd): """ case ctx._im(z) != 0 djtheta3(z, q, nd) = (2*j)**nd * Sum(q**(n*n) * n**nd * exp(j*2*n*z), n, -inf, inf) max term for minimum n*abs(log(q).real) + ctx._im(z) """ n = n0 = int(-ctx._im(z)/abs(ctx._re(ctx.log(q)))) e2 = ctx.expj(2*z) e = e0 = ctx.expj(2*n*z) a = q**(n*n) * e s = term = n**nd * a if n != 0: eps1 = ctx.eps*abs(term) else: eps1 = ctx.eps*abs(a) while 1: n += 1 e = e * e2 a = q**(n*n) * e term = n**nd * a if n != 0: aterm = abs(term) else: aterm = abs(a) if aterm < eps1: break s += term e = e0 e2 = ctx.expj(-2*z) n = n0 while 1: n -= 1 e = e * e2 a = q**(n*n) * e term = n**nd * a if n != 0: aterm = abs(term) else: aterm = abs(a) if aterm < eps1: break s += term return (2*ctx.j)**nd * s @defun def jtheta(ctx, n, z, q, derivative=0): if derivative: return ctx._djtheta(n, z, q, derivative) z = ctx.convert(z) q = ctx.convert(q) # Implementation note # If ctx._im(z) is close to zero, _jacobi_theta2 and _jacobi_theta3 # are used, # which compute the series starting from n=0 using fixed precision # numbers; # otherwise _jacobi_theta2a and _jacobi_theta3a are used, which compute # the series starting from n=n0, which is the largest term. # TODO: write _jacobi_theta2a and _jacobi_theta3a using fixed-point if abs(q) > ctx.THETA_Q_LIM: raise ValueError('abs(q) > THETA_Q_LIM = %f' % ctx.THETA_Q_LIM) extra = 10 if z: M = ctx.mag(z) if M > 5 or (n == 1 and M < -5): extra += 2*abs(M) cz = 0.5 extra2 = 50 prec0 = ctx.prec try: ctx.prec += extra if n == 1: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._jacobi_theta2(z - ctx.pi/2, q) else: ctx.dps += 10 res = ctx._jacobi_theta2a(z - ctx.pi/2, q) else: res = ctx._jacobi_theta2(z - ctx.pi/2, q) elif n == 2: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._jacobi_theta2(z, q) else: ctx.dps += 10 res = ctx._jacobi_theta2a(z, q) else: res = ctx._jacobi_theta2(z, q) elif n == 3: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._jacobi_theta3(z, q) else: ctx.dps += 10 res = ctx._jacobi_theta3a(z, q) else: res = ctx._jacobi_theta3(z, q) elif n == 4: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._jacobi_theta3(z, -q) else: ctx.dps += 10 res = ctx._jacobi_theta3a(z, -q) else: res = ctx._jacobi_theta3(z, -q) else: raise ValueError finally: ctx.prec = prec0 return res @defun def _djtheta(ctx, n, z, q, derivative=1): z = ctx.convert(z) q = ctx.convert(q) nd = int(derivative) if abs(q) > ctx.THETA_Q_LIM: raise ValueError('abs(q) > THETA_Q_LIM = %f' % ctx.THETA_Q_LIM) extra = 10 + ctx.prec * nd // 10 if z: M = ctx.mag(z) if M > 5 or (n != 1 and M < -5): extra += 2*abs(M) cz = 0.5 extra2 = 50 prec0 = ctx.prec try: ctx.prec += extra if n == 1: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._djacobi_theta2(z - ctx.pi/2, q, nd) else: ctx.dps += 10 res = ctx._djacobi_theta2a(z - ctx.pi/2, q, nd) else: res = ctx._djacobi_theta2(z - ctx.pi/2, q, nd) elif n == 2: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._djacobi_theta2(z, q, nd) else: ctx.dps += 10 res = ctx._djacobi_theta2a(z, q, nd) else: res = ctx._djacobi_theta2(z, q, nd) elif n == 3: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._djacobi_theta3(z, q, nd) else: ctx.dps += 10 res = ctx._djacobi_theta3a(z, q, nd) else: res = ctx._djacobi_theta3(z, q, nd) elif n == 4: if ctx._im(z): if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))): ctx.dps += extra2 res = ctx._djacobi_theta3(z, -q, nd) else: ctx.dps += 10 res = ctx._djacobi_theta3a(z, -q, nd) else: res = ctx._djacobi_theta3(z, -q, nd) else: raise ValueError finally: ctx.prec = prec0 return +res mpmath-1.1.0/mpmath/functions/zeta.py000066400000000000000000001070231340375245600176260ustar00rootroot00000000000000from ..libmp.backend import xrange, print_ from .functions import defun, defun_wrapped, defun_static @defun def stieltjes(ctx, n, a=1): n = ctx.convert(n) a = ctx.convert(a) if n < 0: return ctx.bad_domain("Stieltjes constants defined for n >= 0") if hasattr(ctx, "stieltjes_cache"): stieltjes_cache = ctx.stieltjes_cache else: stieltjes_cache = ctx.stieltjes_cache = {} if a == 1: if n == 0: return +ctx.euler if n in stieltjes_cache: prec, s = stieltjes_cache[n] if prec >= ctx.prec: return +s mag = 1 def f(x): xa = x/a v = (xa-ctx.j)*ctx.ln(a-ctx.j*x)**n/(1+xa**2)/(ctx.exp(2*ctx.pi*x)-1) return ctx._re(v) / mag orig = ctx.prec try: # Normalize integrand by approx. magnitude to # speed up quadrature (which uses absolute error) if n > 50: ctx.prec = 20 mag = ctx.quad(f, [0,ctx.inf], maxdegree=3) ctx.prec = orig + 10 + int(n**0.5) s = ctx.quad(f, [0,ctx.inf], maxdegree=20) v = ctx.ln(a)**n/(2*a) - ctx.ln(a)**(n+1)/(n+1) + 2*s/a*mag finally: ctx.prec = orig if a == 1 and ctx.isint(n): stieltjes_cache[n] = (ctx.prec, v) return +v @defun_wrapped def siegeltheta(ctx, t, derivative=0): d = int(derivative) if (t == ctx.inf or t == ctx.ninf): if d < 2: if t == ctx.ninf and d == 0: return ctx.ninf return ctx.inf else: return ctx.zero if d == 0: if ctx._im(t): # XXX: cancellation occurs a = ctx.loggamma(0.25+0.5j*t) b = ctx.loggamma(0.25-0.5j*t) return -ctx.ln(ctx.pi)/2*t - 0.5j*(a-b) else: if ctx.isinf(t): return t return ctx._im(ctx.loggamma(0.25+0.5j*t)) - ctx.ln(ctx.pi)/2*t if d > 0: a = (-0.5j)**(d-1)*ctx.polygamma(d-1, 0.25-0.5j*t) b = (0.5j)**(d-1)*ctx.polygamma(d-1, 0.25+0.5j*t) if ctx._im(t): if d == 1: return -0.5*ctx.log(ctx.pi)+0.25*(a+b) else: return 0.25*(a+b) else: if d == 1: return ctx._re(-0.5*ctx.log(ctx.pi)+0.25*(a+b)) else: return ctx._re(0.25*(a+b)) @defun_wrapped def grampoint(ctx, n): # asymptotic expansion, from # http://mathworld.wolfram.com/GramPoint.html g = 2*ctx.pi*ctx.exp(1+ctx.lambertw((8*n+1)/(8*ctx.e))) return ctx.findroot(lambda t: ctx.siegeltheta(t)-ctx.pi*n, g) @defun_wrapped def siegelz(ctx, t, **kwargs): d = int(kwargs.get("derivative", 0)) t = ctx.convert(t) t1 = ctx._re(t) t2 = ctx._im(t) prec = ctx.prec try: if abs(t1) > 500*prec and t2**2 < t1: v = ctx.rs_z(t, d) if ctx._is_real_type(t): return ctx._re(v) return v except NotImplementedError: pass ctx.prec += 21 e1 = ctx.expj(ctx.siegeltheta(t)) z = ctx.zeta(0.5+ctx.j*t) if d == 0: v = e1*z ctx.prec=prec if ctx._is_real_type(t): return ctx._re(v) return +v z1 = ctx.zeta(0.5+ctx.j*t, derivative=1) theta1 = ctx.siegeltheta(t, derivative=1) if d == 1: v = ctx.j*e1*(z1+z*theta1) ctx.prec=prec if ctx._is_real_type(t): return ctx._re(v) return +v z2 = ctx.zeta(0.5+ctx.j*t, derivative=2) theta2 = ctx.siegeltheta(t, derivative=2) comb1 = theta1**2-ctx.j*theta2 if d == 2: def terms(): return [2*z1*theta1, z2, z*comb1] v = ctx.sum_accurately(terms, 1) v = -e1*v ctx.prec = prec if ctx._is_real_type(t): return ctx._re(v) return +v ctx.prec += 10 z3 = ctx.zeta(0.5+ctx.j*t, derivative=3) theta3 = ctx.siegeltheta(t, derivative=3) comb2 = theta1**3-3*ctx.j*theta1*theta2-theta3 if d == 3: def terms(): return [3*theta1*z2, 3*z1*comb1, z3+z*comb2] v = ctx.sum_accurately(terms, 1) v = -ctx.j*e1*v ctx.prec = prec if ctx._is_real_type(t): return ctx._re(v) return +v z4 = ctx.zeta(0.5+ctx.j*t, derivative=4) theta4 = ctx.siegeltheta(t, derivative=4) def terms(): return [theta1**4, -6*ctx.j*theta1**2*theta2, -3*theta2**2, -4*theta1*theta3, ctx.j*theta4] comb3 = ctx.sum_accurately(terms, 1) if d == 4: def terms(): return [6*theta1**2*z2, -6*ctx.j*z2*theta2, 4*theta1*z3, 4*z1*comb2, z4, z*comb3] v = ctx.sum_accurately(terms, 1) v = e1*v ctx.prec = prec if ctx._is_real_type(t): return ctx._re(v) return +v if d > 4: h = lambda x: ctx.siegelz(x, derivative=4) return ctx.diff(h, t, n=d-4) _zeta_zeros = [ 14.134725142,21.022039639,25.010857580,30.424876126,32.935061588, 37.586178159,40.918719012,43.327073281,48.005150881,49.773832478, 52.970321478,56.446247697,59.347044003,60.831778525,65.112544048, 67.079810529,69.546401711,72.067157674,75.704690699,77.144840069, 79.337375020,82.910380854,84.735492981,87.425274613,88.809111208, 92.491899271,94.651344041,95.870634228,98.831194218,101.317851006, 103.725538040,105.446623052,107.168611184,111.029535543,111.874659177, 114.320220915,116.226680321,118.790782866,121.370125002,122.946829294, 124.256818554,127.516683880,129.578704200,131.087688531,133.497737203, 134.756509753,138.116042055,139.736208952,141.123707404,143.111845808, 146.000982487,147.422765343,150.053520421,150.925257612,153.024693811, 156.112909294,157.597591818,158.849988171,161.188964138,163.030709687, 165.537069188,167.184439978,169.094515416,169.911976479,173.411536520, 174.754191523,176.441434298,178.377407776,179.916484020,182.207078484, 184.874467848,185.598783678,187.228922584,189.416158656,192.026656361, 193.079726604,195.265396680,196.876481841,198.015309676,201.264751944, 202.493594514,204.189671803,205.394697202,207.906258888,209.576509717, 211.690862595,213.347919360,214.547044783,216.169538508,219.067596349, 220.714918839,221.430705555,224.007000255,224.983324670,227.421444280, 229.337413306,231.250188700,231.987235253,233.693404179,236.524229666, ] def _load_zeta_zeros(url): import urllib d = urllib.urlopen(url) L = [float(x) for x in d.readlines()] # Sanity check assert round(L[0]) == 14 _zeta_zeros[:] = L @defun def oldzetazero(ctx, n, url='http://www.dtc.umn.edu/~odlyzko/zeta_tables/zeros1'): n = int(n) if n < 0: return ctx.zetazero(-n).conjugate() if n == 0: raise ValueError("n must be nonzero") if n > len(_zeta_zeros) and n <= 100000: _load_zeta_zeros(url) if n > len(_zeta_zeros): raise NotImplementedError("n too large for zetazeros") return ctx.mpc(0.5, ctx.findroot(ctx.siegelz, _zeta_zeros[n-1])) @defun_wrapped def riemannr(ctx, x): if x == 0: return ctx.zero # Check if a simple asymptotic estimate is accurate enough if abs(x) > 1000: a = ctx.li(x) b = 0.5*ctx.li(ctx.sqrt(x)) if abs(b) < abs(a)*ctx.eps: return a if abs(x) < 0.01: # XXX ctx.prec += int(-ctx.log(abs(x),2)) # Sum Gram's series s = t = ctx.one u = ctx.ln(x) k = 1 while abs(t) > abs(s)*ctx.eps: t = t * u / k s += t / (k * ctx._zeta_int(k+1)) k += 1 return s @defun_static def primepi(ctx, x): x = int(x) if x < 2: return 0 return len(ctx.list_primes(x)) # TODO: fix the interface wrt contexts @defun_wrapped def primepi2(ctx, x): x = int(x) if x < 2: return ctx._iv.zero if x < 2657: return ctx._iv.mpf(ctx.primepi(x)) mid = ctx.li(x) # Schoenfeld's estimate for x >= 2657, assuming RH err = ctx.sqrt(x,rounding='u')*ctx.ln(x,rounding='u')/8/ctx.pi(rounding='d') a = ctx.floor((ctx._iv.mpf(mid)-err).a, rounding='d') b = ctx.ceil((ctx._iv.mpf(mid)+err).b, rounding='u') return ctx._iv.mpf([a,b]) @defun_wrapped def primezeta(ctx, s): if ctx.isnan(s): return s if ctx.re(s) <= 0: raise ValueError("prime zeta function defined only for re(s) > 0") if s == 1: return ctx.inf if s == 0.5: return ctx.mpc(ctx.ninf, ctx.pi) r = ctx.re(s) if r > ctx.prec: return 0.5**s else: wp = ctx.prec + int(r) def terms(): orig = ctx.prec # zeta ~ 1+eps; need to set precision # to get logarithm accurately k = 0 while 1: k += 1 u = ctx.moebius(k) if not u: continue ctx.prec = wp t = u*ctx.ln(ctx.zeta(k*s))/k if not t: return #print ctx.prec, ctx.nstr(t) ctx.prec = orig yield t return ctx.sum_accurately(terms) # TODO: for bernpoly and eulerpoly, ensure that all exact zeros are covered @defun_wrapped def bernpoly(ctx, n, z): # Slow implementation: #return sum(ctx.binomial(n,k)*ctx.bernoulli(k)*z**(n-k) for k in xrange(0,n+1)) n = int(n) if n < 0: raise ValueError("Bernoulli polynomials only defined for n >= 0") if z == 0 or (z == 1 and n > 1): return ctx.bernoulli(n) if z == 0.5: return (ctx.ldexp(1,1-n)-1)*ctx.bernoulli(n) if n <= 3: if n == 0: return z ** 0 if n == 1: return z - 0.5 if n == 2: return (6*z*(z-1)+1)/6 if n == 3: return z*(z*(z-1.5)+0.5) if ctx.isinf(z): return z ** n if ctx.isnan(z): return z if abs(z) > 2: def terms(): t = ctx.one yield t r = ctx.one/z k = 1 while k <= n: t = t*(n+1-k)/k*r if not (k > 2 and k & 1): yield t*ctx.bernoulli(k) k += 1 return ctx.sum_accurately(terms) * z**n else: def terms(): yield ctx.bernoulli(n) t = ctx.one k = 1 while k <= n: t = t*(n+1-k)/k * z m = n-k if not (m > 2 and m & 1): yield t*ctx.bernoulli(m) k += 1 return ctx.sum_accurately(terms) @defun_wrapped def eulerpoly(ctx, n, z): n = int(n) if n < 0: raise ValueError("Euler polynomials only defined for n >= 0") if n <= 2: if n == 0: return z ** 0 if n == 1: return z - 0.5 if n == 2: return z*(z-1) if ctx.isinf(z): return z**n if ctx.isnan(z): return z m = n+1 if z == 0: return -2*(ctx.ldexp(1,m)-1)*ctx.bernoulli(m)/m * z**0 if z == 1: return 2*(ctx.ldexp(1,m)-1)*ctx.bernoulli(m)/m * z**0 if z == 0.5: if n % 2: return ctx.zero # Use exact code for Euler numbers if n < 100 or n*ctx.mag(0.46839865*n) < ctx.prec*0.25: return ctx.ldexp(ctx._eulernum(n), -n) # http://functions.wolfram.com/Polynomials/EulerE2/06/01/02/01/0002/ def terms(): t = ctx.one k = 0 w = ctx.ldexp(1,n+2) while 1: v = n-k+1 if not (v > 2 and v & 1): yield (2-w)*ctx.bernoulli(v)*t k += 1 if k > n: break t = t*z*(n-k+2)/k w *= 0.5 return ctx.sum_accurately(terms) / m @defun def eulernum(ctx, n, exact=False): n = int(n) if exact: return int(ctx._eulernum(n)) if n < 100: return ctx.mpf(ctx._eulernum(n)) if n % 2: return ctx.zero return ctx.ldexp(ctx.eulerpoly(n,0.5), n) # TODO: this should be implemented low-level def polylog_series(ctx, s, z): tol = +ctx.eps l = ctx.zero k = 1 zk = z while 1: term = zk / k**s l += term if abs(term) < tol: break zk *= z k += 1 return l def polylog_continuation(ctx, n, z): if n < 0: return z*0 twopij = 2j * ctx.pi a = -twopij**n/ctx.fac(n) * ctx.bernpoly(n, ctx.ln(z)/twopij) if ctx._is_real_type(z) and z < 0: a = ctx._re(a) if ctx._im(z) < 0 or (ctx._im(z) == 0 and ctx._re(z) >= 1): a -= twopij*ctx.ln(z)**(n-1)/ctx.fac(n-1) return a def polylog_unitcircle(ctx, n, z): tol = +ctx.eps if n > 1: l = ctx.zero logz = ctx.ln(z) logmz = ctx.one m = 0 while 1: if (n-m) != 1: term = ctx.zeta(n-m) * logmz / ctx.fac(m) if term and abs(term) < tol: break l += term logmz *= logz m += 1 l += ctx.ln(z)**(n-1)/ctx.fac(n-1)*(ctx.harmonic(n-1)-ctx.ln(-ctx.ln(z))) elif n < 1: # else l = ctx.fac(-n)*(-ctx.ln(z))**(n-1) logz = ctx.ln(z) logkz = ctx.one k = 0 while 1: b = ctx.bernoulli(k-n+1) if b: term = b*logkz/(ctx.fac(k)*(k-n+1)) if abs(term) < tol: break l -= term logkz *= logz k += 1 else: raise ValueError if ctx._is_real_type(z) and z < 0: l = ctx._re(l) return l def polylog_general(ctx, s, z): v = ctx.zero u = ctx.ln(z) if not abs(u) < 5: # theoretically |u| < 2*pi j = ctx.j v = 1-s y = ctx.ln(-z)/(2*ctx.pi*j) return ctx.gamma(v)*(j**v*ctx.zeta(v,0.5+y) + j**-v*ctx.zeta(v,0.5-y))/(2*ctx.pi)**v t = 1 k = 0 while 1: term = ctx.zeta(s-k) * t if abs(term) < ctx.eps: break v += term k += 1 t *= u t /= k return ctx.gamma(1-s)*(-u)**(s-1) + v @defun_wrapped def polylog(ctx, s, z): s = ctx.convert(s) z = ctx.convert(z) if z == 1: return ctx.zeta(s) if z == -1: return -ctx.altzeta(s) if s == 0: return z/(1-z) if s == 1: return -ctx.ln(1-z) if s == -1: return z/(1-z)**2 if abs(z) <= 0.75 or (not ctx.isint(s) and abs(z) < 0.9): return polylog_series(ctx, s, z) if abs(z) >= 1.4 and ctx.isint(s): return (-1)**(s+1)*polylog_series(ctx, s, 1/z) + polylog_continuation(ctx, s, z) if ctx.isint(s): return polylog_unitcircle(ctx, int(s), z) return polylog_general(ctx, s, z) @defun_wrapped def clsin(ctx, s, z, pi=False): if ctx.isint(s) and s < 0 and int(s) % 2 == 1: return z*0 if pi: a = ctx.expjpi(z) else: a = ctx.expj(z) if ctx._is_real_type(z) and ctx._is_real_type(s): return ctx.im(ctx.polylog(s,a)) b = 1/a return (-0.5j)*(ctx.polylog(s,a) - ctx.polylog(s,b)) @defun_wrapped def clcos(ctx, s, z, pi=False): if ctx.isint(s) and s < 0 and int(s) % 2 == 0: return z*0 if pi: a = ctx.expjpi(z) else: a = ctx.expj(z) if ctx._is_real_type(z) and ctx._is_real_type(s): return ctx.re(ctx.polylog(s,a)) b = 1/a return 0.5*(ctx.polylog(s,a) + ctx.polylog(s,b)) @defun def altzeta(ctx, s, **kwargs): try: return ctx._altzeta(s, **kwargs) except NotImplementedError: return ctx._altzeta_generic(s) @defun_wrapped def _altzeta_generic(ctx, s): if s == 1: return ctx.ln2 + 0*s return -ctx.powm1(2, 1-s) * ctx.zeta(s) @defun def zeta(ctx, s, a=1, derivative=0, method=None, **kwargs): d = int(derivative) if a == 1 and not (d or method): try: return ctx._zeta(s, **kwargs) except NotImplementedError: pass s = ctx.convert(s) prec = ctx.prec method = kwargs.get('method') verbose = kwargs.get('verbose') if (not s) and (not derivative): return ctx.mpf(0.5) - ctx._convert_param(a)[0] if a == 1 and method != 'euler-maclaurin': im = abs(ctx._im(s)) re = abs(ctx._re(s)) #if (im < prec or method == 'borwein') and not derivative: # try: # if verbose: # print "zeta: Attempting to use the Borwein algorithm" # return ctx._zeta(s, **kwargs) # except NotImplementedError: # if verbose: # print "zeta: Could not use the Borwein algorithm" # pass if abs(im) > 500*prec and 10*re < prec and derivative <= 4 or \ method == 'riemann-siegel': try: # py2.4 compatible try block try: if verbose: print("zeta: Attempting to use the Riemann-Siegel algorithm") return ctx.rs_zeta(s, derivative, **kwargs) except NotImplementedError: if verbose: print("zeta: Could not use the Riemann-Siegel algorithm") pass finally: ctx.prec = prec if s == 1: return ctx.inf abss = abs(s) if abss == ctx.inf: if ctx.re(s) == ctx.inf: if d == 0: return ctx.one return ctx.zero return s*0 elif ctx.isnan(abss): return 1/s if ctx.re(s) > 2*ctx.prec and a == 1 and not derivative: return ctx.one + ctx.power(2, -s) return +ctx._hurwitz(s, a, d, **kwargs) @defun def _hurwitz(ctx, s, a=1, d=0, **kwargs): prec = ctx.prec verbose = kwargs.get('verbose') try: extraprec = 10 ctx.prec += extraprec # We strongly want to special-case rational a a, atype = ctx._convert_param(a) if ctx.re(s) < 0: if verbose: print("zeta: Attempting reflection formula") try: return _hurwitz_reflection(ctx, s, a, d, atype) except NotImplementedError: pass if verbose: print("zeta: Reflection formula failed") if verbose: print("zeta: Using the Euler-Maclaurin algorithm") while 1: ctx.prec = prec + extraprec T1, T2 = _hurwitz_em(ctx, s, a, d, prec+10, verbose) cancellation = ctx.mag(T1) - ctx.mag(T1+T2) if verbose: print_("Term 1:", T1) print_("Term 2:", T2) print_("Cancellation:", cancellation, "bits") if cancellation < extraprec: return T1 + T2 else: extraprec = max(2*extraprec, min(cancellation + 5, 100*prec)) if extraprec > kwargs.get('maxprec', 100*prec): raise ctx.NoConvergence("zeta: too much cancellation") finally: ctx.prec = prec def _hurwitz_reflection(ctx, s, a, d, atype): # TODO: implement for derivatives if d != 0: raise NotImplementedError res = ctx.re(s) negs = -s # Integer reflection formula if ctx.isnpint(s): n = int(res) if n <= 0: return ctx.bernpoly(1-n, a) / (n-1) if not (atype == 'Q' or atype == 'Z'): raise NotImplementedError t = 1-s # We now require a to be standardized v = 0 shift = 0 b = a while ctx.re(b) > 1: b -= 1 v -= b**negs shift -= 1 while ctx.re(b) <= 0: v += b**negs b += 1 shift += 1 # Rational reflection formula try: p, q = a._mpq_ except: assert a == int(a) p = int(a) q = 1 p += shift*q assert 1 <= p <= q g = ctx.fsum(ctx.cospi(t/2-2*k*b)*ctx._hurwitz(t,(k,q)) \ for k in range(1,q+1)) g *= 2*ctx.gamma(t)/(2*ctx.pi*q)**t v += g return v def _hurwitz_em(ctx, s, a, d, prec, verbose): # May not be converted at this point a = ctx.convert(a) tol = -prec # Estimate number of terms for Euler-Maclaurin summation; could be improved M1 = 0 M2 = prec // 3 N = M2 lsum = 0 # This speeds up the recurrence for derivatives if ctx.isint(s): s = int(ctx._re(s)) s1 = s-1 while 1: # Truncated L-series l = ctx._zetasum(s, M1+a, M2-M1-1, [d])[0][0] #if d: # l = ctx.fsum((-ctx.ln(n+a))**d * (n+a)**negs for n in range(M1,M2)) #else: # l = ctx.fsum((n+a)**negs for n in range(M1,M2)) lsum += l M2a = M2+a logM2a = ctx.ln(M2a) logM2ad = logM2a**d logs = [logM2ad] logr = 1/logM2a rM2a = 1/M2a M2as = M2a**(-s) if d: tailsum = ctx.gammainc(d+1, s1*logM2a) / s1**(d+1) else: tailsum = 1/((s1)*(M2a)**s1) tailsum += 0.5 * logM2ad * M2as U = [1] r = M2as fact = 2 for j in range(1, N+1): # TODO: the following could perhaps be tidied a bit j2 = 2*j if j == 1: upds = [1] else: upds = [j2-2, j2-1] for m in upds: D = min(m,d+1) if m <= d: logs.append(logs[-1] * logr) Un = [0]*(D+1) for i in xrange(D): Un[i] = (1-m-s)*U[i] for i in xrange(1,D+1): Un[i] += (d-(i-1))*U[i-1] U = Un r *= rM2a t = ctx.fdot(U, logs) * r * ctx.bernoulli(j2)/(-fact) tailsum += t if ctx.mag(t) < tol: return lsum, (-1)**d * tailsum fact *= (j2+1)*(j2+2) if verbose: print_("Sum range:", M1, M2, "term magnitude", ctx.mag(t), "tolerance", tol) M1, M2 = M2, M2*2 if ctx.re(s) < 0: N += N//2 @defun def _zetasum(ctx, s, a, n, derivatives=[0], reflect=False): """ Returns [xd0,xd1,...,xdr], [yd0,yd1,...ydr] where xdk = D^k ( 1/a^s + 1/(a+1)^s + ... + 1/(a+n)^s ) ydk = D^k conj( 1/a^(1-s) + 1/(a+1)^(1-s) + ... + 1/(a+n)^(1-s) ) D^k = kth derivative with respect to s, k ranges over the given list of derivatives (which should consist of either a single element or a range 0,1,...r). If reflect=False, the ydks are not computed. """ #print "zetasum", s, a, n # don't use the fixed-point code if there are large exponentials if abs(ctx.re(s)) < 0.5 * ctx.prec: try: return ctx._zetasum_fast(s, a, n, derivatives, reflect) except NotImplementedError: pass negs = ctx.fneg(s, exact=True) have_derivatives = derivatives != [0] have_one_derivative = len(derivatives) == 1 if not reflect: if not have_derivatives: return [ctx.fsum((a+k)**negs for k in xrange(n+1))], [] if have_one_derivative: d = derivatives[0] x = ctx.fsum(ctx.ln(a+k)**d * (a+k)**negs for k in xrange(n+1)) return [(-1)**d * x], [] maxd = max(derivatives) if not have_one_derivative: derivatives = range(maxd+1) xs = [ctx.zero for d in derivatives] if reflect: ys = [ctx.zero for d in derivatives] else: ys = [] for k in xrange(n+1): w = a + k xterm = w ** negs if reflect: yterm = ctx.conj(ctx.one / (w * xterm)) if have_derivatives: logw = -ctx.ln(w) if have_one_derivative: logw = logw ** maxd xs[0] += xterm * logw if reflect: ys[0] += yterm * logw else: t = ctx.one for d in derivatives: xs[d] += xterm * t if reflect: ys[d] += yterm * t t *= logw else: xs[0] += xterm if reflect: ys[0] += yterm return xs, ys @defun def dirichlet(ctx, s, chi=[1], derivative=0): s = ctx.convert(s) q = len(chi) d = int(derivative) if d > 2: raise NotImplementedError("arbitrary order derivatives") prec = ctx.prec try: ctx.prec += 10 if s == 1: have_pole = True for x in chi: if x and x != 1: have_pole = False h = +ctx.eps ctx.prec *= 2*(d+1) s += h if have_pole: return +ctx.inf z = ctx.zero for p in range(1,q+1): if chi[p%q]: if d == 1: z += chi[p%q] * (ctx.zeta(s, (p,q), 1) - \ ctx.zeta(s, (p,q))*ctx.log(q)) else: z += chi[p%q] * ctx.zeta(s, (p,q)) z /= q**s finally: ctx.prec = prec return +z def secondzeta_main_term(ctx, s, a, **kwargs): tol = ctx.eps f = lambda n: ctx.gammainc(0.5*s, a*gamm**2, regularized=True)*gamm**(-s) totsum = term = ctx.zero mg = ctx.inf n = 0 while mg > tol: totsum += term n += 1 gamm = ctx.im(ctx.zetazero_memoized(n)) term = f(n) mg = abs(term) err = 0 if kwargs.get("error"): sg = ctx.re(s) err = 0.5*ctx.pi**(-1)*max(1,sg)*a**(sg-0.5)*ctx.log(gamm/(2*ctx.pi))*\ ctx.gammainc(-0.5, a*gamm**2)/abs(ctx.gamma(s/2)) err = abs(err) return +totsum, err, n def secondzeta_prime_term(ctx, s, a, **kwargs): tol = ctx.eps f = lambda n: ctx.gammainc(0.5*(1-s),0.25*ctx.log(n)**2 * a**(-1))*\ ((0.5*ctx.log(n))**(s-1))*ctx.mangoldt(n)/ctx.sqrt(n)/\ (2*ctx.gamma(0.5*s)*ctx.sqrt(ctx.pi)) totsum = term = ctx.zero mg = ctx.inf n = 1 while mg > tol or n < 9: totsum += term n += 1 term = f(n) if term == 0: mg = ctx.inf else: mg = abs(term) if kwargs.get("error"): err = mg return +totsum, err, n def secondzeta_exp_term(ctx, s, a): if ctx.isint(s) and ctx.re(s) <= 0: m = int(round(ctx.re(s))) if not m & 1: return ctx.mpf('-0.25')**(-m//2) tol = ctx.eps f = lambda n: (0.25*a)**n/((n+0.5*s)*ctx.fac(n)) totsum = ctx.zero term = f(0) mg = ctx.inf n = 0 while mg > tol: totsum += term n += 1 term = f(n) mg = abs(term) v = a**(0.5*s)*totsum/ctx.gamma(0.5*s) return v def secondzeta_singular_term(ctx, s, a, **kwargs): factor = a**(0.5*(s-1))/(4*ctx.sqrt(ctx.pi)*ctx.gamma(0.5*s)) extraprec = ctx.mag(factor) ctx.prec += extraprec factor = a**(0.5*(s-1))/(4*ctx.sqrt(ctx.pi)*ctx.gamma(0.5*s)) tol = ctx.eps f = lambda n: ctx.bernpoly(n,0.75)*(4*ctx.sqrt(a))**n*\ ctx.gamma(0.5*n)/((s+n-1)*ctx.fac(n)) totsum = ctx.zero mg1 = ctx.inf n = 1 term = f(n) mg2 = abs(term) while mg2 > tol and mg2 <= mg1: totsum += term n += 1 term = f(n) totsum += term n +=1 term = f(n) mg1 = mg2 mg2 = abs(term) totsum += term pole = -2*(s-1)**(-2)+(ctx.euler+ctx.log(16*ctx.pi**2*a))*(s-1)**(-1) st = factor*(pole+totsum) err = 0 if kwargs.get("error"): if not ((mg2 > tol) and (mg2 <= mg1)): if mg2 <= tol: err = ctx.mpf(10)**int(ctx.log(abs(factor*tol),10)) if mg2 > mg1: err = ctx.mpf(10)**int(ctx.log(abs(factor*mg1),10)) err = max(err, ctx.eps*1.) ctx.prec -= extraprec return +st, err @defun def secondzeta(ctx, s, a = 0.015, **kwargs): r""" Evaluates the secondary zeta function `Z(s)`, defined for `\mathrm{Re}(s)>1` by .. math :: Z(s) = \sum_{n=1}^{\infty} \frac{1}{\tau_n^s} where `\frac12+i\tau_n` runs through the zeros of `\zeta(s)` with imaginary part positive. `Z(s)` extends to a meromorphic function on `\mathbb{C}` with a double pole at `s=1` and simple poles at the points `-2n` for `n=0`, 1, 2, ... **Examples** >>> from mpmath import * >>> mp.pretty = True; mp.dps = 15 >>> secondzeta(2) 0.023104993115419 >>> xi = lambda s: 0.5*s*(s-1)*pi**(-0.5*s)*gamma(0.5*s)*zeta(s) >>> Xi = lambda t: xi(0.5+t*j) >>> -0.5*diff(Xi,0,n=2)/Xi(0) (0.023104993115419 + 0.0j) We may ask for an approximate error value:: >>> secondzeta(0.5+100j, error=True) ((-0.216272011276718 - 0.844952708937228j), 2.22044604925031e-16) The function has poles at the negative odd integers, and dyadic rational values at the negative even integers:: >>> mp.dps = 30 >>> secondzeta(-8) -0.67236328125 >>> secondzeta(-7) +inf **Implementation notes** The function is computed as sum of four terms `Z(s)=A(s)-P(s)+E(s)-S(s)` respectively main, prime, exponential and singular terms. The main term `A(s)` is computed from the zeros of zeta. The prime term depends on the von Mangoldt function. The singular term is responsible for the poles of the function. The four terms depends on a small parameter `a`. We may change the value of `a`. Theoretically this has no effect on the sum of the four terms, but in practice may be important. A smaller value of the parameter `a` makes `A(s)` depend on a smaller number of zeros of zeta, but `P(s)` uses more values of von Mangoldt function. We may also add a verbose option to obtain data about the values of the four terms. >>> mp.dps = 10 >>> secondzeta(0.5 + 40j, error=True, verbose=True) main term = (-30190318549.138656312556 - 13964804384.624622876523j) computed using 19 zeros of zeta prime term = (132717176.89212754625045 + 188980555.17563978290601j) computed using 9 values of the von Mangoldt function exponential term = (542447428666.07179812536 + 362434922978.80192435203j) singular term = (512124392939.98154322355 + 348281138038.65531023921j) ((0.059471043 + 0.3463514534j), 1.455191523e-11) >>> secondzeta(0.5 + 40j, a=0.04, error=True, verbose=True) main term = (-151962888.19606243907725 - 217930683.90210294051982j) computed using 9 zeros of zeta prime term = (2476659342.3038722372461 + 28711581821.921627163136j) computed using 37 values of the von Mangoldt function exponential term = (178506047114.7838188264 + 819674143244.45677330576j) singular term = (175877424884.22441310708 + 790744630738.28669174871j) ((0.059471043 + 0.3463514534j), 1.455191523e-11) Notice the great cancellation between the four terms. Changing `a`, the four terms are very different numbers but the cancellation gives the good value of Z(s). **References** A. Voros, Zeta functions for the Riemann zeros, Ann. Institute Fourier, 53, (2003) 665--699. A. Voros, Zeta functions over Zeros of Zeta Functions, Lecture Notes of the Unione Matematica Italiana, Springer, 2009. """ s = ctx.convert(s) a = ctx.convert(a) tol = ctx.eps if ctx.isint(s) and ctx.re(s) <= 1: if abs(s-1) < tol*1000: return ctx.inf m = int(round(ctx.re(s))) if m & 1: return ctx.inf else: return ((-1)**(-m//2)*\ ctx.fraction(8-ctx.eulernum(-m,exact=True),2**(-m+3))) prec = ctx.prec try: t3 = secondzeta_exp_term(ctx, s, a) extraprec = max(ctx.mag(t3),0) ctx.prec += extraprec + 3 t1, r1, gt = secondzeta_main_term(ctx,s,a,error='True', verbose='True') t2, r2, pt = secondzeta_prime_term(ctx,s,a,error='True', verbose='True') t4, r4 = secondzeta_singular_term(ctx,s,a,error='True') t3 = secondzeta_exp_term(ctx, s, a) err = r1+r2+r4 t = t1-t2+t3-t4 if kwargs.get("verbose"): print_('main term =', t1) print_(' computed using', gt, 'zeros of zeta') print_('prime term =', t2) print_(' computed using', pt, 'values of the von Mangoldt function') print_('exponential term =', t3) print_('singular term =', t4) finally: ctx.prec = prec if kwargs.get("error"): w = max(ctx.mag(abs(t)),0) err = max(err*2**w, ctx.eps*1.*2**w) return +t, err return +t @defun_wrapped def lerchphi(ctx, z, s, a): r""" Gives the Lerch transcendent, defined for `|z| < 1` and `\Re{a} > 0` by .. math :: \Phi(z,s,a) = \sum_{k=0}^{\infty} \frac{z^k}{(a+k)^s} and generally by the recurrence `\Phi(z,s,a) = z \Phi(z,s,a+1) + a^{-s}` along with the integral representation valid for `\Re{a} > 0` .. math :: \Phi(z,s,a) = \frac{1}{2 a^s} + \int_0^{\infty} \frac{z^t}{(a+t)^s} dt - 2 \int_0^{\infty} \frac{\sin(t \log z - s \operatorname{arctan}(t/a)}{(a^2 + t^2)^{s/2} (e^{2 \pi t}-1)} dt. The Lerch transcendent generalizes the Hurwitz zeta function :func:`zeta` (`z = 1`) and the polylogarithm :func:`polylog` (`a = 1`). **Examples** Several evaluations in terms of simpler functions:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> lerchphi(-1,2,0.5); 4*catalan 3.663862376708876060218414 3.663862376708876060218414 >>> diff(lerchphi, (-1,-2,1), (0,1,0)); 7*zeta(3)/(4*pi**2) 0.2131391994087528954617607 0.2131391994087528954617607 >>> lerchphi(-4,1,1); log(5)/4 0.4023594781085250936501898 0.4023594781085250936501898 >>> lerchphi(-3+2j,1,0.5); 2*atanh(sqrt(-3+2j))/sqrt(-3+2j) (1.142423447120257137774002 + 0.2118232380980201350495795j) (1.142423447120257137774002 + 0.2118232380980201350495795j) Evaluation works for complex arguments and `|z| \ge 1`:: >>> lerchphi(1+2j, 3-j, 4+2j) (0.002025009957009908600539469 + 0.003327897536813558807438089j) >>> lerchphi(-2,2,-2.5) -12.28676272353094275265944 >>> lerchphi(10,10,10) (-4.462130727102185701817349e-11 - 1.575172198981096218823481e-12j) >>> lerchphi(10,10,-10.5) (112658784011940.5605789002 - 498113185.5756221777743631j) Some degenerate cases:: >>> lerchphi(0,1,2) 0.5 >>> lerchphi(0,1,-2) -0.5 Reduction to simpler functions:: >>> lerchphi(1, 4.25+1j, 1) (1.044674457556746668033975 - 0.04674508654012658932271226j) >>> zeta(4.25+1j) (1.044674457556746668033975 - 0.04674508654012658932271226j) >>> lerchphi(1 - 0.5**10, 4.25+1j, 1) (1.044629338021507546737197 - 0.04667768813963388181708101j) >>> lerchphi(3, 4, 1) (1.249503297023366545192592 - 0.2314252413375664776474462j) >>> polylog(4, 3) / 3 (1.249503297023366545192592 - 0.2314252413375664776474462j) >>> lerchphi(3, 4, 1 - 0.5**10) (1.253978063946663945672674 - 0.2316736622836535468765376j) **References** 1. [DLMF]_ section 25.14 """ if z == 0: return a ** (-s) # Faster, but these cases are useful for testing right now if z == 1: return ctx.zeta(s, a) if a == 1: return ctx.polylog(s, z) / z if ctx.re(a) < 1: if ctx.isnpint(a): raise ValueError("Lerch transcendent complex infinity") m = int(ctx.ceil(1-ctx.re(a))) v = ctx.zero zpow = ctx.one for n in xrange(m): v += zpow / (a+n)**s zpow *= z return zpow * ctx.lerchphi(z,s, a+m) + v g = ctx.ln(z) v = 1/(2*a**s) + ctx.gammainc(1-s, -a*g) * (-g)**(s-1) / z**a h = s / 2 r = 2*ctx.pi f = lambda t: ctx.sin(s*ctx.atan(t/a)-t*g) / \ ((a**2+t**2)**h * ctx.expm1(r*t)) v += 2*ctx.quad(f, [0, ctx.inf]) if not ctx.im(z) and not ctx.im(s) and not ctx.im(a) and ctx.re(z) < 1: v = ctx.chop(v) return v mpmath-1.1.0/mpmath/functions/zetazeros.py000066400000000000000000000743471340375245600207250ustar00rootroot00000000000000""" The function zetazero(n) computes the n-th nontrivial zero of zeta(s). The general strategy is to locate a block of Gram intervals B where we know exactly the number of zeros contained and which of those zeros is that which we search. If n <= 400 000 000 we know exactly the Rosser exceptions, contained in a list in this file. Hence for n<=400 000 000 we simply look at these list of exceptions. If our zero is implicated in one of these exceptions we have our block B. In other case we simply locate the good Rosser block containing our zero. For n > 400 000 000 we apply the method of Turing, as complemented by Lehman, Brent and Trudgian to find a suitable B. """ from .functions import defun, defun_wrapped def find_rosser_block_zero(ctx, n): """for n<400 000 000 determines a block were one find our zero""" for k in range(len(_ROSSER_EXCEPTIONS)//2): a=_ROSSER_EXCEPTIONS[2*k][0] b=_ROSSER_EXCEPTIONS[2*k][1] if ((a<= n-2) and (n-1 <= b)): t0 = ctx.grampoint(a) t1 = ctx.grampoint(b) v0 = ctx._fp.siegelz(t0) v1 = ctx._fp.siegelz(t1) my_zero_number = n-a-1 zero_number_block = b-a pattern = _ROSSER_EXCEPTIONS[2*k+1] return (my_zero_number, [a,b], [t0,t1], [v0,v1]) k = n-2 t,v,b = compute_triple_tvb(ctx, k) T = [t] V = [v] while b < 0: k -= 1 t,v,b = compute_triple_tvb(ctx, k) T.insert(0,t) V.insert(0,v) my_zero_number = n-k-1 m = n-1 t,v,b = compute_triple_tvb(ctx, m) T.append(t) V.append(v) while b < 0: m += 1 t,v,b = compute_triple_tvb(ctx, m) T.append(t) V.append(v) return (my_zero_number, [k,m], T, V) def wpzeros(t): """Precision needed to compute higher zeros""" wp = 53 if t > 3*10**8: wp = 63 if t > 10**11: wp = 70 if t > 10**14: wp = 83 return wp def separate_zeros_in_block(ctx, zero_number_block, T, V, limitloop=None, fp_tolerance=None): """Separate the zeros contained in the block T, limitloop determines how long one must search""" if limitloop is None: limitloop = ctx.inf loopnumber = 0 variations = count_variations(V) while ((variations < zero_number_block) and (loopnumber 0): alpha = ctx.sqrt(u/v) b= (alpha*a+b2)/(alpha+1) else: b = (a+b2)/2 if fp_tolerance < 10: w = ctx._fp.siegelz(b) if abs(w)ITERATION_LIMIT)and(loopnumber>2)and(variations+2==zero_number_block): dtMax=0 dtSec=0 kMax = 0 for k1 in range(1,len(T)): dt = T[k1]-T[k1-1] if dt > dtMax: kMax=k1 dtSec = dtMax dtMax = dt elif (dtdtSec): dtSec = dt if dtMax>3*dtSec: f = lambda x: ctx.rs_z(x,derivative=1) t0=T[kMax-1] t1 = T[kMax] t=ctx.findroot(f, (t0,t1), solver ='illinois',verify=False, verbose=False) v = ctx.siegelz(t) if (t0 2*wpz: index +=1 precs = [precs[0] // 2 +3+2*index] + precs ctx.prec = precs[0] + guard r = ctx.findroot(lambda x:ctx.siegelz(x), (t0,t1), solver ='illinois', verbose=False) #print "first step at", ctx.dps, "digits" z=ctx.mpc(0.5,r) for prec in precs[1:]: ctx.prec = prec + guard #print "refining to", ctx.dps, "digits" znew = z - ctx.zeta(z) / ctx.zeta(z, derivative=1) #print "difference", ctx.nstr(abs(z-znew)) z=ctx.mpc(0.5,ctx.im(znew)) return ctx.im(z) def sure_number_block(ctx, n): """The number of good Rosser blocks needed to apply Turing method References: R. P. Brent, On the Zeros of the Riemann Zeta Function in the Critical Strip, Math. Comp. 33 (1979) 1361--1372 T. Trudgian, Improvements to Turing Method, Math. Comp.""" if n < 9*10**5: return(2) g = ctx.grampoint(n-100) lg = ctx._fp.ln(g) brent = 0.0061 * lg**2 +0.08*lg trudgian = 0.0031 * lg**2 +0.11*lg N = ctx.ceil(min(brent,trudgian)) N = int(N) return N def compute_triple_tvb(ctx, n): t = ctx.grampoint(n) v = ctx._fp.siegelz(t) if ctx.mag(abs(v))400 000 000""" sb = sure_number_block(ctx, n) number_goodblocks = 0 m2 = n-1 t, v, b = compute_triple_tvb(ctx, m2) Tf = [t] Vf = [v] while b < 0: m2 += 1 t,v,b = compute_triple_tvb(ctx, m2) Tf.append(t) Vf.append(v) goodpoints = [m2] T = [t] V = [v] while number_goodblocks < 2*sb: m2 += 1 t, v, b = compute_triple_tvb(ctx, m2) T.append(t) V.append(v) while b < 0: m2 += 1 t,v,b = compute_triple_tvb(ctx, m2) T.append(t) V.append(v) goodpoints.append(m2) zn = len(T)-1 A, B, separated =\ separate_zeros_in_block(ctx, zn, T, V, limitloop=ITERATION_LIMIT, fp_tolerance=fp_tolerance) Tf.pop() Tf.extend(A) Vf.pop() Vf.extend(B) if separated: number_goodblocks += 1 else: number_goodblocks = 0 T = [t] V = [v] # Now the same procedure to the left number_goodblocks = 0 m2 = n-2 t, v, b = compute_triple_tvb(ctx, m2) Tf.insert(0,t) Vf.insert(0,v) while b < 0: m2 -= 1 t,v,b = compute_triple_tvb(ctx, m2) Tf.insert(0,t) Vf.insert(0,v) goodpoints.insert(0,m2) T = [t] V = [v] while number_goodblocks < 2*sb: m2 -= 1 t, v, b = compute_triple_tvb(ctx, m2) T.insert(0,t) V.insert(0,v) while b < 0: m2 -= 1 t,v,b = compute_triple_tvb(ctx, m2) T.insert(0,t) V.insert(0,v) goodpoints.insert(0,m2) zn = len(T)-1 A, B, separated =\ separate_zeros_in_block(ctx, zn, T, V, limitloop=ITERATION_LIMIT, fp_tolerance=fp_tolerance) A.pop() Tf = A+Tf B.pop() Vf = B+Vf if separated: number_goodblocks += 1 else: number_goodblocks = 0 T = [t] V = [v] r = goodpoints[2*sb] lg = len(goodpoints) s = goodpoints[lg-2*sb-1] tr, vr, br = compute_triple_tvb(ctx, r) ar = Tf.index(tr) ts, vs, bs = compute_triple_tvb(ctx, s) as1 = Tf.index(ts) T = Tf[ar:as1+1] V = Vf[ar:as1+1] zn = s-r A, B, separated =\ separate_zeros_in_block(ctx, zn,T,V,limitloop=ITERATION_LIMIT, fp_tolerance=fp_tolerance) if separated: return (n-r-1,[r,s],A,B) q = goodpoints[sb] lg = len(goodpoints) t = goodpoints[lg-sb-1] tq, vq, bq = compute_triple_tvb(ctx, q) aq = Tf.index(tq) tt, vt, bt = compute_triple_tvb(ctx, t) at = Tf.index(tt) T = Tf[aq:at+1] V = Vf[aq:at+1] return (n-q-1,[q,t],T,V) def count_variations(V): count = 0 vold = V[0] for n in range(1, len(V)): vnew = V[n] if vold*vnew < 0: count +=1 vold = vnew return count def pattern_construct(ctx, block, T, V): pattern = '(' a = block[0] b = block[1] t0,v0,b0 = compute_triple_tvb(ctx, a) k = 0 k0 = 0 for n in range(a+1,b+1): t1,v1,b1 = compute_triple_tvb(ctx, n) lgT =len(T) while (k < lgT) and (T[k] <= t1): k += 1 L = V[k0:k] L.append(v1) L.insert(0,v0) count = count_variations(L) pattern = pattern + ("%s" % count) if b1 > 0: pattern = pattern + ')(' k0 = k t0,v0,b0 = t1,v1,b1 pattern = pattern[:-1] return pattern @defun def zetazero(ctx, n, info=False, round=True): r""" Computes the `n`-th nontrivial zero of `\zeta(s)` on the critical line, i.e. returns an approximation of the `n`-th largest complex number `s = \frac{1}{2} + ti` for which `\zeta(s) = 0`. Equivalently, the imaginary part `t` is a zero of the Z-function (:func:`~mpmath.siegelz`). **Examples** The first few zeros:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> zetazero(1) (0.5 + 14.13472514173469379045725j) >>> zetazero(2) (0.5 + 21.02203963877155499262848j) >>> zetazero(20) (0.5 + 77.14484006887480537268266j) Verifying that the values are zeros:: >>> for n in range(1,5): ... s = zetazero(n) ... chop(zeta(s)), chop(siegelz(s.imag)) ... (0.0, 0.0) (0.0, 0.0) (0.0, 0.0) (0.0, 0.0) Negative indices give the conjugate zeros (`n = 0` is undefined):: >>> zetazero(-1) (0.5 - 14.13472514173469379045725j) :func:`~mpmath.zetazero` supports arbitrarily large `n` and arbitrary precision:: >>> mp.dps = 15 >>> zetazero(1234567) (0.5 + 727690.906948208j) >>> mp.dps = 50 >>> zetazero(1234567) (0.5 + 727690.9069482075392389420041147142092708393819935j) >>> chop(zeta(_)/_) 0.0 with *info=True*, :func:`~mpmath.zetazero` gives additional information:: >>> mp.dps = 15 >>> zetazero(542964976,info=True) ((0.5 + 209039046.578535j), [542964969, 542964978], 6, '(013111110)') This means that the zero is between Gram points 542964969 and 542964978; it is the 6-th zero between them. Finally (01311110) is the pattern of zeros in this interval. The numbers indicate the number of zeros in each Gram interval (Rosser blocks between parenthesis). In this case there is only one Rosser block of length nine. """ n = int(n) if n < 0: return ctx.zetazero(-n).conjugate() if n == 0: raise ValueError("n must be nonzero") wpinitial = ctx.prec try: wpz, fp_tolerance = comp_fp_tolerance(ctx, n) ctx.prec = wpz if n < 400000000: my_zero_number, block, T, V =\ find_rosser_block_zero(ctx, n) else: my_zero_number, block, T, V =\ search_supergood_block(ctx, n, fp_tolerance) zero_number_block = block[1]-block[0] T, V, separated = separate_zeros_in_block(ctx, zero_number_block, T, V, limitloop=ctx.inf, fp_tolerance=fp_tolerance) if info: pattern = pattern_construct(ctx,block,T,V) prec = max(wpinitial, wpz) t = separate_my_zero(ctx, my_zero_number, zero_number_block,T,V,prec) v = ctx.mpc(0.5,t) finally: ctx.prec = wpinitial if round: v =+v if info: return (v,block,my_zero_number,pattern) else: return v def gram_index(ctx, t): if t > 10**13: wp = 3*ctx.log(t, 10) else: wp = 0 prec = ctx.prec try: ctx.prec += wp x0 = (t/(2*ctx.pi))*ctx.log(t/(2*ctx.pi)) h = ctx.findroot(lambda x:ctx.siegeltheta(t)-ctx.pi*x, x0) h = int(h) finally: ctx.prec = prec return(h) def count_to(ctx, t, T, V): count = 0 vold = V[0] told = T[0] tnew = T[1] k = 1 while tnew < t: vnew = V[k] if vold*vnew < 0: count += 1 vold = vnew k += 1 tnew = T[k] a = ctx.siegelz(t) if a*vold < 0: count += 1 return count def comp_fp_tolerance(ctx, n): wpz = wpzeros(n*ctx.log(n)) if n < 15*10**8: fp_tolerance = 0.0005 elif n <= 10**14: fp_tolerance = 0.1 else: fp_tolerance = 100 return wpz, fp_tolerance @defun def nzeros(ctx, t): r""" Computes the number of zeros of the Riemann zeta function in `(0,1) \times (0,t]`, usually denoted by `N(t)`. **Examples** The first zero has imaginary part between 14 and 15:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> nzeros(14) 0 >>> nzeros(15) 1 >>> zetazero(1) (0.5 + 14.1347251417347j) Some closely spaced zeros:: >>> nzeros(10**7) 21136125 >>> zetazero(21136125) (0.5 + 9999999.32718175j) >>> zetazero(21136126) (0.5 + 10000000.2400236j) >>> nzeros(545439823.215) 1500000001 >>> zetazero(1500000001) (0.5 + 545439823.201985j) >>> zetazero(1500000002) (0.5 + 545439823.325697j) This confirms the data given by J. van de Lune, H. J. J. te Riele and D. T. Winter in 1986. """ if t < 14.1347251417347: return 0 x = gram_index(ctx, t) k = int(ctx.floor(x)) wpinitial = ctx.prec wpz, fp_tolerance = comp_fp_tolerance(ctx, k) ctx.prec = wpz a = ctx.siegelz(t) if k == -1 and a < 0: return 0 elif k == -1 and a > 0: return 1 if k+2 < 400000000: Rblock = find_rosser_block_zero(ctx, k+2) else: Rblock = search_supergood_block(ctx, k+2, fp_tolerance) n1, n2 = Rblock[1] if n2-n1 == 1: b = Rblock[3][0] if a*b > 0: ctx.prec = wpinitial return k+1 else: ctx.prec = wpinitial return k+2 my_zero_number,block, T, V = Rblock zero_number_block = n2-n1 T, V, separated = separate_zeros_in_block(ctx,\ zero_number_block, T, V,\ limitloop=ctx.inf,\ fp_tolerance=fp_tolerance) n = count_to(ctx, t, T, V) ctx.prec = wpinitial return n+n1+1 @defun_wrapped def backlunds(ctx, t): r""" Computes the function `S(t) = \operatorname{arg} \zeta(\frac{1}{2} + it) / \pi`. See Titchmarsh Section 9.3 for details of the definition. **Examples** >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> backlunds(217.3) 0.16302205431184 Generally, the value is a small number. At Gram points it is an integer, frequently equal to 0:: >>> chop(backlunds(grampoint(200))) 0.0 >>> backlunds(extraprec(10)(grampoint)(211)) 1.0 >>> backlunds(extraprec(10)(grampoint)(232)) -1.0 The number of zeros of the Riemann zeta function up to height `t` satisfies `N(t) = \theta(t)/\pi + 1 + S(t)` (see :func:nzeros` and :func:`siegeltheta`):: >>> t = 1234.55 >>> nzeros(t) 842 >>> siegeltheta(t)/pi+1+backlunds(t) 842.0 """ return ctx.nzeros(t)-1-ctx.siegeltheta(t)/ctx.pi """ _ROSSER_EXCEPTIONS is a list of all exceptions to Rosser's rule for n <= 400 000 000. Alternately the entry is of type [n,m], or a string. The string is the zero pattern of the Block and the relevant adjacent. For example (010)3 corresponds to a block composed of three Gram intervals, the first ant third without a zero and the intermediate with a zero. The next Gram interval contain three zeros. So that in total we have 4 zeros in 4 Gram blocks. n and m are the indices of the Gram points of this interval of four Gram intervals. The Rosser exception is therefore formed by the three Gram intervals that are signaled between parenthesis. We have included also some Rosser's exceptions beyond n=400 000 000 that are noted in the literature by some reason. The list is composed from the data published in the references: R. P. Brent, J. van de Lune, H. J. J. te Riele, D. T. Winter, 'On the Zeros of the Riemann Zeta Function in the Critical Strip. II', Math. Comp. 39 (1982) 681--688. See also Corrigenda in Math. Comp. 46 (1986) 771. J. van de Lune, H. J. J. te Riele, 'On the Zeros of the Riemann Zeta Function in the Critical Strip. III', Math. Comp. 41 (1983) 759--767. See also Corrigenda in Math. Comp. 46 (1986) 771. J. van de Lune, 'Sums of Equal Powers of Positive Integers', Dissertation, Vrije Universiteit te Amsterdam, Centrum voor Wiskunde en Informatica, Amsterdam, 1984. Thanks to the authors all this papers and those others that have contributed to make this possible. """ _ROSSER_EXCEPTIONS = \ [[13999525, 13999528], '(00)3', [30783329, 30783332], '(00)3', [30930926, 30930929], '3(00)', [37592215, 37592218], '(00)3', [40870156, 40870159], '(00)3', [43628107, 43628110], '(00)3', [46082042, 46082045], '(00)3', [46875667, 46875670], '(00)3', [49624540, 49624543], '3(00)', [50799238, 50799241], '(00)3', [55221453, 55221456], '3(00)', [56948779, 56948782], '3(00)', [60515663, 60515666], '(00)3', [61331766, 61331770], '(00)40', [69784843, 69784846], '3(00)', [75052114, 75052117], '(00)3', [79545240, 79545243], '3(00)', [79652247, 79652250], '3(00)', [83088043, 83088046], '(00)3', [83689522, 83689525], '3(00)', [85348958, 85348961], '(00)3', [86513820, 86513823], '(00)3', [87947596, 87947599], '3(00)', [88600095, 88600098], '(00)3', [93681183, 93681186], '(00)3', [100316551, 100316554], '3(00)', [100788444, 100788447], '(00)3', [106236172, 106236175], '(00)3', [106941327, 106941330], '3(00)', [107287955, 107287958], '(00)3', [107532016, 107532019], '3(00)', [110571044, 110571047], '(00)3', [111885253, 111885256], '3(00)', [113239783, 113239786], '(00)3', [120159903, 120159906], '(00)3', [121424391, 121424394], '3(00)', [121692931, 121692934], '3(00)', [121934170, 121934173], '3(00)', [122612848, 122612851], '3(00)', [126116567, 126116570], '(00)3', [127936513, 127936516], '(00)3', [128710277, 128710280], '3(00)', [129398902, 129398905], '3(00)', [130461096, 130461099], '3(00)', [131331947, 131331950], '3(00)', [137334071, 137334074], '3(00)', [137832603, 137832606], '(00)3', [138799471, 138799474], '3(00)', [139027791, 139027794], '(00)3', [141617806, 141617809], '(00)3', [144454931, 144454934], '(00)3', [145402379, 145402382], '3(00)', [146130245, 146130248], '3(00)', [147059770, 147059773], '(00)3', [147896099, 147896102], '3(00)', [151097113, 151097116], '(00)3', [152539438, 152539441], '(00)3', [152863168, 152863171], '3(00)', [153522726, 153522729], '3(00)', [155171524, 155171527], '3(00)', [155366607, 155366610], '(00)3', [157260686, 157260689], '3(00)', [157269224, 157269227], '(00)3', [157755123, 157755126], '(00)3', [158298484, 158298487], '3(00)', [160369050, 160369053], '3(00)', [162962787, 162962790], '(00)3', [163724709, 163724712], '(00)3', [164198113, 164198116], '3(00)', [164689301, 164689305], '(00)40', [164880228, 164880231], '3(00)', [166201932, 166201935], '(00)3', [168573836, 168573839], '(00)3', [169750763, 169750766], '(00)3', [170375507, 170375510], '(00)3', [170704879, 170704882], '3(00)', [172000992, 172000995], '3(00)', [173289941, 173289944], '(00)3', [173737613, 173737616], '3(00)', [174102513, 174102516], '(00)3', [174284990, 174284993], '(00)3', [174500513, 174500516], '(00)3', [175710609, 175710612], '(00)3', [176870843, 176870846], '3(00)', [177332732, 177332735], '3(00)', [177902861, 177902864], '3(00)', [179979095, 179979098], '(00)3', [181233726, 181233729], '3(00)', [181625435, 181625438], '(00)3', [182105255, 182105259], '22(00)', [182223559, 182223562], '3(00)', [191116404, 191116407], '3(00)', [191165599, 191165602], '3(00)', [191297535, 191297539], '(00)22', [192485616, 192485619], '(00)3', [193264634, 193264638], '22(00)', [194696968, 194696971], '(00)3', [195876805, 195876808], '(00)3', [195916548, 195916551], '3(00)', [196395160, 196395163], '3(00)', [196676303, 196676306], '(00)3', [197889882, 197889885], '3(00)', [198014122, 198014125], '(00)3', [199235289, 199235292], '(00)3', [201007375, 201007378], '(00)3', [201030605, 201030608], '3(00)', [201184290, 201184293], '3(00)', [201685414, 201685418], '(00)22', [202762875, 202762878], '3(00)', [202860957, 202860960], '3(00)', [203832577, 203832580], '3(00)', [205880544, 205880547], '(00)3', [206357111, 206357114], '(00)3', [207159767, 207159770], '3(00)', [207167343, 207167346], '3(00)', [207482539, 207482543], '3(010)', [207669540, 207669543], '3(00)', [208053426, 208053429], '(00)3', [208110027, 208110030], '3(00)', [209513826, 209513829], '3(00)', [212623522, 212623525], '(00)3', [213841715, 213841718], '(00)3', [214012333, 214012336], '(00)3', [214073567, 214073570], '(00)3', [215170600, 215170603], '3(00)', [215881039, 215881042], '3(00)', [216274604, 216274607], '3(00)', [216957120, 216957123], '3(00)', [217323208, 217323211], '(00)3', [218799264, 218799267], '(00)3', [218803557, 218803560], '3(00)', [219735146, 219735149], '(00)3', [219830062, 219830065], '3(00)', [219897904, 219897907], '(00)3', [221205545, 221205548], '(00)3', [223601929, 223601932], '(00)3', [223907076, 223907079], '3(00)', [223970397, 223970400], '(00)3', [224874044, 224874048], '22(00)', [225291157, 225291160], '(00)3', [227481734, 227481737], '(00)3', [228006442, 228006445], '3(00)', [228357900, 228357903], '(00)3', [228386399, 228386402], '(00)3', [228907446, 228907449], '(00)3', [228984552, 228984555], '3(00)', [229140285, 229140288], '3(00)', [231810024, 231810027], '(00)3', [232838062, 232838065], '3(00)', [234389088, 234389091], '3(00)', [235588194, 235588197], '(00)3', [236645695, 236645698], '(00)3', [236962876, 236962879], '3(00)', [237516723, 237516727], '04(00)', [240004911, 240004914], '(00)3', [240221306, 240221309], '3(00)', [241389213, 241389217], '(010)3', [241549003, 241549006], '(00)3', [241729717, 241729720], '(00)3', [241743684, 241743687], '3(00)', [243780200, 243780203], '3(00)', [243801317, 243801320], '(00)3', [244122072, 244122075], '(00)3', [244691224, 244691227], '3(00)', [244841577, 244841580], '(00)3', [245813461, 245813464], '(00)3', [246299475, 246299478], '(00)3', [246450176, 246450179], '3(00)', [249069349, 249069352], '(00)3', [250076378, 250076381], '(00)3', [252442157, 252442160], '3(00)', [252904231, 252904234], '3(00)', [255145220, 255145223], '(00)3', [255285971, 255285974], '3(00)', [256713230, 256713233], '(00)3', [257992082, 257992085], '(00)3', [258447955, 258447959], '22(00)', [259298045, 259298048], '3(00)', [262141503, 262141506], '(00)3', [263681743, 263681746], '3(00)', [266527881, 266527885], '(010)3', [266617122, 266617125], '(00)3', [266628044, 266628047], '3(00)', [267305763, 267305766], '(00)3', [267388404, 267388407], '3(00)', [267441672, 267441675], '3(00)', [267464886, 267464889], '(00)3', [267554907, 267554910], '3(00)', [269787480, 269787483], '(00)3', [270881434, 270881437], '(00)3', [270997583, 270997586], '3(00)', [272096378, 272096381], '3(00)', [272583009, 272583012], '(00)3', [274190881, 274190884], '3(00)', [274268747, 274268750], '(00)3', [275297429, 275297432], '3(00)', [275545476, 275545479], '3(00)', [275898479, 275898482], '3(00)', [275953000, 275953003], '(00)3', [277117197, 277117201], '(00)22', [277447310, 277447313], '3(00)', [279059657, 279059660], '3(00)', [279259144, 279259147], '3(00)', [279513636, 279513639], '3(00)', [279849069, 279849072], '3(00)', [280291419, 280291422], '(00)3', [281449425, 281449428], '3(00)', [281507953, 281507956], '3(00)', [281825600, 281825603], '(00)3', [282547093, 282547096], '3(00)', [283120963, 283120966], '3(00)', [283323493, 283323496], '(00)3', [284764535, 284764538], '3(00)', [286172639, 286172642], '3(00)', [286688824, 286688827], '(00)3', [287222172, 287222175], '3(00)', [287235534, 287235537], '3(00)', [287304861, 287304864], '3(00)', [287433571, 287433574], '(00)3', [287823551, 287823554], '(00)3', [287872422, 287872425], '3(00)', [288766615, 288766618], '3(00)', [290122963, 290122966], '3(00)', [290450849, 290450853], '(00)22', [291426141, 291426144], '3(00)', [292810353, 292810356], '3(00)', [293109861, 293109864], '3(00)', [293398054, 293398057], '3(00)', [294134426, 294134429], '3(00)', [294216438, 294216441], '(00)3', [295367141, 295367144], '3(00)', [297834111, 297834114], '3(00)', [299099969, 299099972], '3(00)', [300746958, 300746961], '3(00)', [301097423, 301097426], '(00)3', [301834209, 301834212], '(00)3', [302554791, 302554794], '(00)3', [303497445, 303497448], '3(00)', [304165344, 304165347], '3(00)', [304790218, 304790222], '3(010)', [305302352, 305302355], '(00)3', [306785996, 306785999], '3(00)', [307051443, 307051446], '3(00)', [307481539, 307481542], '3(00)', [308605569, 308605572], '3(00)', [309237610, 309237613], '3(00)', [310509287, 310509290], '(00)3', [310554057, 310554060], '3(00)', [310646345, 310646348], '3(00)', [311274896, 311274899], '(00)3', [311894272, 311894275], '3(00)', [312269470, 312269473], '(00)3', [312306601, 312306605], '(00)40', [312683193, 312683196], '3(00)', [314499804, 314499807], '3(00)', [314636802, 314636805], '(00)3', [314689897, 314689900], '3(00)', [314721319, 314721322], '3(00)', [316132890, 316132893], '3(00)', [316217470, 316217474], '(010)3', [316465705, 316465708], '3(00)', [316542790, 316542793], '(00)3', [320822347, 320822350], '3(00)', [321733242, 321733245], '3(00)', [324413970, 324413973], '(00)3', [325950140, 325950143], '(00)3', [326675884, 326675887], '(00)3', [326704208, 326704211], '3(00)', [327596247, 327596250], '3(00)', [328123172, 328123175], '3(00)', [328182212, 328182215], '(00)3', [328257498, 328257501], '3(00)', [328315836, 328315839], '(00)3', [328800974, 328800977], '(00)3', [328998509, 328998512], '3(00)', [329725370, 329725373], '(00)3', [332080601, 332080604], '(00)3', [332221246, 332221249], '(00)3', [332299899, 332299902], '(00)3', [332532822, 332532825], '(00)3', [333334544, 333334548], '(00)22', [333881266, 333881269], '3(00)', [334703267, 334703270], '3(00)', [334875138, 334875141], '3(00)', [336531451, 336531454], '3(00)', [336825907, 336825910], '(00)3', [336993167, 336993170], '(00)3', [337493998, 337494001], '3(00)', [337861034, 337861037], '3(00)', [337899191, 337899194], '(00)3', [337958123, 337958126], '(00)3', [342331982, 342331985], '3(00)', [342676068, 342676071], '3(00)', [347063781, 347063784], '3(00)', [347697348, 347697351], '3(00)', [347954319, 347954322], '3(00)', [348162775, 348162778], '3(00)', [349210702, 349210705], '(00)3', [349212913, 349212916], '3(00)', [349248650, 349248653], '(00)3', [349913500, 349913503], '3(00)', [350891529, 350891532], '3(00)', [351089323, 351089326], '3(00)', [351826158, 351826161], '3(00)', [352228580, 352228583], '(00)3', [352376244, 352376247], '3(00)', [352853758, 352853761], '(00)3', [355110439, 355110442], '(00)3', [355808090, 355808094], '(00)40', [355941556, 355941559], '3(00)', [356360231, 356360234], '(00)3', [356586657, 356586660], '3(00)', [356892926, 356892929], '(00)3', [356908232, 356908235], '3(00)', [357912730, 357912733], '3(00)', [358120344, 358120347], '3(00)', [359044096, 359044099], '(00)3', [360819357, 360819360], '3(00)', [361399662, 361399666], '(010)3', [362361315, 362361318], '(00)3', [363610112, 363610115], '(00)3', [363964804, 363964807], '3(00)', [364527375, 364527378], '(00)3', [365090327, 365090330], '(00)3', [365414539, 365414542], '3(00)', [366738474, 366738477], '3(00)', [368714778, 368714783], '04(010)', [368831545, 368831548], '(00)3', [368902387, 368902390], '(00)3', [370109769, 370109772], '3(00)', [370963333, 370963336], '3(00)', [372541136, 372541140], '3(010)', [372681562, 372681565], '(00)3', [373009410, 373009413], '(00)3', [373458970, 373458973], '3(00)', [375648658, 375648661], '3(00)', [376834728, 376834731], '3(00)', [377119945, 377119948], '(00)3', [377335703, 377335706], '(00)3', [378091745, 378091748], '3(00)', [379139522, 379139525], '3(00)', [380279160, 380279163], '(00)3', [380619442, 380619445], '3(00)', [381244231, 381244234], '3(00)', [382327446, 382327450], '(010)3', [382357073, 382357076], '3(00)', [383545479, 383545482], '3(00)', [384363766, 384363769], '(00)3', [384401786, 384401790], '22(00)', [385198212, 385198215], '3(00)', [385824476, 385824479], '(00)3', [385908194, 385908197], '3(00)', [386946806, 386946809], '3(00)', [387592175, 387592179], '22(00)', [388329293, 388329296], '(00)3', [388679566, 388679569], '3(00)', [388832142, 388832145], '3(00)', [390087103, 390087106], '(00)3', [390190926, 390190930], '(00)22', [390331207, 390331210], '3(00)', [391674495, 391674498], '3(00)', [391937831, 391937834], '3(00)', [391951632, 391951636], '(00)22', [392963986, 392963989], '(00)3', [393007921, 393007924], '3(00)', [393373210, 393373213], '3(00)', [393759572, 393759575], '(00)3', [394036662, 394036665], '(00)3', [395813866, 395813869], '(00)3', [395956690, 395956693], '3(00)', [396031670, 396031673], '3(00)', [397076433, 397076436], '3(00)', [397470601, 397470604], '3(00)', [398289458, 398289461], '3(00)', # [368714778, 368714783], '04(010)', [437953499, 437953504], '04(010)', [526196233, 526196238], '032(00)', [744719566, 744719571], '(010)40', [750375857, 750375862], '032(00)', [958241932, 958241937], '04(010)', [983377342, 983377347], '(00)410', [1003780080, 1003780085], '04(010)', [1070232754, 1070232759], '(00)230', [1209834865, 1209834870], '032(00)', [1257209100, 1257209105], '(00)410', [1368002233, 1368002238], '(00)230' ] mpmath-1.1.0/mpmath/identification.py000066400000000000000000000711261340375245600176500ustar00rootroot00000000000000""" Implements the PSLQ algorithm for integer relation detection, and derivative algorithms for constant recognition. """ from .libmp.backend import xrange from .libmp import int_types, sqrt_fixed # round to nearest integer (can be done more elegantly...) def round_fixed(x, prec): return ((x + (1<<(prec-1))) >> prec) << prec class IdentificationMethods(object): pass def pslq(ctx, x, tol=None, maxcoeff=1000, maxsteps=100, verbose=False): r""" Given a vector of real numbers `x = [x_0, x_1, ..., x_n]`, ``pslq(x)`` uses the PSLQ algorithm to find a list of integers `[c_0, c_1, ..., c_n]` such that .. math :: |c_1 x_1 + c_2 x_2 + ... + c_n x_n| < \mathrm{tol} and such that `\max |c_k| < \mathrm{maxcoeff}`. If no such vector exists, :func:`~mpmath.pslq` returns ``None``. The tolerance defaults to 3/4 of the working precision. **Examples** Find rational approximations for `\pi`:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> pslq([-1, pi], tol=0.01) [22, 7] >>> pslq([-1, pi], tol=0.001) [355, 113] >>> mpf(22)/7; mpf(355)/113; +pi 3.14285714285714 3.14159292035398 3.14159265358979 Pi is not a rational number with denominator less than 1000:: >>> pslq([-1, pi]) >>> To within the standard precision, it can however be approximated by at least one rational number with denominator less than `10^{12}`:: >>> p, q = pslq([-1, pi], maxcoeff=10**12) >>> print(p); print(q) 238410049439 75888275702 >>> mpf(p)/q 3.14159265358979 The PSLQ algorithm can be applied to long vectors. For example, we can investigate the rational (in)dependence of integer square roots:: >>> mp.dps = 30 >>> pslq([sqrt(n) for n in range(2, 5+1)]) >>> >>> pslq([sqrt(n) for n in range(2, 6+1)]) >>> >>> pslq([sqrt(n) for n in range(2, 8+1)]) [2, 0, 0, 0, 0, 0, -1] **Machin formulas** A famous formula for `\pi` is Machin's, .. math :: \frac{\pi}{4} = 4 \operatorname{acot} 5 - \operatorname{acot} 239 There are actually infinitely many formulas of this type. Two others are .. math :: \frac{\pi}{4} = \operatorname{acot} 1 \frac{\pi}{4} = 12 \operatorname{acot} 49 + 32 \operatorname{acot} 57 + 5 \operatorname{acot} 239 + 12 \operatorname{acot} 110443 We can easily verify the formulas using the PSLQ algorithm:: >>> mp.dps = 30 >>> pslq([pi/4, acot(1)]) [1, -1] >>> pslq([pi/4, acot(5), acot(239)]) [1, -4, 1] >>> pslq([pi/4, acot(49), acot(57), acot(239), acot(110443)]) [1, -12, -32, 5, -12] We could try to generate a custom Machin-like formula by running the PSLQ algorithm with a few inverse cotangent values, for example acot(2), acot(3) ... acot(10). Unfortunately, there is a linear dependence among these values, resulting in only that dependence being detected, with a zero coefficient for `\pi`:: >>> pslq([pi] + [acot(n) for n in range(2,11)]) [0, 1, -1, 0, 0, 0, -1, 0, 0, 0] We get better luck by removing linearly dependent terms:: >>> pslq([pi] + [acot(n) for n in range(2,11) if n not in (3, 5)]) [1, -8, 0, 0, 4, 0, 0, 0] In other words, we found the following formula:: >>> 8*acot(2) - 4*acot(7) 3.14159265358979323846264338328 >>> +pi 3.14159265358979323846264338328 **Algorithm** This is a fairly direct translation to Python of the pseudocode given by David Bailey, "The PSLQ Integer Relation Algorithm": http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html The present implementation uses fixed-point instead of floating-point arithmetic, since this is significantly (about 7x) faster. """ n = len(x) if n < 2: raise ValueError("n cannot be less than 2") # At too low precision, the algorithm becomes meaningless prec = ctx.prec if prec < 53: raise ValueError("prec cannot be less than 53") if verbose and prec // max(2,n) < 5: print("Warning: precision for PSLQ may be too low") target = int(prec * 0.75) if tol is None: tol = ctx.mpf(2)**(-target) else: tol = ctx.convert(tol) extra = 60 prec += extra if verbose: print("PSLQ using prec %i and tol %s" % (prec, ctx.nstr(tol))) tol = ctx.to_fixed(tol, prec) assert tol # Convert to fixed-point numbers. The dummy None is added so we can # use 1-based indexing. (This just allows us to be consistent with # Bailey's indexing. The algorithm is 100 lines long, so debugging # a single wrong index can be painful.) x = [None] + [ctx.to_fixed(ctx.mpf(xk), prec) for xk in x] # Sanity check on magnitudes minx = min(abs(xx) for xx in x[1:]) if not minx: raise ValueError("PSLQ requires a vector of nonzero numbers") if minx < tol//100: if verbose: print("STOPPING: (one number is too small)") return None g = sqrt_fixed((4<> prec) s[k] = sqrt_fixed(t, prec) t = s[1] y = x[:] for k in xrange(1, n+1): y[k] = (x[k] << prec) // t s[k] = (s[k] << prec) // t # step 3 for i in xrange(1, n+1): for j in xrange(i+1, n): H[i,j] = 0 if i <= n-1: if s[i]: H[i,i] = (s[i+1] << prec) // s[i] else: H[i,i] = 0 for j in range(1, i): sjj1 = s[j]*s[j+1] if sjj1: H[i,j] = ((-y[i]*y[j])<> prec) for k in xrange(1, j+1): H[i,k] = H[i,k] - (t*H[j,k] >> prec) for k in xrange(1, n+1): A[i,k] = A[i,k] - (t*A[j,k] >> prec) B[k,j] = B[k,j] + (t*B[k,i] >> prec) # Main algorithm for REP in range(maxsteps): # Step 1 m = -1 szmax = -1 for i in range(1, n): h = H[i,i] sz = (g**i * abs(h)) >> (prec*(i-1)) if sz > szmax: m = i szmax = sz # Step 2 y[m], y[m+1] = y[m+1], y[m] tmp = {} for i in xrange(1,n+1): H[m,i], H[m+1,i] = H[m+1,i], H[m,i] for i in xrange(1,n+1): A[m,i], A[m+1,i] = A[m+1,i], A[m,i] for i in xrange(1,n+1): B[i,m], B[i,m+1] = B[i,m+1], B[i,m] # Step 3 if m <= n - 2: t0 = sqrt_fixed((H[m,m]**2 + H[m,m+1]**2)>>prec, prec) # A zero element probably indicates that the precision has # been exhausted. XXX: this could be spurious, due to # using fixed-point arithmetic if not t0: break t1 = (H[m,m] << prec) // t0 t2 = (H[m,m+1] << prec) // t0 for i in xrange(m, n+1): t3 = H[i,m] t4 = H[i,m+1] H[i,m] = (t1*t3+t2*t4) >> prec H[i,m+1] = (-t2*t3+t1*t4) >> prec # Step 4 for i in xrange(m+1, n+1): for j in xrange(min(i-1, m+1), 0, -1): try: t = round_fixed((H[i,j] << prec)//H[j,j], prec) # Precision probably exhausted except ZeroDivisionError: break y[j] = y[j] + ((t*y[i]) >> prec) for k in xrange(1, j+1): H[i,k] = H[i,k] - (t*H[j,k] >> prec) for k in xrange(1, n+1): A[i,k] = A[i,k] - (t*A[j,k] >> prec) B[k,j] = B[k,j] + (t*B[k,i] >> prec) # Until a relation is found, the error typically decreases # slowly (e.g. a factor 1-10) with each step TODO: we could # compare err from two successive iterations. If there is a # large drop (several orders of magnitude), that indicates a # "high quality" relation was detected. Reporting this to # the user somehow might be useful. best_err = maxcoeff<> prec) for j in \ range(1,n+1)] if max(abs(v) for v in vec) < maxcoeff: if verbose: print("FOUND relation at iter %i/%i, error: %s" % \ (REP, maxsteps, ctx.nstr(err / ctx.mpf(2)**prec, 1))) return vec best_err = min(err, best_err) # Calculate a lower bound for the norm. We could do this # more exactly (using the Euclidean norm) but there is probably # no practical benefit. recnorm = max(abs(h) for h in H.values()) if recnorm: norm = ((1 << (2*prec)) // recnorm) >> prec norm //= 100 else: norm = ctx.inf if verbose: print("%i/%i: Error: %8s Norm: %s" % \ (REP, maxsteps, ctx.nstr(best_err / ctx.mpf(2)**prec, 1), norm)) if norm >= maxcoeff: break if verbose: print("CANCELLING after step %i/%i." % (REP, maxsteps)) print("Could not find an integer relation. Norm bound: %s" % norm) return None def findpoly(ctx, x, n=1, **kwargs): r""" ``findpoly(x, n)`` returns the coefficients of an integer polynomial `P` of degree at most `n` such that `P(x) \approx 0`. If no polynomial having `x` as a root can be found, :func:`~mpmath.findpoly` returns ``None``. :func:`~mpmath.findpoly` works by successively calling :func:`~mpmath.pslq` with the vectors `[1, x]`, `[1, x, x^2]`, `[1, x, x^2, x^3]`, ..., `[1, x, x^2, .., x^n]` as input. Keyword arguments given to :func:`~mpmath.findpoly` are forwarded verbatim to :func:`~mpmath.pslq`. In particular, you can specify a tolerance for `P(x)` with ``tol`` and a maximum permitted coefficient size with ``maxcoeff``. For large values of `n`, it is recommended to run :func:`~mpmath.findpoly` at high precision; preferably 50 digits or more. **Examples** By default (degree `n = 1`), :func:`~mpmath.findpoly` simply finds a linear polynomial with a rational root:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> findpoly(0.7) [-10, 7] The generated coefficient list is valid input to ``polyval`` and ``polyroots``:: >>> nprint(polyval(findpoly(phi, 2), phi), 1) -2.0e-16 >>> for r in polyroots(findpoly(phi, 2)): ... print(r) ... -0.618033988749895 1.61803398874989 Numbers of the form `m + n \sqrt p` for integers `(m, n, p)` are solutions to quadratic equations. As we find here, `1+\sqrt 2` is a root of the polynomial `x^2 - 2x - 1`:: >>> findpoly(1+sqrt(2), 2) [1, -2, -1] >>> findroot(lambda x: x**2 - 2*x - 1, 1) 2.4142135623731 Despite only containing square roots, the following number results in a polynomial of degree 4:: >>> findpoly(sqrt(2)+sqrt(3), 4) [1, 0, -10, 0, 1] In fact, `x^4 - 10x^2 + 1` is the *minimal polynomial* of `r = \sqrt 2 + \sqrt 3`, meaning that a rational polynomial of lower degree having `r` as a root does not exist. Given sufficient precision, :func:`~mpmath.findpoly` will usually find the correct minimal polynomial of a given algebraic number. **Non-algebraic numbers** If :func:`~mpmath.findpoly` fails to find a polynomial with given coefficient size and tolerance constraints, that means no such polynomial exists. We can verify that `\pi` is not an algebraic number of degree 3 with coefficients less than 1000:: >>> mp.dps = 15 >>> findpoly(pi, 3) >>> It is always possible to find an algebraic approximation of a number using one (or several) of the following methods: 1. Increasing the permitted degree 2. Allowing larger coefficients 3. Reducing the tolerance One example of each method is shown below:: >>> mp.dps = 15 >>> findpoly(pi, 4) [95, -545, 863, -183, -298] >>> findpoly(pi, 3, maxcoeff=10000) [836, -1734, -2658, -457] >>> findpoly(pi, 3, tol=1e-7) [-4, 22, -29, -2] It is unknown whether Euler's constant is transcendental (or even irrational). We can use :func:`~mpmath.findpoly` to check that if is an algebraic number, its minimal polynomial must have degree at least 7 and a coefficient of magnitude at least 1000000:: >>> mp.dps = 200 >>> findpoly(euler, 6, maxcoeff=10**6, tol=1e-100, maxsteps=1000) >>> Note that the high precision and strict tolerance is necessary for such high-degree runs, since otherwise unwanted low-accuracy approximations will be detected. It may also be necessary to set maxsteps high to prevent a premature exit (before the coefficient bound has been reached). Running with ``verbose=True`` to get an idea what is happening can be useful. """ x = ctx.mpf(x) if n < 1: raise ValueError("n cannot be less than 1") if x == 0: return [1, 0] xs = [ctx.mpf(1)] for i in range(1,n+1): xs.append(x**i) a = ctx.pslq(xs, **kwargs) if a is not None: return a[::-1] def fracgcd(p, q): x, y = p, q while y: x, y = y, x % y if x != 1: p //= x q //= x if q == 1: return p return p, q def pslqstring(r, constants): q = r[0] r = r[1:] s = [] for i in range(len(r)): p = r[i] if p: z = fracgcd(-p,q) cs = constants[i][1] if cs == '1': cs = '' else: cs = '*' + cs if isinstance(z, int_types): if z > 0: term = str(z) + cs else: term = ("(%s)" % z) + cs else: term = ("(%s/%s)" % z) + cs s.append(term) s = ' + '.join(s) if '+' in s or '*' in s: s = '(' + s + ')' return s or '0' def prodstring(r, constants): q = r[0] r = r[1:] num = [] den = [] for i in range(len(r)): p = r[i] if p: z = fracgcd(-p,q) cs = constants[i][1] if isinstance(z, int_types): if abs(z) == 1: t = cs else: t = '%s**%s' % (cs, abs(z)) ([num,den][z<0]).append(t) else: t = '%s**(%s/%s)' % (cs, abs(z[0]), z[1]) ([num,den][z[0]<0]).append(t) num = '*'.join(num) den = '*'.join(den) if num and den: return "(%s)/(%s)" % (num, den) if num: return num if den: return "1/(%s)" % den def quadraticstring(ctx,t,a,b,c): if c < 0: a,b,c = -a,-b,-c u1 = (-b+ctx.sqrt(b**2-4*a*c))/(2*c) u2 = (-b-ctx.sqrt(b**2-4*a*c))/(2*c) if abs(u1-t) < abs(u2-t): if b: s = '((%s+sqrt(%s))/%s)' % (-b,b**2-4*a*c,2*c) else: s = '(sqrt(%s)/%s)' % (-4*a*c,2*c) else: if b: s = '((%s-sqrt(%s))/%s)' % (-b,b**2-4*a*c,2*c) else: s = '(-sqrt(%s)/%s)' % (-4*a*c,2*c) return s # Transformation y = f(x,c), with inverse function x = f(y,c) # The third entry indicates whether the transformation is # redundant when c = 1 transforms = [ (lambda ctx,x,c: x*c, '$y/$c', 0), (lambda ctx,x,c: x/c, '$c*$y', 1), (lambda ctx,x,c: c/x, '$c/$y', 0), (lambda ctx,x,c: (x*c)**2, 'sqrt($y)/$c', 0), (lambda ctx,x,c: (x/c)**2, '$c*sqrt($y)', 1), (lambda ctx,x,c: (c/x)**2, '$c/sqrt($y)', 0), (lambda ctx,x,c: c*x**2, 'sqrt($y)/sqrt($c)', 1), (lambda ctx,x,c: x**2/c, 'sqrt($c)*sqrt($y)', 1), (lambda ctx,x,c: c/x**2, 'sqrt($c)/sqrt($y)', 1), (lambda ctx,x,c: ctx.sqrt(x*c), '$y**2/$c', 0), (lambda ctx,x,c: ctx.sqrt(x/c), '$c*$y**2', 1), (lambda ctx,x,c: ctx.sqrt(c/x), '$c/$y**2', 0), (lambda ctx,x,c: c*ctx.sqrt(x), '$y**2/$c**2', 1), (lambda ctx,x,c: ctx.sqrt(x)/c, '$c**2*$y**2', 1), (lambda ctx,x,c: c/ctx.sqrt(x), '$c**2/$y**2', 1), (lambda ctx,x,c: ctx.exp(x*c), 'log($y)/$c', 0), (lambda ctx,x,c: ctx.exp(x/c), '$c*log($y)', 1), (lambda ctx,x,c: ctx.exp(c/x), '$c/log($y)', 0), (lambda ctx,x,c: c*ctx.exp(x), 'log($y/$c)', 1), (lambda ctx,x,c: ctx.exp(x)/c, 'log($c*$y)', 1), (lambda ctx,x,c: c/ctx.exp(x), 'log($c/$y)', 0), (lambda ctx,x,c: ctx.ln(x*c), 'exp($y)/$c', 0), (lambda ctx,x,c: ctx.ln(x/c), '$c*exp($y)', 1), (lambda ctx,x,c: ctx.ln(c/x), '$c/exp($y)', 0), (lambda ctx,x,c: c*ctx.ln(x), 'exp($y/$c)', 1), (lambda ctx,x,c: ctx.ln(x)/c, 'exp($c*$y)', 1), (lambda ctx,x,c: c/ctx.ln(x), 'exp($c/$y)', 0), ] def identify(ctx, x, constants=[], tol=None, maxcoeff=1000, full=False, verbose=False): r""" Given a real number `x`, ``identify(x)`` attempts to find an exact formula for `x`. This formula is returned as a string. If no match is found, ``None`` is returned. With ``full=True``, a list of matching formulas is returned. As a simple example, :func:`~mpmath.identify` will find an algebraic formula for the golden ratio:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> identify(phi) '((1+sqrt(5))/2)' :func:`~mpmath.identify` can identify simple algebraic numbers and simple combinations of given base constants, as well as certain basic transformations thereof. More specifically, :func:`~mpmath.identify` looks for the following: 1. Fractions 2. Quadratic algebraic numbers 3. Rational linear combinations of the base constants 4. Any of the above after first transforming `x` into `f(x)` where `f(x)` is `1/x`, `\sqrt x`, `x^2`, `\log x` or `\exp x`, either directly or with `x` or `f(x)` multiplied or divided by one of the base constants 5. Products of fractional powers of the base constants and small integers Base constants can be given as a list of strings representing mpmath expressions (:func:`~mpmath.identify` will ``eval`` the strings to numerical values and use the original strings for the output), or as a dict of formula:value pairs. In order not to produce spurious results, :func:`~mpmath.identify` should be used with high precision; preferably 50 digits or more. **Examples** Simple identifications can be performed safely at standard precision. Here the default recognition of rational, algebraic, and exp/log of algebraic numbers is demonstrated:: >>> mp.dps = 15 >>> identify(0.22222222222222222) '(2/9)' >>> identify(1.9662210973805663) 'sqrt(((24+sqrt(48))/8))' >>> identify(4.1132503787829275) 'exp((sqrt(8)/2))' >>> identify(0.881373587019543) 'log(((2+sqrt(8))/2))' By default, :func:`~mpmath.identify` does not recognize `\pi`. At standard precision it finds a not too useful approximation. At slightly increased precision, this approximation is no longer accurate enough and :func:`~mpmath.identify` more correctly returns ``None``:: >>> identify(pi) '(2**(176/117)*3**(20/117)*5**(35/39))/(7**(92/117))' >>> mp.dps = 30 >>> identify(pi) >>> Numbers such as `\pi`, and simple combinations of user-defined constants, can be identified if they are provided explicitly:: >>> identify(3*pi-2*e, ['pi', 'e']) '(3*pi + (-2)*e)' Here is an example using a dict of constants. Note that the constants need not be "atomic"; :func:`~mpmath.identify` can just as well express the given number in terms of expressions given by formulas:: >>> identify(pi+e, {'a':pi+2, 'b':2*e}) '((-2) + 1*a + (1/2)*b)' Next, we attempt some identifications with a set of base constants. It is necessary to increase the precision a bit. >>> mp.dps = 50 >>> base = ['sqrt(2)','pi','log(2)'] >>> identify(0.25, base) '(1/4)' >>> identify(3*pi + 2*sqrt(2) + 5*log(2)/7, base) '(2*sqrt(2) + 3*pi + (5/7)*log(2))' >>> identify(exp(pi+2), base) 'exp((2 + 1*pi))' >>> identify(1/(3+sqrt(2)), base) '((3/7) + (-1/7)*sqrt(2))' >>> identify(sqrt(2)/(3*pi+4), base) 'sqrt(2)/(4 + 3*pi)' >>> identify(5**(mpf(1)/3)*pi*log(2)**2, base) '5**(1/3)*pi*log(2)**2' An example of an erroneous solution being found when too low precision is used:: >>> mp.dps = 15 >>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)']) '((11/25) + (-158/75)*pi + (76/75)*e + (44/15)*sqrt(2))' >>> mp.dps = 50 >>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)']) '1/(3*pi + (-4)*e + 2*sqrt(2))' **Finding approximate solutions** The tolerance ``tol`` defaults to 3/4 of the working precision. Lowering the tolerance is useful for finding approximate matches. We can for example try to generate approximations for pi:: >>> mp.dps = 15 >>> identify(pi, tol=1e-2) '(22/7)' >>> identify(pi, tol=1e-3) '(355/113)' >>> identify(pi, tol=1e-10) '(5**(339/269))/(2**(64/269)*3**(13/269)*7**(92/269))' With ``full=True``, and by supplying a few base constants, ``identify`` can generate almost endless lists of approximations for any number (the output below has been truncated to show only the first few):: >>> for p in identify(pi, ['e', 'catalan'], tol=1e-5, full=True): ... print(p) ... # doctest: +ELLIPSIS e/log((6 + (-4/3)*e)) (3**3*5*e*catalan**2)/(2*7**2) sqrt(((-13) + 1*e + 22*catalan)) log(((-6) + 24*e + 4*catalan)/e) exp(catalan*((-1/5) + (8/15)*e)) catalan*(6 + (-6)*e + 15*catalan) sqrt((5 + 26*e + (-3)*catalan))/e e*sqrt(((-27) + 2*e + 25*catalan)) log(((-1) + (-11)*e + 59*catalan)) ((3/20) + (21/20)*e + (3/20)*catalan) ... The numerical values are roughly as close to `\pi` as permitted by the specified tolerance: >>> e/log(6-4*e/3) 3.14157719846001 >>> 135*e*catalan**2/98 3.14166950419369 >>> sqrt(e-13+22*catalan) 3.14158000062992 >>> log(24*e-6+4*catalan)-1 3.14158791577159 **Symbolic processing** The output formula can be evaluated as a Python expression. Note however that if fractions (like '2/3') are present in the formula, Python's :func:`~mpmath.eval()` may erroneously perform integer division. Note also that the output is not necessarily in the algebraically simplest form:: >>> identify(sqrt(2)) '(sqrt(8)/2)' As a solution to both problems, consider using SymPy's :func:`~mpmath.sympify` to convert the formula into a symbolic expression. SymPy can be used to pretty-print or further simplify the formula symbolically:: >>> from sympy import sympify # doctest: +SKIP >>> sympify(identify(sqrt(2))) # doctest: +SKIP 2**(1/2) Sometimes :func:`~mpmath.identify` can simplify an expression further than a symbolic algorithm:: >>> from sympy import simplify # doctest: +SKIP >>> x = sympify('-1/(-3/2+(1/2)*5**(1/2))*(3/2-1/2*5**(1/2))**(1/2)') # doctest: +SKIP >>> x # doctest: +SKIP (3/2 - 5**(1/2)/2)**(-1/2) >>> x = simplify(x) # doctest: +SKIP >>> x # doctest: +SKIP 2/(6 - 2*5**(1/2))**(1/2) >>> mp.dps = 30 # doctest: +SKIP >>> x = sympify(identify(x.evalf(30))) # doctest: +SKIP >>> x # doctest: +SKIP 1/2 + 5**(1/2)/2 (In fact, this functionality is available directly in SymPy as the function :func:`~mpmath.nsimplify`, which is essentially a wrapper for :func:`~mpmath.identify`.) **Miscellaneous issues and limitations** The input `x` must be a real number. All base constants must be positive real numbers and must not be rationals or rational linear combinations of each other. The worst-case computation time grows quickly with the number of base constants. Already with 3 or 4 base constants, :func:`~mpmath.identify` may require several seconds to finish. To search for relations among a large number of constants, you should consider using :func:`~mpmath.pslq` directly. The extended transformations are applied to x, not the constants separately. As a result, ``identify`` will for example be able to recognize ``exp(2*pi+3)`` with ``pi`` given as a base constant, but not ``2*exp(pi)+3``. It will be able to recognize the latter if ``exp(pi)`` is given explicitly as a base constant. """ solutions = [] def addsolution(s): if verbose: print("Found: ", s) solutions.append(s) x = ctx.mpf(x) # Further along, x will be assumed positive if x == 0: if full: return ['0'] else: return '0' if x < 0: sol = ctx.identify(-x, constants, tol, maxcoeff, full, verbose) if sol is None: return sol if full: return ["-(%s)"%s for s in sol] else: return "-(%s)" % sol if tol: tol = ctx.mpf(tol) else: tol = ctx.eps**0.7 M = maxcoeff if constants: if isinstance(constants, dict): constants = [(ctx.mpf(v), name) for (name, v) in sorted(constants.items())] else: namespace = dict((name, getattr(ctx,name)) for name in dir(ctx)) constants = [(eval(p, namespace), p) for p in constants] else: constants = [] # We always want to find at least rational terms if 1 not in [value for (name, value) in constants]: constants = [(ctx.mpf(1), '1')] + constants # PSLQ with simple algebraic and functional transformations for ft, ftn, red in transforms: for c, cn in constants: if red and cn == '1': continue t = ft(ctx,x,c) # Prevent exponential transforms from wreaking havoc if abs(t) > M**2 or abs(t) < tol: continue # Linear combination of base constants r = ctx.pslq([t] + [a[0] for a in constants], tol, M) s = None if r is not None and max(abs(uw) for uw in r) <= M and r[0]: s = pslqstring(r, constants) # Quadratic algebraic numbers else: q = ctx.pslq([ctx.one, t, t**2], tol, M) if q is not None and len(q) == 3 and q[2]: aa, bb, cc = q if max(abs(aa),abs(bb),abs(cc)) <= M: s = quadraticstring(ctx,t,aa,bb,cc) if s: if cn == '1' and ('/$c' in ftn): s = ftn.replace('$y', s).replace('/$c', '') else: s = ftn.replace('$y', s).replace('$c', cn) addsolution(s) if not full: return solutions[0] if verbose: print(".") # Check for a direct multiplicative formula if x != 1: # Allow fractional powers of fractions ilogs = [2,3,5,7] # Watch out for existing fractional powers of fractions logs = [] for a, s in constants: if not sum(bool(ctx.findpoly(ctx.ln(a)/ctx.ln(i),1)) for i in ilogs): logs.append((ctx.ln(a), s)) logs = [(ctx.ln(i),str(i)) for i in ilogs] + logs r = ctx.pslq([ctx.ln(x)] + [a[0] for a in logs], tol, M) if r is not None and max(abs(uw) for uw in r) <= M and r[0]: addsolution(prodstring(r, logs)) if not full: return solutions[0] if full: return sorted(solutions, key=len) else: return None IdentificationMethods.pslq = pslq IdentificationMethods.findpoly = findpoly IdentificationMethods.identify = identify if __name__ == '__main__': import doctest doctest.testmod() mpmath-1.1.0/mpmath/libmp/000077500000000000000000000000001340375245600154015ustar00rootroot00000000000000mpmath-1.1.0/mpmath/libmp/__init__.py000066400000000000000000000074241340375245600175210ustar00rootroot00000000000000from .libmpf import (prec_to_dps, dps_to_prec, repr_dps, round_down, round_up, round_floor, round_ceiling, round_nearest, to_pickable, from_pickable, ComplexResult, fzero, fnzero, fone, fnone, ftwo, ften, fhalf, fnan, finf, fninf, math_float_inf, round_int, normalize, normalize1, from_man_exp, from_int, to_man_exp, to_int, mpf_ceil, mpf_floor, mpf_nint, mpf_frac, from_float, from_npfloat, from_Decimal, to_float, from_rational, to_rational, to_fixed, mpf_rand, mpf_eq, mpf_hash, mpf_cmp, mpf_lt, mpf_le, mpf_gt, mpf_ge, mpf_pos, mpf_neg, mpf_abs, mpf_sign, mpf_add, mpf_sub, mpf_sum, mpf_mul, mpf_mul_int, mpf_shift, mpf_frexp, mpf_div, mpf_rdiv_int, mpf_mod, mpf_pow_int, mpf_perturb, to_digits_exp, to_str, str_to_man_exp, from_str, from_bstr, to_bstr, mpf_sqrt, mpf_hypot) from .libmpc import (mpc_one, mpc_zero, mpc_two, mpc_half, mpc_is_inf, mpc_is_infnan, mpc_to_str, mpc_to_complex, mpc_hash, mpc_conjugate, mpc_is_nonzero, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_pos, mpc_neg, mpc_shift, mpc_abs, mpc_arg, mpc_floor, mpc_ceil, mpc_nint, mpc_frac, mpc_mul, mpc_square, mpc_mul_mpf, mpc_mul_imag_mpf, mpc_mul_int, mpc_div, mpc_div_mpf, mpc_reciprocal, mpc_mpf_div, complex_int_pow, mpc_pow, mpc_pow_mpf, mpc_pow_int, mpc_sqrt, mpc_nthroot, mpc_cbrt, mpc_exp, mpc_log, mpc_cos, mpc_sin, mpc_tan, mpc_cos_pi, mpc_sin_pi, mpc_cosh, mpc_sinh, mpc_tanh, mpc_atan, mpc_acos, mpc_asin, mpc_asinh, mpc_acosh, mpc_atanh, mpc_fibonacci, mpf_expj, mpf_expjpi, mpc_expj, mpc_expjpi, mpc_cos_sin, mpc_cos_sin_pi) from .libelefun import (ln2_fixed, mpf_ln2, ln10_fixed, mpf_ln10, pi_fixed, mpf_pi, e_fixed, mpf_e, phi_fixed, mpf_phi, degree_fixed, mpf_degree, mpf_pow, mpf_nthroot, mpf_cbrt, log_int_fixed, agm_fixed, mpf_log, mpf_log_hypot, mpf_exp, mpf_cos_sin, mpf_cos, mpf_sin, mpf_tan, mpf_cos_sin_pi, mpf_cos_pi, mpf_sin_pi, mpf_cosh_sinh, mpf_cosh, mpf_sinh, mpf_tanh, mpf_atan, mpf_atan2, mpf_asin, mpf_acos, mpf_asinh, mpf_acosh, mpf_atanh, mpf_fibonacci) from .libhyper import (NoConvergence, make_hyp_summator, mpf_erf, mpf_erfc, mpf_ei, mpc_ei, mpf_e1, mpc_e1, mpf_expint, mpf_ci_si, mpf_ci, mpf_si, mpc_ci, mpc_si, mpf_besseljn, mpc_besseljn, mpf_agm, mpf_agm1, mpc_agm, mpc_agm1, mpf_ellipk, mpc_ellipk, mpf_ellipe, mpc_ellipe) from .gammazeta import (catalan_fixed, mpf_catalan, khinchin_fixed, mpf_khinchin, glaisher_fixed, mpf_glaisher, apery_fixed, mpf_apery, euler_fixed, mpf_euler, mertens_fixed, mpf_mertens, twinprime_fixed, mpf_twinprime, mpf_bernoulli, bernfrac, mpf_gamma_int, mpf_factorial, mpc_factorial, mpf_gamma, mpc_gamma, mpf_loggamma, mpc_loggamma, mpf_rgamma, mpc_rgamma, mpf_gamma_old, mpc_gamma_old, mpf_factorial_old, mpc_factorial_old, mpf_harmonic, mpc_harmonic, mpf_psi0, mpc_psi0, mpf_psi, mpc_psi, mpf_zeta_int, mpf_zeta, mpc_zeta, mpf_altzeta, mpc_altzeta, mpf_zetasum, mpc_zetasum) from .libmpi import (mpi_str, mpi_from_str, mpi_to_str, mpi_eq, mpi_ne, mpi_lt, mpi_le, mpi_gt, mpi_ge, mpi_add, mpi_sub, mpi_delta, mpi_mid, mpi_pos, mpi_neg, mpi_abs, mpi_mul, mpi_div, mpi_exp, mpi_log, mpi_sqrt, mpi_pow_int, mpi_pow, mpi_cos_sin, mpi_cos, mpi_sin, mpi_tan, mpi_cot, mpi_atan, mpi_atan2, mpci_pos, mpci_neg, mpci_add, mpci_sub, mpci_mul, mpci_div, mpci_pow, mpci_abs, mpci_pow, mpci_exp, mpci_log, mpci_cos, mpci_sin, mpi_gamma, mpci_gamma, mpi_loggamma, mpci_loggamma, mpi_rgamma, mpci_rgamma, mpi_factorial, mpci_factorial) from .libintmath import (trailing, bitcount, numeral, bin_to_radix, isqrt, isqrt_small, isqrt_fast, sqrt_fixed, sqrtrem, ifib, ifac, list_primes, isprime, moebius, gcd, eulernum, stirling1, stirling2) from .backend import (gmpy, sage, BACKEND, STRICT, MPZ, MPZ_TYPE, MPZ_ZERO, MPZ_ONE, MPZ_TWO, MPZ_THREE, MPZ_FIVE, int_types, HASH_MODULUS, HASH_BITS) mpmath-1.1.0/mpmath/libmp/backend.py000066400000000000000000000054511340375245600173470ustar00rootroot00000000000000import os import sys #----------------------------------------------------------------------------# # Support GMPY for high-speed large integer arithmetic. # # # # To allow an external module to handle arithmetic, we need to make sure # # that all high-precision variables are declared of the correct type. MPZ # # is the constructor for the high-precision type. It defaults to Python's # # long type but can be assinged another type, typically gmpy.mpz. # # # # MPZ must be used for the mantissa component of an mpf and must be used # # for internal fixed-point operations. # # # # Side-effects # # 1) "is" cannot be used to test for special values. Must use "==". # # 2) There are bugs in GMPY prior to v1.02 so we must use v1.03 or later. # #----------------------------------------------------------------------------# # So we can import it from this module gmpy = None sage = None sage_utils = None if sys.version_info[0] < 3: python3 = False else: python3 = True BACKEND = 'python' from .six import exec_, print_ if not python3: MPZ = long xrange = xrange basestring = basestring else: MPZ = int xrange = range basestring = str # Define constants for calculating hash on Python 3.2. if sys.version >= "3.2": HASH_MODULUS = sys.hash_info.modulus if sys.hash_info.width == 32: HASH_BITS = 31 else: HASH_BITS = 61 else: HASH_MODULUS = None HASH_BITS = None if 'MPMATH_NOGMPY' not in os.environ: try: try: import gmpy2 as gmpy except ImportError: try: import gmpy except ImportError: raise ImportError if gmpy.version() >= '1.03': BACKEND = 'gmpy' MPZ = gmpy.mpz except: pass if 'MPMATH_NOSAGE' not in os.environ: try: import sage.all import sage.libs.mpmath.utils as _sage_utils sage = sage.all sage_utils = _sage_utils BACKEND = 'sage' MPZ = sage.Integer except: pass if 'MPMATH_STRICT' in os.environ: STRICT = True else: STRICT = False MPZ_TYPE = type(MPZ(0)) MPZ_ZERO = MPZ(0) MPZ_ONE = MPZ(1) MPZ_TWO = MPZ(2) MPZ_THREE = MPZ(3) MPZ_FIVE = MPZ(5) try: if BACKEND == 'python': int_types = (int, long) else: int_types = (int, long, MPZ_TYPE) except NameError: if BACKEND == 'python': int_types = (int,) else: int_types = (int, MPZ_TYPE) mpmath-1.1.0/mpmath/libmp/gammazeta.py000066400000000000000000002321161340375245600177260ustar00rootroot00000000000000""" ----------------------------------------------------------------------- This module implements gamma- and zeta-related functions: * Bernoulli numbers * Factorials * The gamma function * Polygamma functions * Harmonic numbers * The Riemann zeta function * Constants related to these functions ----------------------------------------------------------------------- """ import math import sys from .backend import xrange from .backend import MPZ, MPZ_ZERO, MPZ_ONE, MPZ_THREE, gmpy from .libintmath import list_primes, ifac, ifac2, moebius from .libmpf import (\ round_floor, round_ceiling, round_down, round_up, round_nearest, round_fast, lshift, sqrt_fixed, isqrt_fast, fzero, fone, fnone, fhalf, ftwo, finf, fninf, fnan, from_int, to_int, to_fixed, from_man_exp, from_rational, mpf_pos, mpf_neg, mpf_abs, mpf_add, mpf_sub, mpf_mul, mpf_mul_int, mpf_div, mpf_sqrt, mpf_pow_int, mpf_rdiv_int, mpf_perturb, mpf_le, mpf_lt, mpf_gt, mpf_shift, negative_rnd, reciprocal_rnd, bitcount, to_float, mpf_floor, mpf_sign, ComplexResult ) from .libelefun import (\ constant_memo, def_mpf_constant, mpf_pi, pi_fixed, ln2_fixed, log_int_fixed, mpf_ln2, mpf_exp, mpf_log, mpf_pow, mpf_cosh, mpf_cos_sin, mpf_cosh_sinh, mpf_cos_sin_pi, mpf_cos_pi, mpf_sin_pi, ln_sqrt2pi_fixed, mpf_ln_sqrt2pi, sqrtpi_fixed, mpf_sqrtpi, cos_sin_fixed, exp_fixed ) from .libmpc import (\ mpc_zero, mpc_one, mpc_half, mpc_two, mpc_abs, mpc_shift, mpc_pos, mpc_neg, mpc_add, mpc_sub, mpc_mul, mpc_div, mpc_add_mpf, mpc_mul_mpf, mpc_div_mpf, mpc_mpf_div, mpc_mul_int, mpc_pow_int, mpc_log, mpc_exp, mpc_pow, mpc_cos_pi, mpc_sin_pi, mpc_reciprocal, mpc_square, mpc_sub_mpf ) # Catalan's constant is computed using Lupas's rapidly convergent series # (listed on http://mathworld.wolfram.com/CatalansConstant.html) # oo # ___ n-1 8n 2 3 2 # 1 \ (-1) 2 (40n - 24n + 3) [(2n)!] (n!) # K = --- ) ----------------------------------------- # 64 /___ 3 2 # n (2n-1) [(4n)!] # n = 1 @constant_memo def catalan_fixed(prec): prec = prec + 20 a = one = MPZ_ONE << prec s, t, n = 0, 1, 1 while t: a *= 32 * n**3 * (2*n-1) a //= (3-16*n+16*n**2)**2 t = a * (-1)**(n-1) * (40*n**2-24*n+3) // (n**3 * (2*n-1)) s += t n += 1 return s >> (20 + 6) # Khinchin's constant is relatively difficult to compute. Here # we use the rational zeta series # oo 2*n-1 # ___ ___ # \ ` zeta(2*n)-1 \ ` (-1)^(k+1) # log(K)*log(2) = ) ------------ ) ---------- # /___. n /___. k # n = 1 k = 1 # which adds half a digit per term. The essential trick for achieving # reasonable efficiency is to recycle both the values of the zeta # function (essentially Bernoulli numbers) and the partial terms of # the inner sum. # An alternative might be to use K = 2*exp[1/log(2) X] where # / 1 1 [ pi*x*(1-x^2) ] # X = | ------ log [ ------------ ]. # / 0 x(1+x) [ sin(pi*x) ] # and integrate numerically. In practice, this seems to be slightly # slower than the zeta series at high precision. @constant_memo def khinchin_fixed(prec): wp = int(prec + prec**0.5 + 15) s = MPZ_ZERO fac = from_int(4) t = ONE = MPZ_ONE << wp pi = mpf_pi(wp) pipow = twopi2 = mpf_shift(mpf_mul(pi, pi, wp), 2) n = 1 while 1: zeta2n = mpf_abs(mpf_bernoulli(2*n, wp)) zeta2n = mpf_mul(zeta2n, pipow, wp) zeta2n = mpf_div(zeta2n, fac, wp) zeta2n = to_fixed(zeta2n, wp) term = (((zeta2n - ONE) * t) // n) >> wp if term < 100: break #if not n % 10: # print n, math.log(int(abs(term))) s += term t += ONE//(2*n+1) - ONE//(2*n) n += 1 fac = mpf_mul_int(fac, (2*n)*(2*n-1), wp) pipow = mpf_mul(pipow, twopi2, wp) s = (s << wp) // ln2_fixed(wp) K = mpf_exp(from_man_exp(s, -wp), wp) K = to_fixed(K, prec) return K # Glaisher's constant is defined as A = exp(1/2 - zeta'(-1)). # One way to compute it would be to perform direct numerical # differentiation, but computing arbitrary Riemann zeta function # values at high precision is expensive. We instead use the formula # A = exp((6 (-zeta'(2))/pi^2 + log 2 pi + gamma)/12) # and compute zeta'(2) from the series representation # oo # ___ # \ log k # -zeta'(2) = ) ----- # /___ 2 # k # k = 2 # This series converges exceptionally slowly, but can be accelerated # using Euler-Maclaurin formula. The important insight is that the # E-M integral can be done in closed form and that the high order # are given by # n / \ # d | log x | a + b log x # --- | ----- | = ----------- # n | 2 | 2 + n # dx \ x / x # where a and b are integers given by a simple recurrence. Note # that just one logarithm is needed. However, lots of integer # logarithms are required for the initial summation. # This algorithm could possibly be turned into a faster algorithm # for general evaluation of zeta(s) or zeta'(s); this should be # looked into. @constant_memo def glaisher_fixed(prec): wp = prec + 30 # Number of direct terms to sum before applying the Euler-Maclaurin # formula to the tail. TODO: choose more intelligently N = int(0.33*prec + 5) ONE = MPZ_ONE << wp # Euler-Maclaurin, step 1: sum log(k)/k**2 for k from 2 to N-1 s = MPZ_ZERO for k in range(2, N): #print k, N s += log_int_fixed(k, wp) // k**2 logN = log_int_fixed(N, wp) #logN = to_fixed(mpf_log(from_int(N), wp+20), wp) # E-M step 2: integral of log(x)/x**2 from N to inf s += (ONE + logN) // N # E-M step 3: endpoint correction term f(N)/2 s += logN // (N**2 * 2) # E-M step 4: the series of derivatives pN = N**3 a = 1 b = -2 j = 3 fac = from_int(2) k = 1 while 1: # D(2*k-1) * B(2*k) / fac(2*k) [D(n) = nth derivative] D = ((a << wp) + b*logN) // pN D = from_man_exp(D, -wp) B = mpf_bernoulli(2*k, wp) term = mpf_mul(B, D, wp) term = mpf_div(term, fac, wp) term = to_fixed(term, wp) if abs(term) < 100: break #if not k % 10: # print k, math.log(int(abs(term)), 10) s -= term # Advance derivative twice a, b, pN, j = b-a*j, -j*b, pN*N, j+1 a, b, pN, j = b-a*j, -j*b, pN*N, j+1 k += 1 fac = mpf_mul_int(fac, (2*k)*(2*k-1), wp) # A = exp((6*s/pi**2 + log(2*pi) + euler)/12) pi = pi_fixed(wp) s *= 6 s = (s << wp) // (pi**2 >> wp) s += euler_fixed(wp) s += to_fixed(mpf_log(from_man_exp(2*pi, -wp), wp), wp) s //= 12 A = mpf_exp(from_man_exp(s, -wp), wp) return to_fixed(A, prec) # Apery's constant can be computed using the very rapidly convergent # series # oo # ___ 2 10 # \ n 205 n + 250 n + 77 (n!) # zeta(3) = ) (-1) ------------------- ---------- # /___ 64 5 # n = 0 ((2n+1)!) @constant_memo def apery_fixed(prec): prec += 20 d = MPZ_ONE << prec term = MPZ(77) << prec n = 1 s = MPZ_ZERO while term: s += term d *= (n**10) d //= (((2*n+1)**5) * (2*n)**5) term = (-1)**n * (205*(n**2) + 250*n + 77) * d n += 1 return s >> (20 + 6) """ Euler's constant (gamma) is computed using the Brent-McMillan formula, gamma ~= I(n)/J(n) - log(n), where I(n) = sum_{k=0,1,2,...} (n**k / k!)**2 * H(k) J(n) = sum_{k=0,1,2,...} (n**k / k!)**2 H(k) = 1 + 1/2 + 1/3 + ... + 1/k The error is bounded by O(exp(-4n)). Choosing n to be a power of two, 2**p, the logarithm becomes particularly easy to calculate.[1] We use the formulation of Algorithm 3.9 in [2] to make the summation more efficient. Reference: [1] Xavier Gourdon & Pascal Sebah, The Euler constant: gamma http://numbers.computation.free.fr/Constants/Gamma/gamma.pdf [2] Jonathan Borwein & David Bailey, Mathematics by Experiment, A K Peters, 2003 """ @constant_memo def euler_fixed(prec): extra = 30 prec += extra # choose p such that exp(-4*(2**p)) < 2**-n p = int(math.log((prec/4) * math.log(2), 2)) + 1 n = 2**p A = U = -p*ln2_fixed(prec) B = V = MPZ_ONE << prec k = 1 while 1: B = B*n**2//k**2 A = (A*n**2//k + B)//k U += A V += B if max(abs(A), abs(B)) < 100: break k += 1 return (U<<(prec-extra))//V # Use zeta accelerated formulas for the Mertens and twin # prime constants; see # http://mathworld.wolfram.com/MertensConstant.html # http://mathworld.wolfram.com/TwinPrimesConstant.html @constant_memo def mertens_fixed(prec): wp = prec + 20 m = 2 s = mpf_euler(wp) while 1: t = mpf_zeta_int(m, wp) if t == fone: break t = mpf_log(t, wp) t = mpf_mul_int(t, moebius(m), wp) t = mpf_div(t, from_int(m), wp) s = mpf_add(s, t) m += 1 return to_fixed(s, prec) @constant_memo def twinprime_fixed(prec): def I(n): return sum(moebius(d)<<(n//d) for d in xrange(1,n+1) if not n%d)//n wp = 2*prec + 30 res = fone primes = [from_rational(1,p,wp) for p in [2,3,5,7]] ppowers = [mpf_mul(p,p,wp) for p in primes] n = 2 while 1: a = mpf_zeta_int(n, wp) for i in range(4): a = mpf_mul(a, mpf_sub(fone, ppowers[i]), wp) ppowers[i] = mpf_mul(ppowers[i], primes[i], wp) a = mpf_pow_int(a, -I(n), wp) if mpf_pos(a, prec+10, 'n') == fone: break #from libmpf import to_str #print n, to_str(mpf_sub(fone, a), 6) res = mpf_mul(res, a, wp) n += 1 res = mpf_mul(res, from_int(3*15*35), wp) res = mpf_div(res, from_int(4*16*36), wp) return to_fixed(res, prec) mpf_euler = def_mpf_constant(euler_fixed) mpf_apery = def_mpf_constant(apery_fixed) mpf_khinchin = def_mpf_constant(khinchin_fixed) mpf_glaisher = def_mpf_constant(glaisher_fixed) mpf_catalan = def_mpf_constant(catalan_fixed) mpf_mertens = def_mpf_constant(mertens_fixed) mpf_twinprime = def_mpf_constant(twinprime_fixed) #-----------------------------------------------------------------------# # # # Bernoulli numbers # # # #-----------------------------------------------------------------------# MAX_BERNOULLI_CACHE = 3000 r""" Small Bernoulli numbers and factorials are used in numerous summations, so it is critical for speed that sequential computation is fast and that values are cached up to a fairly high threshold. On the other hand, we also want to support fast computation of isolated large numbers. Currently, no such acceleration is provided for integer factorials (though it is for large floating-point factorials, which are computed via gamma if the precision is low enough). For sequential computation of Bernoulli numbers, we use Ramanujan's formula / n + 3 \ B = (A(n) - S(n)) / | | n \ n / where A(n) = (n+3)/3 when n = 0 or 2 (mod 6), A(n) = -(n+3)/6 when n = 4 (mod 6), and [n/6] ___ \ / n + 3 \ S(n) = ) | | * B /___ \ n - 6*k / n-6*k k = 1 For isolated large Bernoulli numbers, we use the Riemann zeta function to calculate a numerical value for B_n. The von Staudt-Clausen theorem can then be used to optionally find the exact value of the numerator and denominator. """ bernoulli_cache = {} f3 = from_int(3) f6 = from_int(6) def bernoulli_size(n): """Accurately estimate the size of B_n (even n > 2 only)""" lgn = math.log(n,2) return int(2.326 + 0.5*lgn + n*(lgn - 4.094)) BERNOULLI_PREC_CUTOFF = bernoulli_size(MAX_BERNOULLI_CACHE) def mpf_bernoulli(n, prec, rnd=None): """Computation of Bernoulli numbers (numerically)""" if n < 2: if n < 0: raise ValueError("Bernoulli numbers only defined for n >= 0") if n == 0: return fone if n == 1: return mpf_neg(fhalf) # For odd n > 1, the Bernoulli numbers are zero if n & 1: return fzero # If precision is extremely high, we can save time by computing # the Bernoulli number at a lower precision that is sufficient to # obtain the exact fraction, round to the exact fraction, and # convert the fraction back to an mpf value at the original precision if prec > BERNOULLI_PREC_CUTOFF and prec > bernoulli_size(n)*1.1 + 1000: p, q = bernfrac(n) return from_rational(p, q, prec, rnd or round_floor) if n > MAX_BERNOULLI_CACHE: return mpf_bernoulli_huge(n, prec, rnd) wp = prec + 30 # Reuse nearby precisions wp += 32 - (prec & 31) cached = bernoulli_cache.get(wp) if cached: numbers, state = cached if n in numbers: if not rnd: return numbers[n] return mpf_pos(numbers[n], prec, rnd) m, bin, bin1 = state if n - m > 10: return mpf_bernoulli_huge(n, prec, rnd) else: if n > 10: return mpf_bernoulli_huge(n, prec, rnd) numbers = {0:fone} m, bin, bin1 = state = [2, MPZ(10), MPZ_ONE] bernoulli_cache[wp] = (numbers, state) while m <= n: #print m case = m % 6 # Accurately estimate size of B_m so we can use # fixed point math without using too much precision szbm = bernoulli_size(m) s = 0 sexp = max(0, szbm) - wp if m < 6: a = MPZ_ZERO else: a = bin1 for j in xrange(1, m//6+1): usign, uman, uexp, ubc = u = numbers[m-6*j] if usign: uman = -uman s += lshift(a*uman, uexp-sexp) # Update inner binomial coefficient j6 = 6*j a *= ((m-5-j6)*(m-4-j6)*(m-3-j6)*(m-2-j6)*(m-1-j6)*(m-j6)) a //= ((4+j6)*(5+j6)*(6+j6)*(7+j6)*(8+j6)*(9+j6)) if case == 0: b = mpf_rdiv_int(m+3, f3, wp) if case == 2: b = mpf_rdiv_int(m+3, f3, wp) if case == 4: b = mpf_rdiv_int(-m-3, f6, wp) s = from_man_exp(s, sexp, wp) b = mpf_div(mpf_sub(b, s, wp), from_int(bin), wp) numbers[m] = b m += 2 # Update outer binomial coefficient bin = bin * ((m+2)*(m+3)) // (m*(m-1)) if m > 6: bin1 = bin1 * ((2+m)*(3+m)) // ((m-7)*(m-6)) state[:] = [m, bin, bin1] return numbers[n] def mpf_bernoulli_huge(n, prec, rnd=None): wp = prec + 10 piprec = wp + int(math.log(n,2)) v = mpf_gamma_int(n+1, wp) v = mpf_mul(v, mpf_zeta_int(n, wp), wp) v = mpf_mul(v, mpf_pow_int(mpf_pi(piprec), -n, wp)) v = mpf_shift(v, 1-n) if not n & 3: v = mpf_neg(v) return mpf_pos(v, prec, rnd or round_fast) def bernfrac(n): r""" Returns a tuple of integers `(p, q)` such that `p/q = B_n` exactly, where `B_n` denotes the `n`-th Bernoulli number. The fraction is always reduced to lowest terms. Note that for `n > 1` and `n` odd, `B_n = 0`, and `(0, 1)` is returned. **Examples** The first few Bernoulli numbers are exactly:: >>> from mpmath import * >>> for n in range(15): ... p, q = bernfrac(n) ... print("%s %s/%s" % (n, p, q)) ... 0 1/1 1 -1/2 2 1/6 3 0/1 4 -1/30 5 0/1 6 1/42 7 0/1 8 -1/30 9 0/1 10 5/66 11 0/1 12 -691/2730 13 0/1 14 7/6 This function works for arbitrarily large `n`:: >>> p, q = bernfrac(10**4) >>> print(q) 2338224387510 >>> print(len(str(p))) 27692 >>> mp.dps = 15 >>> print(mpf(p) / q) -9.04942396360948e+27677 >>> print(bernoulli(10**4)) -9.04942396360948e+27677 .. note :: :func:`~mpmath.bernoulli` computes a floating-point approximation directly, without computing the exact fraction first. This is much faster for large `n`. **Algorithm** :func:`~mpmath.bernfrac` works by computing the value of `B_n` numerically and then using the von Staudt-Clausen theorem [1] to reconstruct the exact fraction. For large `n`, this is significantly faster than computing `B_1, B_2, \ldots, B_2` recursively with exact arithmetic. The implementation has been tested for `n = 10^m` up to `m = 6`. In practice, :func:`~mpmath.bernfrac` appears to be about three times slower than the specialized program calcbn.exe [2] **References** 1. MathWorld, von Staudt-Clausen Theorem: http://mathworld.wolfram.com/vonStaudt-ClausenTheorem.html 2. The Bernoulli Number Page: http://www.bernoulli.org/ """ n = int(n) if n < 3: return [(1, 1), (-1, 2), (1, 6)][n] if n & 1: return (0, 1) q = 1 for k in list_primes(n+1): if not (n % (k-1)): q *= k prec = bernoulli_size(n) + int(math.log(q,2)) + 20 b = mpf_bernoulli(n, prec) p = mpf_mul(b, from_int(q)) pint = to_int(p, round_nearest) return (pint, q) #-----------------------------------------------------------------------# # # # The gamma function (OLD IMPLEMENTATION) # # # #-----------------------------------------------------------------------# """ We compute the real factorial / gamma function using Spouge's approximation x! = (x+a)**(x+1/2) * exp(-x-a) * [c_0 + S(x) + eps] where S(x) is the sum of c_k/(x+k) from k = 1 to a-1 and the coefficients are given by c_0 = sqrt(2*pi) (-1)**(k-1) c_k = ----------- (a-k)**(k-1/2) exp(-k+a), k = 1,2,...,a-1 (k - 1)! As proved by Spouge, if we choose a = log(2)/log(2*pi)*n = 0.38*n, the relative error eps is less than 2^(-n) for any x in the right complex half-plane (assuming a > 2). In practice, it seems that a can be chosen quite a bit lower still (30-50%); this possibility should be investigated. For negative x, we use the reflection formula. References: ----------- John L. Spouge, "Computation of the gamma, digamma, and trigamma functions", SIAM Journal on Numerical Analysis 31 (1994), no. 3, 931-944. """ spouge_cache = {} def calc_spouge_coefficients(a, prec): wp = prec + int(a*1.4) c = [0] * a # b = exp(a-1) b = mpf_exp(from_int(a-1), wp) # e = exp(1) e = mpf_exp(fone, wp) # sqrt(2*pi) sq2pi = mpf_sqrt(mpf_shift(mpf_pi(wp), 1), wp) c[0] = to_fixed(sq2pi, prec) for k in xrange(1, a): # c[k] = ((-1)**(k-1) * (a-k)**k) * b / sqrt(a-k) term = mpf_mul_int(b, ((-1)**(k-1) * (a-k)**k), wp) term = mpf_div(term, mpf_sqrt(from_int(a-k), wp), wp) c[k] = to_fixed(term, prec) # b = b / (e * k) b = mpf_div(b, mpf_mul(e, from_int(k), wp), wp) return c # Cached lookup of coefficients def get_spouge_coefficients(prec): # This exact precision has been used before if prec in spouge_cache: return spouge_cache[prec] for p in spouge_cache: if 0.8 <= prec/float(p) < 1: return spouge_cache[p] # Here we estimate the value of a based on Spouge's inequality for # the relative error a = max(3, int(0.38*prec)) # 0.38 = log(2)/log(2*pi), ~= 1.26*n coefs = calc_spouge_coefficients(a, prec) spouge_cache[prec] = (prec, a, coefs) return spouge_cache[prec] def spouge_sum_real(x, prec, a, c): x = to_fixed(x, prec) s = c[0] for k in xrange(1, a): s += (c[k] << prec) // (x + (k << prec)) return from_man_exp(s, -prec, prec, round_floor) # Unused: for fast computation of gamma(p/q) def spouge_sum_rational(p, q, prec, a, c): s = c[0] for k in xrange(1, a): s += c[k] * q // (p+q*k) return from_man_exp(s, -prec, prec, round_floor) # For a complex number a + b*I, we have # # c_k (a+k)*c_k b * c_k # ------------- = --------- - ------- * I # (a + b*I) + k M M # # 2 2 2 2 2 # where M = (a+k) + b = (a + b ) + (2*a*k + k ) def spouge_sum_complex(re, im, prec, a, c): re = to_fixed(re, prec) im = to_fixed(im, prec) sre, sim = c[0], 0 mag = ((re**2)>>prec) + ((im**2)>>prec) for k in xrange(1, a): M = mag + re*(2*k) + ((k**2) << prec) sre += (c[k] * (re + (k << prec))) // M sim -= (c[k] * im) // M re = from_man_exp(sre, -prec, prec, round_floor) im = from_man_exp(sim, -prec, prec, round_floor) return re, im def mpf_gamma_int_old(n, prec, rounding=round_fast): if n < 1000: return from_int(ifac(n-1), prec, rounding) # XXX: choose the cutoff less arbitrarily size = int(n*math.log(n,2)) if prec > size/20.0: return from_int(ifac(n-1), prec, rounding) return mpf_gamma(from_int(n), prec, rounding) def mpf_factorial_old(x, prec, rounding=round_fast): return mpf_gamma_old(x, prec, rounding, p1=0) def mpc_factorial_old(x, prec, rounding=round_fast): return mpc_gamma_old(x, prec, rounding, p1=0) def mpf_gamma_old(x, prec, rounding=round_fast, p1=1): """ Computes the gamma function of a real floating-point argument. With p1=0, computes a factorial instead. """ sign, man, exp, bc = x if not man: if x == finf: return finf if x == fninf or x == fnan: return fnan # More precision is needed for enormous x. TODO: # use Stirling's formula + Euler-Maclaurin summation size = exp + bc if size > 5: size = int(size * math.log(size,2)) wp = prec + max(0, size) + 15 if exp >= 0: if sign or (p1 and not man): raise ValueError("gamma function pole") # A direct factorial is fastest if exp + bc <= 10: return from_int(ifac((man< 5: size = int(size * math.log(size,2)) reflect = sign or (exp+bc < -1) wp = prec + max(0, size) + 25 # Near x = 0 pole (TODO: other poles) if p1: if size < -prec-5: return mpc_add_mpf(mpc_div(mpc_one, x, 2*prec+10), \ mpf_neg(mpf_euler(2*prec+10)), prec, rounding) elif size < -5: wp += (-2*size) if p1: # Should be done exactly! re_orig = re re = mpf_sub(re, fone, bc+abs(exp)+2) x = re, im if reflect: # Reflection formula wp += 15 pi = mpf_pi(wp), fzero pix = mpc_mul(x, pi, wp) t = mpc_sin_pi(x, wp) u = mpc_sub(mpc_one, x, wp) g = mpc_gamma_old(u, wp) w = mpc_mul(t, g, wp) return mpc_div(pix, w, wp) # Extremely close to the real line? # XXX: reflection formula if iexp+ibc < -wp: a = mpf_gamma_old(re_orig, wp) b = mpf_psi0(re_orig, wp) gamma_diff = mpf_div(a, b, wp) return mpf_pos(a, prec, rounding), mpf_mul(gamma_diff, im, prec, rounding) sprec, a, c = get_spouge_coefficients(wp) s = spouge_sum_complex(re, im, sprec, a, c) # gamma = exp(log(x+a)*(x+0.5) - xpa) * s repa = mpf_add(re, from_int(a), wp) logxpa = mpc_log((repa, im), wp) reph = mpf_add(re, fhalf, wp) t = mpc_sub(mpc_mul(logxpa, (reph, im), wp), (repa, im), wp) t = mpc_mul(mpc_exp(t, wp), s, prec, rounding) return t #-----------------------------------------------------------------------# # # # Polygamma functions # # # #-----------------------------------------------------------------------# r""" For all polygamma (psi) functions, we use the Euler-Maclaurin summation formula. It looks slightly different in the m = 0 and m > 0 cases. For m = 0, we have oo ___ B (0) 1 \ 2 k -2 k psi (z) ~ log z + --- - ) ------ z 2 z /___ (2 k)! k = 1 Experiment shows that the minimum term of the asymptotic series reaches 2^(-p) when Re(z) > 0.11*p. So we simply use the recurrence for psi (equivalent, in fact, to summing to the first few terms directly before applying E-M) to obtain z large enough. Since, very crudely, log z ~= 1 for Re(z) > 1, we can use fixed-point arithmetic (if z is extremely large, log(z) itself is a sufficient approximation, so we can stop there already). For Re(z) << 0, we could use recurrence, but this is of course inefficient for large negative z, so there we use the reflection formula instead. For m > 0, we have N - 1 ___ ~~~(m) [ \ 1 ] 1 1 psi (z) ~ [ ) -------- ] + ---------- + -------- + [ /___ m+1 ] m+1 m k = 1 (z+k) ] 2 (z+N) m (z+N) oo ___ B \ 2 k (m+1) (m+2) ... (m+2k-1) + ) ------ ------------------------ /___ (2 k)! m + 2 k k = 1 (z+N) where ~~~ denotes the function rescaled by 1/((-1)^(m+1) m!). Here again N is chosen to make z+N large enough for the minimum term in the last series to become smaller than eps. TODO: the current estimation of N for m > 0 is *very suboptimal*. TODO: implement the reflection formula for m > 0, Re(z) << 0. It is generally a combination of multiple cotangents. Need to figure out a reasonably simple way to generate these formulas on the fly. TODO: maybe use exact algorithms to compute psi for integral and certain rational arguments, as this can be much more efficient. (On the other hand, the availability of these special values provides a convenient way to test the general algorithm.) """ # Harmonic numbers are just shifted digamma functions # We should calculate these exactly when x is an integer # and when doing so is faster. def mpf_harmonic(x, prec, rnd): if x in (fzero, fnan, finf): return x a = mpf_psi0(mpf_add(fone, x, prec+5), prec) return mpf_add(a, mpf_euler(prec+5, rnd), prec, rnd) def mpc_harmonic(z, prec, rnd): if z[1] == fzero: return (mpf_harmonic(z[0], prec, rnd), fzero) a = mpc_psi0(mpc_add_mpf(z, fone, prec+5), prec) return mpc_add_mpf(a, mpf_euler(prec+5, rnd), prec, rnd) def mpf_psi0(x, prec, rnd=round_fast): """ Computation of the digamma function (psi function of order 0) of a real argument. """ sign, man, exp, bc = x wp = prec + 10 if not man: if x == finf: return x if x == fninf or x == fnan: return fnan if x == fzero or (exp >= 0 and sign): raise ValueError("polygamma pole") # Near 0 -- fixed-point arithmetic becomes bad if exp+bc < -5: v = mpf_psi0(mpf_add(x, fone, prec, rnd), prec, rnd) return mpf_sub(v, mpf_div(fone, x, wp, rnd), prec, rnd) # Reflection formula if sign and exp+bc > 3: c, s = mpf_cos_sin_pi(x, wp) q = mpf_mul(mpf_div(c, s, wp), mpf_pi(wp), wp) p = mpf_psi0(mpf_sub(fone, x, wp), wp) return mpf_sub(p, q, prec, rnd) # The logarithmic term is accurate enough if (not sign) and bc + exp > wp: return mpf_log(mpf_sub(x, fone, wp), prec, rnd) # Initial recurrence to obtain a large enough x m = to_int(x) n = int(0.11*wp) + 2 s = MPZ_ZERO x = to_fixed(x, wp) one = MPZ_ONE << wp if m < n: for k in xrange(m, n): s -= (one << wp) // x x += one x -= one # Logarithmic term s += to_fixed(mpf_log(from_man_exp(x, -wp, wp), wp), wp) # Endpoint term in Euler-Maclaurin expansion s += (one << wp) // (2*x) # Euler-Maclaurin remainder sum x2 = (x*x) >> wp t = one prev = 0 k = 1 while 1: t = (t*x2) >> wp bsign, bman, bexp, bbc = mpf_bernoulli(2*k, wp) offset = (bexp + 2*wp) if offset >= 0: term = (bman << offset) // (t*(2*k)) else: term = (bman >> (-offset)) // (t*(2*k)) if k & 1: s -= term else: s += term if k > 2 and term >= prev: break prev = term k += 1 return from_man_exp(s, -wp, wp, rnd) def mpc_psi0(z, prec, rnd=round_fast): """ Computation of the digamma function (psi function of order 0) of a complex argument. """ re, im = z # Fall back to the real case if im == fzero: return (mpf_psi0(re, prec, rnd), fzero) wp = prec + 20 sign, man, exp, bc = re # Reflection formula if sign and exp+bc > 3: c = mpc_cos_pi(z, wp) s = mpc_sin_pi(z, wp) q = mpc_mul_mpf(mpc_div(c, s, wp), mpf_pi(wp), wp) p = mpc_psi0(mpc_sub(mpc_one, z, wp), wp) return mpc_sub(p, q, prec, rnd) # Just the logarithmic term if (not sign) and bc + exp > wp: return mpc_log(mpc_sub(z, mpc_one, wp), prec, rnd) # Initial recurrence to obtain a large enough z w = to_int(re) n = int(0.11*wp) + 2 s = mpc_zero if w < n: for k in xrange(w, n): s = mpc_sub(s, mpc_reciprocal(z, wp), wp) z = mpc_add_mpf(z, fone, wp) z = mpc_sub(z, mpc_one, wp) # Logarithmic and endpoint term s = mpc_add(s, mpc_log(z, wp), wp) s = mpc_add(s, mpc_div(mpc_half, z, wp), wp) # Euler-Maclaurin remainder sum z2 = mpc_square(z, wp) t = mpc_one prev = mpc_zero k = 1 eps = mpf_shift(fone, -wp+2) while 1: t = mpc_mul(t, z2, wp) bern = mpf_bernoulli(2*k, wp) term = mpc_mpf_div(bern, mpc_mul_int(t, 2*k, wp), wp) s = mpc_sub(s, term, wp) szterm = mpc_abs(term, 10) if k > 2 and mpf_le(szterm, eps): break prev = term k += 1 return s # Currently unoptimized def mpf_psi(m, x, prec, rnd=round_fast): """ Computation of the polygamma function of arbitrary integer order m >= 0, for a real argument x. """ if m == 0: return mpf_psi0(x, prec, rnd=round_fast) return mpc_psi(m, (x, fzero), prec, rnd)[0] def mpc_psi(m, z, prec, rnd=round_fast): """ Computation of the polygamma function of arbitrary integer order m >= 0, for a complex argument z. """ if m == 0: return mpc_psi0(z, prec, rnd) re, im = z wp = prec + 20 sign, man, exp, bc = re if not im[1]: if im in (finf, fninf, fnan): return (fnan, fnan) if not man: if re == finf and im == fzero: return (fzero, fzero) if re == fnan: return (fnan, fnan) # Recurrence w = to_int(re) n = int(0.4*wp + 4*m) s = mpc_zero if w < n: for k in xrange(w, n): t = mpc_pow_int(z, -m-1, wp) s = mpc_add(s, t, wp) z = mpc_add_mpf(z, fone, wp) zm = mpc_pow_int(z, -m, wp) z2 = mpc_pow_int(z, -2, wp) # 1/m*(z+N)^m integral_term = mpc_div_mpf(zm, from_int(m), wp) s = mpc_add(s, integral_term, wp) # 1/2*(z+N)^(-(m+1)) s = mpc_add(s, mpc_mul_mpf(mpc_div(zm, z, wp), fhalf, wp), wp) a = m + 1 b = 2 k = 1 # Important: we want to sum up to the *relative* error, # not the absolute error, because psi^(m)(z) might be tiny magn = mpc_abs(s, 10) magn = magn[2]+magn[3] eps = mpf_shift(fone, magn-wp+2) while 1: zm = mpc_mul(zm, z2, wp) bern = mpf_bernoulli(2*k, wp) scal = mpf_mul_int(bern, a, wp) scal = mpf_div(scal, from_int(b), wp) term = mpc_mul_mpf(zm, scal, wp) s = mpc_add(s, term, wp) szterm = mpc_abs(term, 10) if k > 2 and mpf_le(szterm, eps): break #print k, to_str(szterm, 10), to_str(eps, 10) a *= (m+2*k)*(m+2*k+1) b *= (2*k+1)*(2*k+2) k += 1 # Scale and sign factor v = mpc_mul_mpf(s, mpf_gamma(from_int(m+1), wp), prec, rnd) if not (m & 1): v = mpf_neg(v[0]), mpf_neg(v[1]) return v #-----------------------------------------------------------------------# # # # Riemann zeta function # # # #-----------------------------------------------------------------------# r""" We use zeta(s) = eta(s) / (1 - 2**(1-s)) and Borwein's approximation n-1 ___ k -1 \ (-1) (d_k - d_n) eta(s) ~= ---- ) ------------------ d_n /___ s k = 0 (k + 1) where k ___ i \ (n + i - 1)! 4 d_k = n ) ---------------. /___ (n - i)! (2i)! i = 0 If s = a + b*I, the absolute error for eta(s) is bounded by 3 (1 + 2|b|) ------------ * exp(|b| pi/2) n (3+sqrt(8)) Disregarding the linear term, we have approximately, log(err) ~= log(exp(1.58*|b|)) - log(5.8**n) log(err) ~= 1.58*|b| - log(5.8)*n log(err) ~= 1.58*|b| - 1.76*n log2(err) ~= 2.28*|b| - 2.54*n So for p bits, we should choose n > (p + 2.28*|b|) / 2.54. References: ----------- Peter Borwein, "An Efficient Algorithm for the Riemann Zeta Function" http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P117.ps http://en.wikipedia.org/wiki/Dirichlet_eta_function """ borwein_cache = {} def borwein_coefficients(n): if n in borwein_cache: return borwein_cache[n] ds = [MPZ_ZERO] * (n+1) d = MPZ_ONE s = ds[0] = MPZ_ONE for i in range(1, n+1): d = d * 4 * (n+i-1) * (n-i+1) d //= ((2*i) * ((2*i)-1)) s += d ds[i] = s borwein_cache[n] = ds return ds ZETA_INT_CACHE_MAX_PREC = 1000 zeta_int_cache = {} def mpf_zeta_int(s, prec, rnd=round_fast): """ Optimized computation of zeta(s) for an integer s. """ wp = prec + 20 s = int(s) if s in zeta_int_cache and zeta_int_cache[s][0] >= wp: return mpf_pos(zeta_int_cache[s][1], prec, rnd) if s < 2: if s == 1: raise ValueError("zeta(1) pole") if not s: return mpf_neg(fhalf) return mpf_div(mpf_bernoulli(-s+1, wp), from_int(s-1), prec, rnd) # 2^-s term vanishes? if s >= wp: return mpf_perturb(fone, 0, prec, rnd) # 5^-s term vanishes? elif s >= wp*0.431: t = one = 1 << wp t += 1 << (wp - s) t += one // (MPZ_THREE ** s) t += 1 << max(0, wp - s*2) return from_man_exp(t, -wp, prec, rnd) else: # Fast enough to sum directly? # Even better, we use the Euler product (idea stolen from pari) m = (float(wp)/(s-1) + 1) if m < 30: needed_terms = int(2.0**m + 1) if needed_terms < int(wp/2.54 + 5) / 10: t = fone for k in list_primes(needed_terms): #print k, needed_terms powprec = int(wp - s*math.log(k,2)) if powprec < 2: break a = mpf_sub(fone, mpf_pow_int(from_int(k), -s, powprec), wp) t = mpf_mul(t, a, wp) return mpf_div(fone, t, wp) # Use Borwein's algorithm n = int(wp/2.54 + 5) d = borwein_coefficients(n) t = MPZ_ZERO s = MPZ(s) for k in xrange(n): t += (((-1)**k * (d[k] - d[n])) << wp) // (k+1)**s t = (t << wp) // (-d[n]) t = (t << wp) // ((1 << wp) - (1 << (wp+1-s))) if (s in zeta_int_cache and zeta_int_cache[s][0] < wp) or (s not in zeta_int_cache): zeta_int_cache[s] = (wp, from_man_exp(t, -wp-wp)) return from_man_exp(t, -wp-wp, prec, rnd) def mpf_zeta(s, prec, rnd=round_fast, alt=0): sign, man, exp, bc = s if not man: if s == fzero: if alt: return fhalf else: return mpf_neg(fhalf) if s == finf: return fone return fnan wp = prec + 20 # First term vanishes? if (not sign) and (exp + bc > (math.log(wp,2) + 2)): return mpf_perturb(fone, alt, prec, rnd) # Optimize for integer arguments elif exp >= 0: if alt: if s == fone: return mpf_ln2(prec, rnd) z = mpf_zeta_int(to_int(s), wp, negative_rnd[rnd]) q = mpf_sub(fone, mpf_pow(ftwo, mpf_sub(fone, s, wp), wp), wp) return mpf_mul(z, q, prec, rnd) else: return mpf_zeta_int(to_int(s), prec, rnd) # Negative: use the reflection formula # Borwein only proves the accuracy bound for x >= 1/2. However, based on # tests, the accuracy without reflection is quite good even some distance # to the left of 1/2. XXX: verify this. if sign: # XXX: could use the separate refl. formula for Dirichlet eta if alt: q = mpf_sub(fone, mpf_pow(ftwo, mpf_sub(fone, s, wp), wp), wp) return mpf_mul(mpf_zeta(s, wp), q, prec, rnd) # XXX: -1 should be done exactly y = mpf_sub(fone, s, 10*wp) a = mpf_gamma(y, wp) b = mpf_zeta(y, wp) c = mpf_sin_pi(mpf_shift(s, -1), wp) wp2 = wp + max(0,exp+bc) pi = mpf_pi(wp+wp2) d = mpf_div(mpf_pow(mpf_shift(pi, 1), s, wp2), pi, wp2) return mpf_mul(a,mpf_mul(b,mpf_mul(c,d,wp),wp),prec,rnd) # Near pole r = mpf_sub(fone, s, wp) asign, aman, aexp, abc = mpf_abs(r) pole_dist = -2*(aexp+abc) if pole_dist > wp: if alt: return mpf_ln2(prec, rnd) else: q = mpf_neg(mpf_div(fone, r, wp)) return mpf_add(q, mpf_euler(wp), prec, rnd) else: wp += max(0, pole_dist) t = MPZ_ZERO #wp += 16 - (prec & 15) # Use Borwein's algorithm n = int(wp/2.54 + 5) d = borwein_coefficients(n) t = MPZ_ZERO sf = to_fixed(s, wp) ln2 = ln2_fixed(wp) for k in xrange(n): u = (-sf*log_int_fixed(k+1, wp, ln2)) >> wp #esign, eman, eexp, ebc = mpf_exp(u, wp) #offset = eexp + wp #if offset >= 0: # w = ((d[k] - d[n]) * eman) << offset #else: # w = ((d[k] - d[n]) * eman) >> (-offset) eman = exp_fixed(u, wp, ln2) w = (d[k] - d[n]) * eman if k & 1: t -= w else: t += w t = t // (-d[n]) t = from_man_exp(t, -wp, wp) if alt: return mpf_pos(t, prec, rnd) else: q = mpf_sub(fone, mpf_pow(ftwo, mpf_sub(fone, s, wp), wp), wp) return mpf_div(t, q, prec, rnd) def mpc_zeta(s, prec, rnd=round_fast, alt=0, force=False): re, im = s if im == fzero: return mpf_zeta(re, prec, rnd, alt), fzero # slow for large s if (not force) and mpf_gt(mpc_abs(s, 10), from_int(prec)): raise NotImplementedError wp = prec + 20 # Near pole r = mpc_sub(mpc_one, s, wp) asign, aman, aexp, abc = mpc_abs(r, 10) pole_dist = -2*(aexp+abc) if pole_dist > wp: if alt: q = mpf_ln2(wp) y = mpf_mul(q, mpf_euler(wp), wp) g = mpf_shift(mpf_mul(q, q, wp), -1) g = mpf_sub(y, g) z = mpc_mul_mpf(r, mpf_neg(g), wp) z = mpc_add_mpf(z, q, wp) return mpc_pos(z, prec, rnd) else: q = mpc_neg(mpc_div(mpc_one, r, wp)) q = mpc_add_mpf(q, mpf_euler(wp), wp) return mpc_pos(q, prec, rnd) else: wp += max(0, pole_dist) # Reflection formula. To be rigorous, we should reflect to the left of # re = 1/2 (see comments for mpf_zeta), but this leads to unnecessary # slowdown for interesting values of s if mpf_lt(re, fzero): # XXX: could use the separate refl. formula for Dirichlet eta if alt: q = mpc_sub(mpc_one, mpc_pow(mpc_two, mpc_sub(mpc_one, s, wp), wp), wp) return mpc_mul(mpc_zeta(s, wp), q, prec, rnd) # XXX: -1 should be done exactly y = mpc_sub(mpc_one, s, 10*wp) a = mpc_gamma(y, wp) b = mpc_zeta(y, wp) c = mpc_sin_pi(mpc_shift(s, -1), wp) rsign, rman, rexp, rbc = re isign, iman, iexp, ibc = im mag = max(rexp+rbc, iexp+ibc) wp2 = wp + max(0, mag) pi = mpf_pi(wp+wp2) pi2 = (mpf_shift(pi, 1), fzero) d = mpc_div_mpf(mpc_pow(pi2, s, wp2), pi, wp2) return mpc_mul(a,mpc_mul(b,mpc_mul(c,d,wp),wp),prec,rnd) n = int(wp/2.54 + 5) n += int(0.9*abs(to_int(im))) d = borwein_coefficients(n) ref = to_fixed(re, wp) imf = to_fixed(im, wp) tre = MPZ_ZERO tim = MPZ_ZERO one = MPZ_ONE << wp one_2wp = MPZ_ONE << (2*wp) critical_line = re == fhalf ln2 = ln2_fixed(wp) pi2 = pi_fixed(wp-1) wp2 = wp+wp for k in xrange(n): log = log_int_fixed(k+1, wp, ln2) # A square root is much cheaper than an exp if critical_line: w = one_2wp // isqrt_fast((k+1) << wp2) else: w = exp_fixed((-ref*log) >> wp, wp) if k & 1: w *= (d[n] - d[k]) else: w *= (d[k] - d[n]) wre, wim = cos_sin_fixed((-imf*log)>>wp, wp, pi2) tre += (w * wre) >> wp tim += (w * wim) >> wp tre //= (-d[n]) tim //= (-d[n]) tre = from_man_exp(tre, -wp, wp) tim = from_man_exp(tim, -wp, wp) if alt: return mpc_pos((tre, tim), prec, rnd) else: q = mpc_sub(mpc_one, mpc_pow(mpc_two, r, wp), wp) return mpc_div((tre, tim), q, prec, rnd) def mpf_altzeta(s, prec, rnd=round_fast): return mpf_zeta(s, prec, rnd, 1) def mpc_altzeta(s, prec, rnd=round_fast): return mpc_zeta(s, prec, rnd, 1) # Not optimized currently mpf_zetasum = None def pow_fixed(x, n, wp): if n == 1: return x y = MPZ_ONE << wp while n: if n & 1: y = (y*x) >> wp n -= 1 x = (x*x) >> wp n //= 2 return y # TODO: optimize / cleanup interface / unify with list_primes sieve_cache = [] primes_cache = [] mult_cache = [] def primesieve(n): global sieve_cache, primes_cache, mult_cache if n < len(sieve_cache): sieve = sieve_cache#[:n+1] primes = primes_cache[:primes_cache.index(max(sieve))+1] mult = mult_cache#[:n+1] return sieve, primes, mult sieve = [0] * (n+1) mult = [0] * (n+1) primes = list_primes(n) for p in primes: #sieve[p::p] = p for k in xrange(p,n+1,p): sieve[k] = p for i, p in enumerate(sieve): if i >= 2: m = 1 n = i // p while not n % p: n //= p m += 1 mult[i] = m sieve_cache = sieve primes_cache = primes mult_cache = mult return sieve, primes, mult def zetasum_sieved(critical_line, sre, sim, a, n, wp): if a < 1: raise ValueError("a cannot be less than 1") sieve, primes, mult = primesieve(a+n) basic_powers = {} one = MPZ_ONE << wp one_2wp = MPZ_ONE << (2*wp) wp2 = wp+wp ln2 = ln2_fixed(wp) pi2 = pi_fixed(wp-1) for p in primes: if p*2 > a+n: break log = log_int_fixed(p, wp, ln2) cos, sin = cos_sin_fixed((-sim*log)>>wp, wp, pi2) if critical_line: u = one_2wp // isqrt_fast(p<>wp, wp) pre = (u*cos) >> wp pim = (u*sin) >> wp basic_powers[p] = [(pre, pim)] tre, tim = pre, pim for m in range(1,int(math.log(a+n,p)+0.01)+1): tre, tim = ((pre*tre-pim*tim)>>wp), ((pim*tre+pre*tim)>>wp) basic_powers[p].append((tre,tim)) xre = MPZ_ZERO xim = MPZ_ZERO if a == 1: xre += one aa = max(a,2) for k in xrange(aa, a+n+1): p = sieve[k] if p in basic_powers: m = mult[k] tre, tim = basic_powers[p][m-1] while 1: k //= p**m if k == 1: break p = sieve[k] m = mult[k] pre, pim = basic_powers[p][m-1] tre, tim = ((pre*tre-pim*tim)>>wp), ((pim*tre+pre*tim)>>wp) else: log = log_int_fixed(k, wp, ln2) cos, sin = cos_sin_fixed((-sim*log)>>wp, wp, pi2) if critical_line: u = one_2wp // isqrt_fast(k<>wp, wp) tre = (u*cos) >> wp tim = (u*sin) >> wp xre += tre xim += tim return xre, xim # Set to something large to disable ZETASUM_SIEVE_CUTOFF = 10 def mpc_zetasum(s, a, n, derivatives, reflect, prec): """ Fast version of mp._zetasum, assuming s = complex, a = integer. """ wp = prec + 10 derivatives = list(derivatives) have_derivatives = derivatives != [0] have_one_derivative = len(derivatives) == 1 # parse s sre, sim = s critical_line = (sre == fhalf) sre = to_fixed(sre, wp) sim = to_fixed(sim, wp) if a > 0 and n > ZETASUM_SIEVE_CUTOFF and not have_derivatives \ and not reflect and (n < 4e7 or sys.maxsize > 2**32): re, im = zetasum_sieved(critical_line, sre, sim, a, n, wp) xs = [(from_man_exp(re, -wp, prec, 'n'), from_man_exp(im, -wp, prec, 'n'))] return xs, [] maxd = max(derivatives) if not have_one_derivative: derivatives = range(maxd+1) # x_d = 0, y_d = 0 xre = [MPZ_ZERO for d in derivatives] xim = [MPZ_ZERO for d in derivatives] if reflect: yre = [MPZ_ZERO for d in derivatives] yim = [MPZ_ZERO for d in derivatives] else: yre = yim = [] one = MPZ_ONE << wp one_2wp = MPZ_ONE << (2*wp) ln2 = ln2_fixed(wp) pi2 = pi_fixed(wp-1) wp2 = wp+wp for w in xrange(a, a+n+1): log = log_int_fixed(w, wp, ln2) cos, sin = cos_sin_fixed((-sim*log)>>wp, wp, pi2) if critical_line: u = one_2wp // isqrt_fast(w<>wp, wp) xterm_re = (u * cos) >> wp xterm_im = (u * sin) >> wp if reflect: reciprocal = (one_2wp // (u*w)) yterm_re = (reciprocal * cos) >> wp yterm_im = (reciprocal * sin) >> wp if have_derivatives: if have_one_derivative: log = pow_fixed(log, maxd, wp) xre[0] += (xterm_re * log) >> wp xim[0] += (xterm_im * log) >> wp if reflect: yre[0] += (yterm_re * log) >> wp yim[0] += (yterm_im * log) >> wp else: t = MPZ_ONE << wp for d in derivatives: xre[d] += (xterm_re * t) >> wp xim[d] += (xterm_im * t) >> wp if reflect: yre[d] += (yterm_re * t) >> wp yim[d] += (yterm_im * t) >> wp t = (t * log) >> wp else: xre[0] += xterm_re xim[0] += xterm_im if reflect: yre[0] += yterm_re yim[0] += yterm_im if have_derivatives: if have_one_derivative: if maxd % 2: xre[0] = -xre[0] xim[0] = -xim[0] if reflect: yre[0] = -yre[0] yim[0] = -yim[0] else: xre = [(-1)**d * xre[d] for d in derivatives] xim = [(-1)**d * xim[d] for d in derivatives] if reflect: yre = [(-1)**d * yre[d] for d in derivatives] yim = [(-1)**d * yim[d] for d in derivatives] xs = [(from_man_exp(xa, -wp, prec, 'n'), from_man_exp(xb, -wp, prec, 'n')) for (xa, xb) in zip(xre, xim)] ys = [(from_man_exp(ya, -wp, prec, 'n'), from_man_exp(yb, -wp, prec, 'n')) for (ya, yb) in zip(yre, yim)] return xs, ys #-----------------------------------------------------------------------# # # # The gamma function (NEW IMPLEMENTATION) # # # #-----------------------------------------------------------------------# # Higher means faster, but more precomputation time MAX_GAMMA_TAYLOR_PREC = 5000 # Need to derive higher bounds for Taylor series to go higher assert MAX_GAMMA_TAYLOR_PREC < 15000 # Use Stirling's series if abs(x) > beta*prec # Important: must be large enough for convergence! GAMMA_STIRLING_BETA = 0.2 SMALL_FACTORIAL_CACHE_SIZE = 150 gamma_taylor_cache = {} gamma_stirling_cache = {} small_factorial_cache = [from_int(ifac(n)) for \ n in range(SMALL_FACTORIAL_CACHE_SIZE+1)] def zeta_array(N, prec): """ zeta(n) = A * pi**n / n! + B where A is a rational number (A = Bernoulli number for n even) and B is an infinite sum over powers of exp(2*pi). (B = 0 for n even). TODO: this is currently only used for gamma, but could be very useful elsewhere. """ extra = 30 wp = prec+extra zeta_values = [MPZ_ZERO] * (N+2) pi = pi_fixed(wp) # STEP 1: one = MPZ_ONE << wp zeta_values[0] = -one//2 f_2pi = mpf_shift(mpf_pi(wp),1) exp_2pi_k = exp_2pi = mpf_exp(f_2pi, wp) # Compute exponential series # Store values of 1/(exp(2*pi*k)-1), # exp(2*pi*k)/(exp(2*pi*k)-1)**2, 1/(exp(2*pi*k)-1)**2 # pi*k*exp(2*pi*k)/(exp(2*pi*k)-1)**2 exps3 = [] k = 1 while 1: tp = wp - 9*k if tp < 1: break # 1/(exp(2*pi*k-1) q1 = mpf_div(fone, mpf_sub(exp_2pi_k, fone, tp), tp) # pi*k*exp(2*pi*k)/(exp(2*pi*k)-1)**2 q2 = mpf_mul(exp_2pi_k, mpf_mul(q1,q1,tp), tp) q1 = to_fixed(q1, wp) q2 = to_fixed(q2, wp) q2 = (k * q2 * pi) >> wp exps3.append((q1, q2)) # Multiply for next round exp_2pi_k = mpf_mul(exp_2pi_k, exp_2pi, wp) k += 1 # Exponential sum for n in xrange(3, N+1, 2): s = MPZ_ZERO k = 1 for e1, e2 in exps3: if n%4 == 3: t = e1 // k**n else: U = (n-1)//4 t = (e1 + e2//U) // k**n if not t: break s += t k += 1 zeta_values[n] = -2*s # Even zeta values B = [mpf_abs(mpf_bernoulli(k,wp)) for k in xrange(N+2)] pi_pow = fpi = mpf_pow_int(mpf_shift(mpf_pi(wp), 1), 2, wp) pi_pow = mpf_div(pi_pow, from_int(4), wp) for n in xrange(2,N+2,2): z = mpf_mul(B[n], pi_pow, wp) zeta_values[n] = to_fixed(z, wp) pi_pow = mpf_mul(pi_pow, fpi, wp) pi_pow = mpf_div(pi_pow, from_int((n+1)*(n+2)), wp) # Zeta sum reciprocal_pi = (one << wp) // pi for n in xrange(3, N+1, 4): U = (n-3)//4 s = zeta_values[4*U+4]*(4*U+7)//4 for k in xrange(1, U+1): s -= (zeta_values[4*k] * zeta_values[4*U+4-4*k]) >> wp zeta_values[n] += (2*s*reciprocal_pi) >> wp for n in xrange(5, N+1, 4): U = (n-1)//4 s = zeta_values[4*U+2]*(2*U+1) for k in xrange(1, 2*U+1): s += ((-1)**k*2*k* zeta_values[2*k] * zeta_values[4*U+2-2*k])>>wp zeta_values[n] += ((s*reciprocal_pi)>>wp)//(2*U) return [x>>extra for x in zeta_values] def gamma_taylor_coefficients(inprec): """ Gives the Taylor coefficients of 1/gamma(1+x) as a list of fixed-point numbers. Enough coefficients are returned to ensure that the series converges to the given precision when x is in [0.5, 1.5]. """ # Reuse nearby cache values (small case) if inprec < 400: prec = inprec + (10-(inprec%10)) elif inprec < 1000: prec = inprec + (30-(inprec%30)) else: prec = inprec if prec in gamma_taylor_cache: return gamma_taylor_cache[prec], prec # Experimentally determined bounds if prec < 1000: N = int(prec**0.76 + 2) else: # Valid to at least 15000 bits N = int(prec**0.787 + 2) # Reuse higher precision values for cprec in gamma_taylor_cache: if cprec > prec: coeffs = [x>>(cprec-prec) for x in gamma_taylor_cache[cprec][-N:]] if inprec < 1000: gamma_taylor_cache[prec] = coeffs return coeffs, prec # Cache at a higher precision (large case) if prec > 1000: prec = int(prec * 1.2) wp = prec + 20 A = [0] * N A[0] = MPZ_ZERO A[1] = MPZ_ONE << wp A[2] = euler_fixed(wp) # SLOW, reference implementation #zeta_values = [0,0]+[to_fixed(mpf_zeta_int(k,wp),wp) for k in xrange(2,N)] zeta_values = zeta_array(N, wp) for k in xrange(3, N): a = (-A[2]*A[k-1])>>wp for j in xrange(2,k): a += ((-1)**j * zeta_values[j] * A[k-j]) >> wp a //= (1-k) A[k] = a A = [a>>20 for a in A] A = A[::-1] A = A[:-1] gamma_taylor_cache[prec] = A #return A, prec return gamma_taylor_coefficients(inprec) def gamma_fixed_taylor(xmpf, x, wp, prec, rnd, type): # Determine nearest multiple of N/2 #n = int(x >> (wp-1)) #steps = (n-1)>>1 nearest_int = ((x >> (wp-1)) + MPZ_ONE) >> 1 one = MPZ_ONE << wp coeffs, cwp = gamma_taylor_coefficients(wp) if nearest_int > 0: r = one for i in xrange(nearest_int-1): x -= one r = (r*x) >> wp x -= one p = MPZ_ZERO for c in coeffs: p = c + ((x*p)>>wp) p >>= (cwp-wp) if type == 0: return from_man_exp((r<> wp x += one p = MPZ_ZERO for c in coeffs: p = c + ((x*p)>>wp) p >>= (cwp-wp) if wp - bitcount(abs(x)) > 10: # pass very close to 0, so do floating-point multiply g = mpf_add(xmpf, from_int(-nearest_int)) # exact r = from_man_exp(p*r,-wp-wp) r = mpf_mul(r, g, wp) if type == 0: return mpf_div(fone, r, prec, rnd) if type == 2: return mpf_pos(r, prec, rnd) if type == 3: return mpf_log(mpf_abs(mpf_div(fone, r, wp)), prec, rnd) else: r = from_man_exp(x*p*r,-3*wp) if type == 0: return mpf_div(fone, r, prec, rnd) if type == 2: return mpf_pos(r, prec, rnd) if type == 3: return mpf_neg(mpf_log(mpf_abs(r), prec, rnd)) def stirling_coefficient(n): if n in gamma_stirling_cache: return gamma_stirling_cache[n] p, q = bernfrac(n) q *= MPZ(n*(n-1)) gamma_stirling_cache[n] = p, q, bitcount(abs(p)), bitcount(q) return gamma_stirling_cache[n] def real_stirling_series(x, prec): """ Sums the rational part of Stirling's expansion, log(sqrt(2*pi)) - z + 1/(12*z) - 1/(360*z^3) + ... """ t = (MPZ_ONE<<(prec+prec)) // x # t = 1/x u = (t*t)>>prec # u = 1/x**2 s = ln_sqrt2pi_fixed(prec) - x # Add initial terms of Stirling's series s += t//12; t = (t*u)>>prec s -= t//360; t = (t*u)>>prec s += t//1260; t = (t*u)>>prec s -= t//1680; t = (t*u)>>prec if not t: return s s += t//1188; t = (t*u)>>prec s -= 691*t//360360; t = (t*u)>>prec s += t//156; t = (t*u)>>prec if not t: return s s -= 3617*t//122400; t = (t*u)>>prec s += 43867*t//244188; t = (t*u)>>prec s -= 174611*t//125400; t = (t*u)>>prec if not t: return s k = 22 # From here on, the coefficients are growing, so we # have to keep t at a roughly constant size usize = bitcount(abs(u)) tsize = bitcount(abs(t)) texp = 0 while 1: p, q, pb, qb = stirling_coefficient(k) term_mag = tsize + pb + texp shift = -texp m = pb - term_mag if m > 0 and shift < m: p >>= m shift -= m m = tsize - term_mag if m > 0 and shift < m: w = t >> m shift -= m else: w = t term = (t*p//q) >> shift if not term: break s += term t = (t*u) >> usize texp -= (prec - usize) k += 2 return s def complex_stirling_series(x, y, prec): # t = 1/z _m = (x*x + y*y) >> prec tre = (x << prec) // _m tim = (-y << prec) // _m # u = 1/z**2 ure = (tre*tre - tim*tim) >> prec uim = tim*tre >> (prec-1) # s = log(sqrt(2*pi)) - z sre = ln_sqrt2pi_fixed(prec) - x sim = -y # Add initial terms of Stirling's series sre += tre//12; sim += tim//12; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre -= tre//360; sim -= tim//360; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre += tre//1260; sim += tim//1260; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre -= tre//1680; sim -= tim//1680; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) if abs(tre) + abs(tim) < 5: return sre, sim sre += tre//1188; sim += tim//1188; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre -= 691*tre//360360; sim -= 691*tim//360360; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre += tre//156; sim += tim//156; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) if abs(tre) + abs(tim) < 5: return sre, sim sre -= 3617*tre//122400; sim -= 3617*tim//122400; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre += 43867*tre//244188; sim += 43867*tim//244188; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) sre -= 174611*tre//125400; sim -= 174611*tim//125400; tre, tim = ((tre*ure-tim*uim)>>prec), ((tre*uim+tim*ure)>>prec) if abs(tre) + abs(tim) < 5: return sre, sim k = 22 # From here on, the coefficients are growing, so we # have to keep t at a roughly constant size usize = bitcount(max(abs(ure), abs(uim))) tsize = bitcount(max(abs(tre), abs(tim))) texp = 0 while 1: p, q, pb, qb = stirling_coefficient(k) term_mag = tsize + pb + texp shift = -texp m = pb - term_mag if m > 0 and shift < m: p >>= m shift -= m m = tsize - term_mag if m > 0 and shift < m: wre = tre >> m wim = tim >> m shift -= m else: wre = tre wim = tim termre = (tre*p//q) >> shift termim = (tim*p//q) >> shift if abs(termre) + abs(termim) < 5: break sre += termre sim += termim tre, tim = ((tre*ure - tim*uim)>>usize), \ ((tre*uim + tim*ure)>>usize) texp -= (prec - usize) k += 2 return sre, sim def mpf_gamma(x, prec, rnd='d', type=0): """ This function implements multipurpose evaluation of the gamma function, G(x), as well as the following versions of the same: type = 0 -- G(x) [standard gamma function] type = 1 -- G(x+1) = x*G(x+1) = x! [factorial] type = 2 -- 1/G(x) [reciprocal gamma function] type = 3 -- log(|G(x)|) [log-gamma function, real part] """ # Specal values sign, man, exp, bc = x if not man: if x == fzero: if type == 1: return fone if type == 2: return fzero raise ValueError("gamma function pole") if x == finf: if type == 2: return fzero return finf return fnan # First of all, for log gamma, numbers can be well beyond the fixed-point # range, so we must take care of huge numbers before e.g. trying # to convert x to the nearest integer if type == 3: wp = prec+20 if exp+bc > wp and not sign: return mpf_sub(mpf_mul(x, mpf_log(x, wp), wp), x, prec, rnd) # We strongly want to special-case small integers is_integer = exp >= 0 if is_integer: # Poles if sign: if type == 2: return fzero raise ValueError("gamma function pole") # n = x n = man << exp if n < SMALL_FACTORIAL_CACHE_SIZE: if type == 0: return mpf_pos(small_factorial_cache[n-1], prec, rnd) if type == 1: return mpf_pos(small_factorial_cache[n], prec, rnd) if type == 2: return mpf_div(fone, small_factorial_cache[n-1], prec, rnd) if type == 3: return mpf_log(small_factorial_cache[n-1], prec, rnd) else: # floor(abs(x)) n = int(man >> (-exp)) # Estimate size and precision # Estimate log(gamma(|x|),2) as x*log(x,2) mag = exp + bc gamma_size = n*mag if type == 3: wp = prec + 20 else: wp = prec + bitcount(gamma_size) + 20 # Very close to 0, pole if mag < -wp: if type == 0: return mpf_sub(mpf_div(fone,x, wp),mpf_shift(fone,-wp),prec,rnd) if type == 1: return mpf_sub(fone, x, prec, rnd) if type == 2: return mpf_add(x, mpf_shift(fone,mag-wp), prec, rnd) if type == 3: return mpf_neg(mpf_log(mpf_abs(x), prec, rnd)) # From now on, we assume having a gamma function if type == 1: return mpf_gamma(mpf_add(x, fone), prec, rnd, 0) # Special case integers (those not small enough to be caught above, # but still small enough for an exact factorial to be faster # than an approximate algorithm), and half-integers if exp >= -1: if is_integer: if gamma_size < 10*wp: if type == 0: return from_int(ifac(n-1), prec, rnd) if type == 2: return from_rational(MPZ_ONE, ifac(n-1), prec, rnd) if type == 3: return mpf_log(from_int(ifac(n-1)), prec, rnd) # half-integer if n < 100 or gamma_size < 10*wp: if sign: w = sqrtpi_fixed(wp) if n % 2: f = ifac2(2*n+1) else: f = -ifac2(2*n+1) if type == 0: return mpf_shift(from_rational(w, f, prec, rnd), -wp+n+1) if type == 2: return mpf_shift(from_rational(f, w, prec, rnd), wp-n-1) if type == 3: return mpf_log(mpf_shift(from_rational(w, abs(f), prec, rnd), -wp+n+1), prec, rnd) elif n == 0: if type == 0: return mpf_sqrtpi(prec, rnd) if type == 2: return mpf_div(fone, mpf_sqrtpi(wp), prec, rnd) if type == 3: return mpf_log(mpf_sqrtpi(wp), prec, rnd) else: w = sqrtpi_fixed(wp) w = from_man_exp(w * ifac2(2*n-1), -wp-n) if type == 0: return mpf_pos(w, prec, rnd) if type == 2: return mpf_div(fone, w, prec, rnd) if type == 3: return mpf_log(mpf_abs(w), prec, rnd) # Convert to fixed point offset = exp + wp if offset >= 0: absxman = man << offset else: absxman = man >> (-offset) # For log gamma, provide accurate evaluation for x = 1+eps and 2+eps if type == 3 and not sign: one = MPZ_ONE << wp one_dist = abs(absxman-one) two_dist = abs(absxman-2*one) cancellation = (wp - bitcount(min(one_dist, two_dist))) if cancellation > 10: xsub1 = mpf_sub(fone, x) xsub2 = mpf_sub(ftwo, x) xsub1mag = xsub1[2]+xsub1[3] xsub2mag = xsub2[2]+xsub2[3] if xsub1mag < -wp: return mpf_mul(mpf_euler(wp), mpf_sub(fone, x), prec, rnd) if xsub2mag < -wp: return mpf_mul(mpf_sub(fone, mpf_euler(wp)), mpf_sub(x, ftwo), prec, rnd) # Proceed but increase precision wp += max(-xsub1mag, -xsub2mag) offset = exp + wp if offset >= 0: absxman = man << offset else: absxman = man >> (-offset) # Use Taylor series if appropriate n_for_stirling = int(GAMMA_STIRLING_BETA*wp) if n < max(100, n_for_stirling) and wp < MAX_GAMMA_TAYLOR_PREC: if sign: absxman = -absxman return gamma_fixed_taylor(x, absxman, wp, prec, rnd, type) # Use Stirling's series # First ensure that |x| is large enough for rapid convergence xorig = x # Argument reduction r = 0 if n < n_for_stirling: r = one = MPZ_ONE << wp d = n_for_stirling - n for k in xrange(d): r = (r * absxman) >> wp absxman += one x = xabs = from_man_exp(absxman, -wp) if sign: x = mpf_neg(x) else: xabs = mpf_abs(x) # Asymptotic series y = real_stirling_series(absxman, wp) u = to_fixed(mpf_log(xabs, wp), wp) u = ((absxman - (MPZ_ONE<<(wp-1))) * u) >> wp y += u w = from_man_exp(y, -wp) # Compute final value if sign: # Reflection formula A = mpf_mul(mpf_sin_pi(xorig, wp), xorig, wp) B = mpf_neg(mpf_pi(wp)) if type == 0 or type == 2: A = mpf_mul(A, mpf_exp(w, wp)) if r: B = mpf_mul(B, from_man_exp(r, -wp), wp) if type == 0: return mpf_div(B, A, prec, rnd) if type == 2: return mpf_div(A, B, prec, rnd) if type == 3: if r: B = mpf_mul(B, from_man_exp(r, -wp), wp) A = mpf_add(mpf_log(mpf_abs(A), wp), w, wp) return mpf_sub(mpf_log(mpf_abs(B), wp), A, prec, rnd) else: if type == 0: if r: return mpf_div(mpf_exp(w, wp), from_man_exp(r, -wp), prec, rnd) return mpf_exp(w, prec, rnd) if type == 2: if r: return mpf_div(from_man_exp(r, -wp), mpf_exp(w, wp), prec, rnd) return mpf_exp(mpf_neg(w), prec, rnd) if type == 3: if r: return mpf_sub(w, mpf_log(from_man_exp(r,-wp), wp), prec, rnd) return mpf_pos(w, prec, rnd) def mpc_gamma(z, prec, rnd='d', type=0): a, b = z asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b if b == fzero: # Imaginary part on negative half-axis for log-gamma function if type == 3 and asign: re = mpf_gamma(a, prec, rnd, 3) n = (-aman) >> (-aexp) im = mpf_mul_int(mpf_pi(prec+10), n, prec, rnd) return re, im return mpf_gamma(a, prec, rnd, type), fzero # Some kind of complex inf/nan if (not aman and aexp) or (not bman and bexp): return (fnan, fnan) # Initial working precision wp = prec + 20 amag = aexp+abc bmag = bexp+bbc if aman: mag = max(amag, bmag) else: mag = bmag # Close to 0 if mag < -8: if mag < -wp: # 1/gamma(z) = z + euler*z^2 + O(z^3) v = mpc_add(z, mpc_mul_mpf(mpc_mul(z,z,wp),mpf_euler(wp),wp), wp) if type == 0: return mpc_reciprocal(v, prec, rnd) if type == 1: return mpc_div(z, v, prec, rnd) if type == 2: return mpc_pos(v, prec, rnd) if type == 3: return mpc_log(mpc_reciprocal(v, prec), prec, rnd) elif type != 1: wp += (-mag) # Handle huge log-gamma values; must do this before converting to # a fixed-point value. TODO: determine a precise cutoff of validity # depending on amag and bmag if type == 3 and mag > wp and ((not asign) or (bmag >= amag)): return mpc_sub(mpc_mul(z, mpc_log(z, wp), wp), z, prec, rnd) # From now on, we assume having a gamma function if type == 1: return mpc_gamma((mpf_add(a, fone), b), prec, rnd, 0) an = abs(to_int(a)) bn = abs(to_int(b)) absn = max(an, bn) gamma_size = absn*mag if type == 3: pass else: wp += bitcount(gamma_size) # Reflect to the right half-plane. Note that Stirling's expansion # is valid in the left half-plane too, as long as we're not too close # to the real axis, but in order to use this argument reduction # in the negative direction must be implemented. #need_reflection = asign and ((bmag < 0) or (amag-bmag > 4)) need_reflection = asign zorig = z if need_reflection: z = mpc_neg(z) asign, aman, aexp, abc = a = z[0] bsign, bman, bexp, bbc = b = z[1] # Imaginary part very small compared to real one? yfinal = 0 balance_prec = 0 if bmag < -10: # Check z ~= 1 and z ~= 2 for loggamma if type == 3: zsub1 = mpc_sub_mpf(z, fone) if zsub1[0] == fzero: cancel1 = -bmag else: cancel1 = -max(zsub1[0][2]+zsub1[0][3], bmag) if cancel1 > wp: pi = mpf_pi(wp) x = mpc_mul_mpf(zsub1, pi, wp) x = mpc_mul(x, x, wp) x = mpc_div_mpf(x, from_int(12), wp) y = mpc_mul_mpf(zsub1, mpf_neg(mpf_euler(wp)), wp) yfinal = mpc_add(x, y, wp) if not need_reflection: return mpc_pos(yfinal, prec, rnd) elif cancel1 > 0: wp += cancel1 zsub2 = mpc_sub_mpf(z, ftwo) if zsub2[0] == fzero: cancel2 = -bmag else: cancel2 = -max(zsub2[0][2]+zsub2[0][3], bmag) if cancel2 > wp: pi = mpf_pi(wp) t = mpf_sub(mpf_mul(pi, pi), from_int(6)) x = mpc_mul_mpf(mpc_mul(zsub2, zsub2, wp), t, wp) x = mpc_div_mpf(x, from_int(12), wp) y = mpc_mul_mpf(zsub2, mpf_sub(fone, mpf_euler(wp)), wp) yfinal = mpc_add(x, y, wp) if not need_reflection: return mpc_pos(yfinal, prec, rnd) elif cancel2 > 0: wp += cancel2 if bmag < -wp: # Compute directly from the real gamma function. pp = 2*(wp+10) aabs = mpf_abs(a) eps = mpf_shift(fone, amag-wp) x1 = mpf_gamma(aabs, pp, type=type) x2 = mpf_gamma(mpf_add(aabs, eps), pp, type=type) xprime = mpf_div(mpf_sub(x2, x1, pp), eps, pp) y = mpf_mul(b, xprime, prec, rnd) yfinal = (x1, y) # Note: we still need to use the reflection formula for # near-poles, and the correct branch of the log-gamma function if not need_reflection: return mpc_pos(yfinal, prec, rnd) else: balance_prec += (-bmag) wp += balance_prec n_for_stirling = int(GAMMA_STIRLING_BETA*wp) need_reduction = absn < n_for_stirling afix = to_fixed(a, wp) bfix = to_fixed(b, wp) r = 0 if not yfinal: zprered = z # Argument reduction if absn < n_for_stirling: absn = complex(an, bn) d = int((1 + n_for_stirling**2 - bn**2)**0.5 - an) rre = one = MPZ_ONE << wp rim = MPZ_ZERO for k in xrange(d): rre, rim = ((afix*rre-bfix*rim)>>wp), ((afix*rim + bfix*rre)>>wp) afix += one r = from_man_exp(rre, -wp), from_man_exp(rim, -wp) a = from_man_exp(afix, -wp) z = a, b yre, yim = complex_stirling_series(afix, bfix, wp) # (z-1/2)*log(z) + S lre, lim = mpc_log(z, wp) lre = to_fixed(lre, wp) lim = to_fixed(lim, wp) yre = ((lre*afix - lim*bfix)>>wp) - (lre>>1) + yre yim = ((lre*bfix + lim*afix)>>wp) - (lim>>1) + yim y = from_man_exp(yre, -wp), from_man_exp(yim, -wp) if r and type == 3: # If re(z) > 0 and abs(z) <= 4, the branches of loggamma(z) # and log(gamma(z)) coincide. Otherwise, use the zeroth order # Stirling expansion to compute the correct imaginary part. y = mpc_sub(y, mpc_log(r, wp), wp) zfa = to_float(zprered[0]) zfb = to_float(zprered[1]) zfabs = math.hypot(zfa,zfb) #if not (zfa > 0.0 and zfabs <= 4): yfb = to_float(y[1]) u = math.atan2(zfb, zfa) if zfabs <= 0.5: gi = 0.577216*zfb - u else: gi = -zfb - 0.5*u + zfa*u + zfb*math.log(zfabs) n = int(math.floor((gi-yfb)/(2*math.pi)+0.5)) y = (y[0], mpf_add(y[1], mpf_mul_int(mpf_pi(wp), 2*n, wp), wp)) if need_reflection: if type == 0 or type == 2: A = mpc_mul(mpc_sin_pi(zorig, wp), zorig, wp) B = (mpf_neg(mpf_pi(wp)), fzero) if yfinal: if type == 2: A = mpc_div(A, yfinal, wp) else: A = mpc_mul(A, yfinal, wp) else: A = mpc_mul(A, mpc_exp(y, wp), wp) if r: B = mpc_mul(B, r, wp) if type == 0: return mpc_div(B, A, prec, rnd) if type == 2: return mpc_div(A, B, prec, rnd) # Reflection formula for the log-gamma function with correct branch # http://functions.wolfram.com/GammaBetaErf/LogGamma/16/01/01/0006/ # LogGamma[z] == -LogGamma[-z] - Log[-z] + # Sign[Im[z]] Floor[Re[z]] Pi I + Log[Pi] - # Log[Sin[Pi (z - Floor[Re[z]])]] - # Pi I (1 - Abs[Sign[Im[z]]]) Abs[Floor[Re[z]]] if type == 3: if yfinal: s1 = mpc_neg(yfinal) else: s1 = mpc_neg(y) # s -= log(-z) s1 = mpc_sub(s1, mpc_log(mpc_neg(zorig), wp), wp) # floor(re(z)) rezfloor = mpf_floor(zorig[0]) imzsign = mpf_sign(zorig[1]) pi = mpf_pi(wp) t = mpf_mul(pi, rezfloor) t = mpf_mul_int(t, imzsign, wp) s1 = (s1[0], mpf_add(s1[1], t, wp)) s1 = mpc_add_mpf(s1, mpf_log(pi, wp), wp) t = mpc_sin_pi(mpc_sub_mpf(zorig, rezfloor), wp) t = mpc_log(t, wp) s1 = mpc_sub(s1, t, wp) # Note: may actually be unused, because we fall back # to the mpf_ function for real arguments if not imzsign: t = mpf_mul(pi, mpf_floor(rezfloor), wp) s1 = (s1[0], mpf_sub(s1[1], t, wp)) return mpc_pos(s1, prec, rnd) else: if type == 0: if r: return mpc_div(mpc_exp(y, wp), r, prec, rnd) return mpc_exp(y, prec, rnd) if type == 2: if r: return mpc_div(r, mpc_exp(y, wp), prec, rnd) return mpc_exp(mpc_neg(y), prec, rnd) if type == 3: return mpc_pos(y, prec, rnd) def mpf_factorial(x, prec, rnd='d'): return mpf_gamma(x, prec, rnd, 1) def mpc_factorial(x, prec, rnd='d'): return mpc_gamma(x, prec, rnd, 1) def mpf_rgamma(x, prec, rnd='d'): return mpf_gamma(x, prec, rnd, 2) def mpc_rgamma(x, prec, rnd='d'): return mpc_gamma(x, prec, rnd, 2) def mpf_loggamma(x, prec, rnd='d'): sign, man, exp, bc = x if sign: raise ComplexResult return mpf_gamma(x, prec, rnd, 3) def mpc_loggamma(z, prec, rnd='d'): a, b = z asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b if b == fzero and asign: re = mpf_gamma(a, prec, rnd, 3) n = (-aman) >> (-aexp) im = mpf_mul_int(mpf_pi(prec+10), n, prec, rnd) return re, im return mpc_gamma(z, prec, rnd, 3) def mpf_gamma_int(n, prec, rnd=round_fast): if n < SMALL_FACTORIAL_CACHE_SIZE: return mpf_pos(small_factorial_cache[n-1], prec, rnd) return mpf_gamma(from_int(n), prec, rnd) mpmath-1.1.0/mpmath/libmp/libelefun.py000066400000000000000000001255251340375245600177320ustar00rootroot00000000000000""" This module implements computation of elementary transcendental functions (powers, logarithms, trigonometric and hyperbolic functions, inverse trigonometric and hyperbolic) for real floating-point numbers. For complex and interval implementations of the same functions, see libmpc and libmpi. """ import math from bisect import bisect from .backend import xrange from .backend import MPZ, MPZ_ZERO, MPZ_ONE, MPZ_TWO, MPZ_FIVE, BACKEND from .libmpf import ( round_floor, round_ceiling, round_down, round_up, round_nearest, round_fast, ComplexResult, bitcount, bctable, lshift, rshift, giant_steps, sqrt_fixed, from_int, to_int, from_man_exp, to_fixed, to_float, from_float, from_rational, normalize, fzero, fone, fnone, fhalf, finf, fninf, fnan, mpf_cmp, mpf_sign, mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_div, mpf_shift, mpf_rdiv_int, mpf_pow_int, mpf_sqrt, reciprocal_rnd, negative_rnd, mpf_perturb, isqrt_fast ) from .libintmath import ifib #------------------------------------------------------------------------------- # Tuning parameters #------------------------------------------------------------------------------- # Cutoff for computing exp from cosh+sinh. This reduces the # number of terms by half, but also requires a square root which # is expensive with the pure-Python square root code. if BACKEND == 'python': EXP_COSH_CUTOFF = 600 else: EXP_COSH_CUTOFF = 400 # Cutoff for using more than 2 series EXP_SERIES_U_CUTOFF = 1500 # Also basically determined by sqrt if BACKEND == 'python': COS_SIN_CACHE_PREC = 400 else: COS_SIN_CACHE_PREC = 200 COS_SIN_CACHE_STEP = 8 cos_sin_cache = {} # Number of integer logarithms to cache (for zeta sums) MAX_LOG_INT_CACHE = 2000 log_int_cache = {} LOG_TAYLOR_PREC = 2500 # Use Taylor series with caching up to this prec LOG_TAYLOR_SHIFT = 9 # Cache log values in steps of size 2^-N log_taylor_cache = {} # prec/size ratio of x for fastest convergence in AGM formula LOG_AGM_MAG_PREC_RATIO = 20 ATAN_TAYLOR_PREC = 3000 # Same as for log ATAN_TAYLOR_SHIFT = 7 # steps of size 2^-N atan_taylor_cache = {} # ~= next power of two + 20 cache_prec_steps = [22,22] for k in xrange(1, bitcount(LOG_TAYLOR_PREC)+1): cache_prec_steps += [min(2**k,LOG_TAYLOR_PREC)+20] * 2**(k-1) #----------------------------------------------------------------------------# # # # Elementary mathematical constants # # # #----------------------------------------------------------------------------# def constant_memo(f): """ Decorator for caching computed values of mathematical constants. This decorator should be applied to a function taking a single argument prec as input and returning a fixed-point value with the given precision. """ f.memo_prec = -1 f.memo_val = None def g(prec, **kwargs): memo_prec = f.memo_prec if prec <= memo_prec: return f.memo_val >> (memo_prec-prec) newprec = int(prec*1.05+10) f.memo_val = f(newprec, **kwargs) f.memo_prec = newprec return f.memo_val >> (newprec-prec) g.__name__ = f.__name__ g.__doc__ = f.__doc__ return g def def_mpf_constant(fixed): """ Create a function that computes the mpf value for a mathematical constant, given a function that computes the fixed-point value. Assumptions: the constant is positive and has magnitude ~= 1; the fixed-point function rounds to floor. """ def f(prec, rnd=round_fast): wp = prec + 20 v = fixed(wp) if rnd in (round_up, round_ceiling): v += 1 return normalize(0, v, -wp, bitcount(v), prec, rnd) f.__doc__ = fixed.__doc__ return f def bsp_acot(q, a, b, hyperbolic): if b - a == 1: a1 = MPZ(2*a + 3) if hyperbolic or a&1: return MPZ_ONE, a1 * q**2, a1 else: return -MPZ_ONE, a1 * q**2, a1 m = (a+b)//2 p1, q1, r1 = bsp_acot(q, a, m, hyperbolic) p2, q2, r2 = bsp_acot(q, m, b, hyperbolic) return q2*p1 + r1*p2, q1*q2, r1*r2 # the acoth(x) series converges like the geometric series for x^2 # N = ceil(p*log(2)/(2*log(x))) def acot_fixed(a, prec, hyperbolic): """ Compute acot(a) or acoth(a) for an integer a with binary splitting; see http://numbers.computation.free.fr/Constants/Algorithms/splitting.html """ N = int(0.35 * prec/math.log(a) + 20) p, q, r = bsp_acot(a, 0,N, hyperbolic) return ((p+q)<> extraprec) # Logarithms of integers are needed for various computations involving # logarithms, powers, radix conversion, etc @constant_memo def ln2_fixed(prec): """ Computes ln(2). This is done with a hyperbolic Machin-type formula, with binary splitting at high precision. """ return machin([(18, 26), (-2, 4801), (8, 8749)], prec, True) @constant_memo def ln10_fixed(prec): """ Computes ln(10). This is done with a hyperbolic Machin-type formula. """ return machin([(46, 31), (34, 49), (20, 161)], prec, True) r""" For computation of pi, we use the Chudnovsky series: oo ___ k 1 \ (-1) (6 k)! (A + B k) ----- = ) ----------------------- 12 pi /___ 3 3k+3/2 (3 k)! (k!) C k = 0 where A, B, and C are certain integer constants. This series adds roughly 14 digits per term. Note that C^(3/2) can be extracted so that the series contains only rational terms. This makes binary splitting very efficient. The recurrence formulas for the binary splitting were taken from ftp://ftp.gmplib.org/pub/src/gmp-chudnovsky.c Previously, Machin's formula was used at low precision and the AGM iteration was used at high precision. However, the Chudnovsky series is essentially as fast as the Machin formula at low precision and in practice about 3x faster than the AGM at high precision (despite theoretically having a worse asymptotic complexity), so there is no reason not to use it in all cases. """ # Constants in Chudnovsky's series CHUD_A = MPZ(13591409) CHUD_B = MPZ(545140134) CHUD_C = MPZ(640320) CHUD_D = MPZ(12) def bs_chudnovsky(a, b, level, verbose): """ Computes the sum from a to b of the series in the Chudnovsky formula. Returns g, p, q where p/q is the sum as an exact fraction and g is a temporary value used to save work for recursive calls. """ if b-a == 1: g = MPZ((6*b-5)*(2*b-1)*(6*b-1)) p = b**3 * CHUD_C**3 // 24 q = (-1)**b * g * (CHUD_A+CHUD_B*b) else: if verbose and level < 4: print(" binary splitting", a, b) mid = (a+b)//2 g1, p1, q1 = bs_chudnovsky(a, mid, level+1, verbose) g2, p2, q2 = bs_chudnovsky(mid, b, level+1, verbose) p = p1*p2 g = g1*g2 q = q1*p2 + q2*g1 return g, p, q @constant_memo def pi_fixed(prec, verbose=False, verbose_base=None): """ Compute floor(pi * 2**prec) as a big integer. This is done using Chudnovsky's series (see comments in libelefun.py for details). """ # The Chudnovsky series gives 14.18 digits per term N = int(prec/3.3219280948/14.181647462 + 2) if verbose: print("binary splitting with N =", N) g, p, q = bs_chudnovsky(0, N, 0, verbose) sqrtC = isqrt_fast(CHUD_C<<(2*prec)) v = p*CHUD_C*sqrtC//((q+CHUD_A*p)*CHUD_D) return v def degree_fixed(prec): return pi_fixed(prec)//180 def bspe(a, b): """ Sum series for exp(1)-1 between a, b, returning the result as an exact fraction (p, q). """ if b-a == 1: return MPZ_ONE, MPZ(b) m = (a+b)//2 p1, q1 = bspe(a, m) p2, q2 = bspe(m, b) return p1*q2+p2, q1*q2 @constant_memo def e_fixed(prec): """ Computes exp(1). This is done using the ordinary Taylor series for exp, with binary splitting. For a description of the algorithm, see: http://numbers.computation.free.fr/Constants/ Algorithms/splitting.html """ # Slight overestimate of N needed for 1/N! < 2**(-prec) # This could be tightened for large N. N = int(1.1*prec/math.log(prec) + 20) p, q = bspe(0,N) return ((p+q)<> 11 mpf_phi = def_mpf_constant(phi_fixed) mpf_pi = def_mpf_constant(pi_fixed) mpf_e = def_mpf_constant(e_fixed) mpf_degree = def_mpf_constant(degree_fixed) mpf_ln2 = def_mpf_constant(ln2_fixed) mpf_ln10 = def_mpf_constant(ln10_fixed) @constant_memo def ln_sqrt2pi_fixed(prec): wp = prec + 10 # ln(sqrt(2*pi)) = ln(2*pi)/2 return to_fixed(mpf_log(mpf_shift(mpf_pi(wp), 1), wp), prec-1) @constant_memo def sqrtpi_fixed(prec): return sqrt_fixed(pi_fixed(prec), prec) mpf_sqrtpi = def_mpf_constant(sqrtpi_fixed) mpf_ln_sqrt2pi = def_mpf_constant(ln_sqrt2pi_fixed) #----------------------------------------------------------------------------# # # # Powers # # # #----------------------------------------------------------------------------# def mpf_pow(s, t, prec, rnd=round_fast): """ Compute s**t. Raises ComplexResult if s is negative and t is fractional. """ ssign, sman, sexp, sbc = s tsign, tman, texp, tbc = t if ssign and texp < 0: raise ComplexResult("negative number raised to a fractional power") if texp >= 0: return mpf_pow_int(s, (-1)**tsign * (tman<> pbc)] if pbc > workprec: pm = pm >> (pbc-workprec) pe += pbc - workprec pbc = workprec n -= 1 if not n: break y = y*y exp = exp+exp bc = bc + bc - 2 bc = bc + bctable[int(y >> bc)] if bc > workprec: y = y >> (bc-workprec) exp += bc - workprec bc = workprec n = n // 2 return pm, pe # froot(s, n, prec, rnd) computes the real n-th root of a # positive mpf tuple s. # To compute the root we start from a 50-bit estimate for r # generated with ordinary floating-point arithmetic, and then refine # the value to full accuracy using the iteration # 1 / y \ # r = --- | (n-1) * r + ---------- | # n+1 n \ n r_n**(n-1) / # which is simply Newton's method applied to the equation r**n = y. # With giant_steps(start, prec+extra) = [p0,...,pm, prec+extra] # and y = man * 2**-shift one has # (man * 2**exp)**(1/n) = # y**(1/n) * 2**(start-prec/n) * 2**(p0-start) * ... * 2**(prec+extra-pm) * # 2**((exp+shift-(n-1)*prec)/n -extra)) # The last factor is accounted for in the last line of froot. def nthroot_fixed(y, n, prec, exp1): start = 50 try: y1 = rshift(y, prec - n*start) r = MPZ(int(y1**(1.0/n))) except OverflowError: y1 = from_int(y1, start) fn = from_int(n) fn = mpf_rdiv_int(1, fn, start) r = mpf_pow(y1, fn, start) r = to_int(r) extra = 10 extra1 = n prevp = start for p in giant_steps(start, prec+extra): pm, pe = int_pow_fixed(r, n-1, prevp) r2 = rshift(pm, (n-1)*prevp - p - pe - extra1) B = lshift(y, 2*p-prec+extra1)//r2 r = (B + (n-1) * lshift(r, p-prevp))//n prevp = p return r def mpf_nthroot(s, n, prec, rnd=round_fast): """nth-root of a positive number Use the Newton method when faster, otherwise use x**(1/n) """ sign, man, exp, bc = s if sign: raise ComplexResult("nth root of a negative number") if not man: if s == fnan: return fnan if s == fzero: if n > 0: return fzero if n == 0: return fone return finf # Infinity if not n: return fnan if n < 0: return fzero return finf flag_inverse = False if n < 2: if n == 0: return fone if n == 1: return mpf_pos(s, prec, rnd) if n == -1: return mpf_div(fone, s, prec, rnd) # n < 0 rnd = reciprocal_rnd[rnd] flag_inverse = True extra_inverse = 5 prec += extra_inverse n = -n if n > 20 and (n >= 20000 or prec < int(233 + 28.3 * n**0.62)): prec2 = prec + 10 fn = from_int(n) nth = mpf_rdiv_int(1, fn, prec2) r = mpf_pow(s, nth, prec2, rnd) s = normalize(r[0], r[1], r[2], r[3], prec, rnd) if flag_inverse: return mpf_div(fone, s, prec-extra_inverse, rnd) else: return s # Convert to a fixed-point number with prec2 bits. prec2 = prec + 2*n - (prec%n) # a few tests indicate that # for 10 < n < 10**4 a bit more precision is needed if n > 10: prec2 += prec2//10 prec2 = prec2 - prec2%n # Mantissa may have more bits than we need. Trim it down. shift = bc - prec2 # Adjust exponents to make prec2 and exp+shift multiples of n. sign1 = 0 es = exp+shift if es < 0: sign1 = 1 es = -es if sign1: shift += es%n else: shift -= es%n man = rshift(man, shift) extra = 10 exp1 = ((exp+shift-(n-1)*prec2)//n) - extra rnd_shift = 0 if flag_inverse: if rnd == 'u' or rnd == 'c': rnd_shift = 1 else: if rnd == 'd' or rnd == 'f': rnd_shift = 1 man = nthroot_fixed(man+rnd_shift, n, prec2, exp1) s = from_man_exp(man, exp1, prec, rnd) if flag_inverse: return mpf_div(fone, s, prec-extra_inverse, rnd) else: return s def mpf_cbrt(s, prec, rnd=round_fast): """cubic root of a positive number""" return mpf_nthroot(s, 3, prec, rnd) #----------------------------------------------------------------------------# # # # Logarithms # # # #----------------------------------------------------------------------------# def log_int_fixed(n, prec, ln2=None): """ Fast computation of log(n), caching the value for small n, intended for zeta sums. """ if n in log_int_cache: value, vprec = log_int_cache[n] if vprec >= prec: return value >> (vprec - prec) wp = prec + 10 if wp <= LOG_TAYLOR_SHIFT: if ln2 is None: ln2 = ln2_fixed(wp) r = bitcount(n) x = n << (wp-r) v = log_taylor_cached(x, wp) + r*ln2 else: v = to_fixed(mpf_log(from_int(n), wp+5), wp) if n < MAX_LOG_INT_CACHE: log_int_cache[n] = (v, wp) return v >> (wp-prec) def agm_fixed(a, b, prec): """ Fixed-point computation of agm(a,b), assuming a, b both close to unit magnitude. """ i = 0 while 1: anew = (a+b)>>1 if i > 4 and abs(a-anew) < 8: return a b = isqrt_fast(a*b) a = anew i += 1 return a def log_agm(x, prec): """ Fixed-point computation of -log(x) = log(1/x), suitable for large precision. It is required that 0 < x < 1. The algorithm used is the Sasaki-Kanada formula -log(x) = pi/agm(theta2(x)^2,theta3(x)^2). [1] For faster convergence in the theta functions, x should be chosen closer to 0. Guard bits must be added by the caller. HYPOTHESIS: if x = 2^(-n), n bits need to be added to account for the truncation to a fixed-point number, and this is the only significant cancellation error. The number of bits lost to roundoff is small and can be considered constant. [1] Richard P. Brent, "Fast Algorithms for High-Precision Computation of Elementary Functions (extended abstract)", http://wwwmaths.anu.edu.au/~brent/pd/RNC7-Brent.pdf """ x2 = (x*x) >> prec # Compute jtheta2(x)**2 s = a = b = x2 while a: b = (b*x2) >> prec a = (a*b) >> prec s += a s += (MPZ_ONE<>(prec-2) s = (s*isqrt_fast(x<>prec # Compute jtheta3(x)**2 t = a = b = x while a: b = (b*x2) >> prec a = (a*b) >> prec t += a t = (MPZ_ONE<>prec # Final formula p = agm_fixed(s, t, prec) return (pi_fixed(prec) << prec) // p def log_taylor(x, prec, r=0): """ Fixed-point calculation of log(x). It is assumed that x is close enough to 1 for the Taylor series to converge quickly. Convergence can be improved by specifying r > 0 to compute log(x^(1/2^r))*2^r, at the cost of performing r square roots. The caller must provide sufficient guard bits. """ for i in xrange(r): x = isqrt_fast(x<> prec v4 = (v2*v2) >> prec s0 = v s1 = v//3 v = (v*v4) >> prec k = 5 while v: s0 += v // k k += 2 s1 += v // k v = (v*v4) >> prec k += 2 s1 = (s1*v2) >> prec s = (s0+s1) << (1+r) if sign: return -s return s def log_taylor_cached(x, prec): """ Fixed-point computation of log(x), assuming x in (0.5, 2) and prec <= LOG_TAYLOR_PREC. """ n = x >> (prec-LOG_TAYLOR_SHIFT) cached_prec = cache_prec_steps[prec] dprec = cached_prec - prec if (n, cached_prec) in log_taylor_cache: a, log_a = log_taylor_cache[n, cached_prec] else: a = n << (cached_prec - LOG_TAYLOR_SHIFT) log_a = log_taylor(a, cached_prec, 8) log_taylor_cache[n, cached_prec] = (a, log_a) a >>= dprec log_a >>= dprec u = ((x - a) << prec) // a v = (u << prec) // ((MPZ_TWO << prec) + u) v2 = (v*v) >> prec v4 = (v2*v2) >> prec s0 = v s1 = v//3 v = (v*v4) >> prec k = 5 while v: s0 += v//k k += 2 s1 += v//k v = (v*v4) >> prec k += 2 s1 = (s1*v2) >> prec s = (s0+s1) << 1 return log_a + s def mpf_log(x, prec, rnd=round_fast): """ Compute the natural logarithm of the mpf value x. If x is negative, ComplexResult is raised. """ sign, man, exp, bc = x #------------------------------------------------------------------ # Handle special values if not man: if x == fzero: return fninf if x == finf: return finf if x == fnan: return fnan if sign: raise ComplexResult("logarithm of a negative number") wp = prec + 20 #------------------------------------------------------------------ # Handle log(2^n) = log(n)*2. # Here we catch the only possible exact value, log(1) = 0 if man == 1: if not exp: return fzero return from_man_exp(exp*ln2_fixed(wp), -wp, prec, rnd) mag = exp+bc abs_mag = abs(mag) #------------------------------------------------------------------ # Handle x = 1+eps, where log(x) ~ x. We need to check for # cancellation when moving to fixed-point math and compensate # by increasing the precision. Note that abs_mag in (0, 1) <=> # 0.5 < x < 2 and x != 1 if abs_mag <= 1: # Calculate t = x-1 to measure distance from 1 in bits tsign = 1-abs_mag if tsign: tman = (MPZ_ONE< wp: t = normalize(tsign, tman, abs_mag-bc, tbc, tbc, 'n') return mpf_perturb(t, tsign, prec, rnd) else: wp += cancellation # TODO: if close enough to 1, we could use Taylor series # even in the AGM precision range, since the Taylor series # converges rapidly #------------------------------------------------------------------ # Another special case: # n*log(2) is a good enough approximation if abs_mag > 10000: if bitcount(abs_mag) > wp: return from_man_exp(exp*ln2_fixed(wp), -wp, prec, rnd) #------------------------------------------------------------------ # General case. # Perform argument reduction using log(x) = log(x*2^n) - n*log(2): # If we are in the Taylor precision range, choose magnitude 0 or 1. # If we are in the AGM precision range, choose magnitude -m for # some large m; benchmarking on one machine showed m = prec/20 to be # optimal between 1000 and 100,000 digits. if wp <= LOG_TAYLOR_PREC: m = log_taylor_cached(lshift(man, wp-bc), wp) if mag: m += mag*ln2_fixed(wp) else: optimal_mag = -wp//LOG_AGM_MAG_PREC_RATIO n = optimal_mag - mag x = mpf_shift(x, n) wp += (-optimal_mag) m = -log_agm(to_fixed(x, wp), wp) m -= n*ln2_fixed(wp) return from_man_exp(m, -wp, prec, rnd) def mpf_log_hypot(a, b, prec, rnd): """ Computes log(sqrt(a^2+b^2)) accurately. """ # If either a or b is inf/nan/0, assume it to be a if not b[1]: a, b = b, a # a is inf/nan/0 if not a[1]: # both are inf/nan/0 if not b[1]: if a == b == fzero: return fninf if fnan in (a, b): return fnan # at least one term is (+/- inf)^2 return finf # only a is inf/nan/0 if a == fzero: # log(sqrt(0+b^2)) = log(|b|) return mpf_log(mpf_abs(b), prec, rnd) if a == fnan: return fnan return finf # Exact a2 = mpf_mul(a,a) b2 = mpf_mul(b,b) extra = 20 # Not exact h2 = mpf_add(a2, b2, prec+extra) cancelled = mpf_add(h2, fnone, 10) mag_cancelled = cancelled[2]+cancelled[3] # Just redo the sum exactly if necessary (could be smarter # and avoid memory allocation when a or b is precisely 1 # and the other is tiny...) if cancelled == fzero or mag_cancelled < -extra//2: h2 = mpf_add(a2, b2, prec+extra-min(a2[2],b2[2])) return mpf_shift(mpf_log(h2, prec, rnd), -1) #---------------------------------------------------------------------- # Inverse tangent # def atan_newton(x, prec): if prec >= 100: r = math.atan(int((x>>(prec-53)))/2.0**53) else: r = math.atan(int(x)/2.0**prec) prevp = 50 r = MPZ(int(r * 2.0**53) >> (53-prevp)) extra_p = 50 for wp in giant_steps(prevp, prec): wp += extra_p r = r << (wp-prevp) cos, sin = cos_sin_fixed(r, wp) tan = (sin << wp) // cos a = ((tan-rshift(x, prec-wp)) << wp) // ((MPZ_ONE<>wp)) r = r - a prevp = wp return rshift(r, prevp-prec) def atan_taylor_get_cached(n, prec): # Taylor series with caching wins up to huge precisions # To avoid unnecessary precomputation at low precision, we # do it in steps # Round to next power of 2 prec2 = (1<<(bitcount(prec-1))) + 20 dprec = prec2 - prec if (n, prec2) in atan_taylor_cache: a, atan_a = atan_taylor_cache[n, prec2] else: a = n << (prec2 - ATAN_TAYLOR_SHIFT) atan_a = atan_newton(a, prec2) atan_taylor_cache[n, prec2] = (a, atan_a) return (a >> dprec), (atan_a >> dprec) def atan_taylor(x, prec): n = (x >> (prec-ATAN_TAYLOR_SHIFT)) a, atan_a = atan_taylor_get_cached(n, prec) d = x - a s0 = v = (d << prec) // ((a**2 >> prec) + (a*d >> prec) + (MPZ_ONE << prec)) v2 = (v**2 >> prec) v4 = (v2 * v2) >> prec s1 = v//3 v = (v * v4) >> prec k = 5 while v: s0 += v // k k += 2 s1 += v // k v = (v * v4) >> prec k += 2 s1 = (s1 * v2) >> prec s = s0 - s1 return atan_a + s def atan_inf(sign, prec, rnd): if not sign: return mpf_shift(mpf_pi(prec, rnd), -1) return mpf_neg(mpf_shift(mpf_pi(prec, negative_rnd[rnd]), -1)) def mpf_atan(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if x == fzero: return fzero if x == finf: return atan_inf(0, prec, rnd) if x == fninf: return atan_inf(1, prec, rnd) return fnan mag = exp + bc # Essentially infinity if mag > prec+20: return atan_inf(sign, prec, rnd) # Essentially ~ x if -mag > prec+20: return mpf_perturb(x, 1-sign, prec, rnd) wp = prec + 30 + abs(mag) # For large x, use atan(x) = pi/2 - atan(1/x) if mag >= 2: x = mpf_rdiv_int(1, x, wp) reciprocal = True else: reciprocal = False t = to_fixed(x, wp) if sign: t = -t if wp < ATAN_TAYLOR_PREC: a = atan_taylor(t, wp) else: a = atan_newton(t, wp) if reciprocal: a = ((pi_fixed(wp)>>1)+1) - a if sign: a = -a return from_man_exp(a, -wp, prec, rnd) # TODO: cleanup the special cases def mpf_atan2(y, x, prec, rnd=round_fast): xsign, xman, xexp, xbc = x ysign, yman, yexp, ybc = y if not yman: if y == fzero and x != fnan: if mpf_sign(x) >= 0: return fzero return mpf_pi(prec, rnd) if y in (finf, fninf): if x in (finf, fninf): return fnan # pi/2 if y == finf: return mpf_shift(mpf_pi(prec, rnd), -1) # -pi/2 return mpf_neg(mpf_shift(mpf_pi(prec, negative_rnd[rnd]), -1)) return fnan if ysign: return mpf_neg(mpf_atan2(mpf_neg(y), x, prec, negative_rnd[rnd])) if not xman: if x == fnan: return fnan if x == finf: return fzero if x == fninf: return mpf_pi(prec, rnd) if y == fzero: return fzero return mpf_shift(mpf_pi(prec, rnd), -1) tquo = mpf_atan(mpf_div(y, x, prec+4), prec+4) if xsign: return mpf_add(mpf_pi(prec+4), tquo, prec, rnd) else: return mpf_pos(tquo, prec, rnd) def mpf_asin(x, prec, rnd=round_fast): sign, man, exp, bc = x if bc+exp > 0 and x not in (fone, fnone): raise ComplexResult("asin(x) is real only for -1 <= x <= 1") # asin(x) = 2*atan(x/(1+sqrt(1-x**2))) wp = prec + 15 a = mpf_mul(x, x) b = mpf_add(fone, mpf_sqrt(mpf_sub(fone, a, wp), wp), wp) c = mpf_div(x, b, wp) return mpf_shift(mpf_atan(c, prec, rnd), 1) def mpf_acos(x, prec, rnd=round_fast): # acos(x) = 2*atan(sqrt(1-x**2)/(1+x)) sign, man, exp, bc = x if bc + exp > 0: if x not in (fone, fnone): raise ComplexResult("acos(x) is real only for -1 <= x <= 1") if x == fnone: return mpf_pi(prec, rnd) wp = prec + 15 a = mpf_mul(x, x) b = mpf_sqrt(mpf_sub(fone, a, wp), wp) c = mpf_div(b, mpf_add(fone, x, wp), wp) return mpf_shift(mpf_atan(c, prec, rnd), 1) def mpf_asinh(x, prec, rnd=round_fast): wp = prec + 20 sign, man, exp, bc = x mag = exp+bc if mag < -8: if mag < -wp: return mpf_perturb(x, 1-sign, prec, rnd) wp += (-mag) # asinh(x) = log(x+sqrt(x**2+1)) # use reflection symmetry to avoid cancellation q = mpf_sqrt(mpf_add(mpf_mul(x, x), fone, wp), wp) q = mpf_add(mpf_abs(x), q, wp) if sign: return mpf_neg(mpf_log(q, prec, negative_rnd[rnd])) else: return mpf_log(q, prec, rnd) def mpf_acosh(x, prec, rnd=round_fast): # acosh(x) = log(x+sqrt(x**2-1)) wp = prec + 15 if mpf_cmp(x, fone) == -1: raise ComplexResult("acosh(x) is real only for x >= 1") q = mpf_sqrt(mpf_add(mpf_mul(x,x), fnone, wp), wp) return mpf_log(mpf_add(x, q, wp), prec, rnd) def mpf_atanh(x, prec, rnd=round_fast): # atanh(x) = log((1+x)/(1-x))/2 sign, man, exp, bc = x if (not man) and exp: if x in (fzero, fnan): return x raise ComplexResult("atanh(x) is real only for -1 <= x <= 1") mag = bc + exp if mag > 0: if mag == 1 and man == 1: return [finf, fninf][sign] raise ComplexResult("atanh(x) is real only for -1 <= x <= 1") wp = prec + 15 if mag < -8: if mag < -wp: return mpf_perturb(x, sign, prec, rnd) wp += (-mag) a = mpf_add(x, fone, wp) b = mpf_sub(fone, x, wp) return mpf_shift(mpf_log(mpf_div(a, b, wp), prec, rnd), -1) def mpf_fibonacci(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if x == fninf: return fnan return x # F(2^n) ~= 2^(2^n) size = abs(exp+bc) if exp >= 0: # Exact if size < 10 or size <= bitcount(prec): return from_int(ifib(to_int(x)), prec, rnd) # Use the modified Binet formula wp = prec + size + 20 a = mpf_phi(wp) b = mpf_add(mpf_shift(a, 1), fnone, wp) u = mpf_pow(a, x, wp) v = mpf_cos_pi(x, wp) v = mpf_div(v, u, wp) u = mpf_sub(u, v, wp) u = mpf_div(u, b, prec, rnd) return u #------------------------------------------------------------------------------- # Exponential-type functions #------------------------------------------------------------------------------- def exponential_series(x, prec, type=0): """ Taylor series for cosh/sinh or cos/sin. type = 0 -- returns exp(x) (slightly faster than cosh+sinh) type = 1 -- returns (cosh(x), sinh(x)) type = 2 -- returns (cos(x), sin(x)) """ if x < 0: x = -x sign = 1 else: sign = 0 r = int(0.5*prec**0.5) xmag = bitcount(x) - prec r = max(0, xmag + r) extra = 10 + 2*max(r,-xmag) wp = prec + extra x <<= (extra - r) one = MPZ_ONE << wp alt = (type == 2) if prec < EXP_SERIES_U_CUTOFF: x2 = a = (x*x) >> wp x4 = (x2*x2) >> wp s0 = s1 = MPZ_ZERO k = 2 while a: a //= (k-1)*k; s0 += a; k += 2 a //= (k-1)*k; s1 += a; k += 2 a = (a*x4) >> wp s1 = (x2*s1) >> wp if alt: c = s1 - s0 + one else: c = s1 + s0 + one else: u = int(0.3*prec**0.35) x2 = a = (x*x) >> wp xpowers = [one, x2] for i in xrange(1, u): xpowers.append((xpowers[-1]*x2)>>wp) sums = [MPZ_ZERO] * u k = 2 while a: for i in xrange(u): a //= (k-1)*k if alt and k & 2: sums[i] -= a else: sums[i] += a k += 2 a = (a*xpowers[-1]) >> wp for i in xrange(1, u): sums[i] = (sums[i]*xpowers[i]) >> wp c = sum(sums) + one if type == 0: s = isqrt_fast(c*c - (one<> wp return v >> extra else: # Repeatedly apply the double-angle formula # cosh(2*x) = 2*cosh(x)^2 - 1 # cos(2*x) = 2*cos(x)^2 - 1 pshift = wp-1 for i in xrange(r): c = ((c*c) >> pshift) - one # With the abs, this is the same for sinh and sin s = isqrt_fast(abs((one<>extra), (s>>extra) def exp_basecase(x, prec): """ Compute exp(x) as a fixed-point number. Works for any x, but for speed should have |x| < 1. For an arbitrary number, use exp(x) = exp(x-m*log(2)) * 2^m where m = floor(x/log(2)). """ if prec > EXP_COSH_CUTOFF: return exponential_series(x, prec, 0) r = int(prec**0.5) prec += r s0 = s1 = (MPZ_ONE << prec) k = 2 a = x2 = (x*x) >> prec while a: a //= k; s0 += a; k += 1 a //= k; s1 += a; k += 1 a = (a*x2) >> prec s1 = (s1*x) >> prec s = s0 + s1 u = r while r: s = (s*s) >> prec r -= 1 return s >> u def exp_expneg_basecase(x, prec): """ Computation of exp(x), exp(-x) """ if prec > EXP_COSH_CUTOFF: cosh, sinh = exponential_series(x, prec, 1) return cosh+sinh, cosh-sinh a = exp_basecase(x, prec) b = (MPZ_ONE << (prec+prec)) // a return a, b def cos_sin_basecase(x, prec): """ Compute cos(x), sin(x) as fixed-point numbers, assuming x in [0, pi/2). For an arbitrary number, use x' = x - m*(pi/2) where m = floor(x/(pi/2)) along with quarter-period symmetries. """ if prec > COS_SIN_CACHE_PREC: return exponential_series(x, prec, 2) precs = prec - COS_SIN_CACHE_STEP t = x >> precs n = int(t) if n not in cos_sin_cache: w = t<<(10+COS_SIN_CACHE_PREC-COS_SIN_CACHE_STEP) cos_t, sin_t = exponential_series(w, 10+COS_SIN_CACHE_PREC, 2) cos_sin_cache[n] = (cos_t>>10), (sin_t>>10) cos_t, sin_t = cos_sin_cache[n] offset = COS_SIN_CACHE_PREC - prec cos_t >>= offset sin_t >>= offset x -= t << precs cos = MPZ_ONE << prec sin = x k = 2 a = -((x*x) >> prec) while a: a //= k; cos += a; k += 1; a = (a*x) >> prec a //= k; sin += a; k += 1; a = -((a*x) >> prec) return ((cos*cos_t-sin*sin_t) >> prec), ((sin*cos_t+cos*sin_t) >> prec) def mpf_exp(x, prec, rnd=round_fast): sign, man, exp, bc = x if man: mag = bc + exp wp = prec + 14 if sign: man = -man # TODO: the best cutoff depends on both x and the precision. if prec > 600 and exp >= 0: # Need about log2(exp(n)) ~= 1.45*mag extra precision e = mpf_e(wp+int(1.45*mag)) return mpf_pow_int(e, man<= 2 if mag > 1: # For large arguments: exp(2^mag*(1+eps)) = # exp(2^mag)*exp(2^mag*eps) = exp(2^mag)*(1 + 2^mag*eps + ...) # so about mag extra bits is required. wpmod = wp + mag offset = exp + wpmod if offset >= 0: t = man << offset else: t = man >> (-offset) lg2 = ln2_fixed(wpmod) n, t = divmod(t, lg2) n = int(n) t >>= mag else: offset = exp + wp if offset >= 0: t = man << offset else: t = man >> (-offset) n = 0 man = exp_basecase(t, wp) return from_man_exp(man, n-wp, prec, rnd) if not exp: return fone if x == fninf: return fzero return x def mpf_cosh_sinh(x, prec, rnd=round_fast, tanh=0): """Simultaneously compute (cosh(x), sinh(x)) for real x""" sign, man, exp, bc = x if (not man) and exp: if tanh: if x == finf: return fone if x == fninf: return fnone return fnan if x == finf: return (finf, finf) if x == fninf: return (finf, fninf) return fnan, fnan mag = exp+bc wp = prec+14 if mag < -4: # Extremely close to 0, sinh(x) ~= x and cosh(x) ~= 1 if mag < -wp: if tanh: return mpf_perturb(x, 1-sign, prec, rnd) cosh = mpf_perturb(fone, 0, prec, rnd) sinh = mpf_perturb(x, sign, prec, rnd) return cosh, sinh # Fix for cancellation when computing sinh wp += (-mag) # Does exp(-2*x) vanish? if mag > 10: if 3*(1<<(mag-1)) > wp: # XXX: rounding if tanh: return mpf_perturb([fone,fnone][sign], 1-sign, prec, rnd) c = s = mpf_shift(mpf_exp(mpf_abs(x), prec, rnd), -1) if sign: s = mpf_neg(s) return c, s # |x| > 1 if mag > 1: wpmod = wp + mag offset = exp + wpmod if offset >= 0: t = man << offset else: t = man >> (-offset) lg2 = ln2_fixed(wpmod) n, t = divmod(t, lg2) n = int(n) t >>= mag else: offset = exp + wp if offset >= 0: t = man << offset else: t = man >> (-offset) n = 0 a, b = exp_expneg_basecase(t, wp) # TODO: optimize division precision cosh = a + (b>>(2*n)) sinh = a - (b>>(2*n)) if sign: sinh = -sinh if tanh: man = (sinh << wp) // cosh return from_man_exp(man, -wp, prec, rnd) else: cosh = from_man_exp(cosh, n-wp-1, prec, rnd) sinh = from_man_exp(sinh, n-wp-1, prec, rnd) return cosh, sinh def mod_pi2(man, exp, mag, wp): # Reduce to standard interval if mag > 0: i = 0 while 1: cancellation_prec = 20 << i wpmod = wp + mag + cancellation_prec pi2 = pi_fixed(wpmod-1) pi4 = pi2 >> 1 offset = wpmod + exp if offset >= 0: t = man << offset else: t = man >> (-offset) n, y = divmod(t, pi2) if y > pi4: small = pi2 - y else: small = y if small >> (wp+mag-10): n = int(n) t = y >> mag wp = wpmod - mag break i += 1 else: wp += (-mag) offset = exp + wp if offset >= 0: t = man << offset else: t = man >> (-offset) n = 0 return t, n, wp def mpf_cos_sin(x, prec, rnd=round_fast, which=0, pi=False): """ which: 0 -- return cos(x), sin(x) 1 -- return cos(x) 2 -- return sin(x) 3 -- return tan(x) if pi=True, compute for pi*x """ sign, man, exp, bc = x if not man: if exp: c, s = fnan, fnan else: c, s = fone, fzero if which == 0: return c, s if which == 1: return c if which == 2: return s if which == 3: return s mag = bc + exp wp = prec + 10 # Extremely small? if mag < 0: if mag < -wp: if pi: x = mpf_mul(x, mpf_pi(wp)) c = mpf_perturb(fone, 1, prec, rnd) s = mpf_perturb(x, 1-sign, prec, rnd) if which == 0: return c, s if which == 1: return c if which == 2: return s if which == 3: return mpf_perturb(x, sign, prec, rnd) if pi: if exp >= -1: if exp == -1: c = fzero s = (fone, fnone)[bool(man & 2) ^ sign] elif exp == 0: c, s = (fnone, fzero) else: c, s = (fone, fzero) if which == 0: return c, s if which == 1: return c if which == 2: return s if which == 3: return mpf_div(s, c, prec, rnd) # Subtract nearest half-integer (= mod by pi/2) n = ((man >> (-exp-2)) + 1) >> 1 man = man - (n << (-exp-1)) mag2 = bitcount(man) + exp wp = prec + 10 - mag2 offset = exp + wp if offset >= 0: t = man << offset else: t = man >> (-offset) t = (t*pi_fixed(wp)) >> wp else: t, n, wp = mod_pi2(man, exp, mag, wp) c, s = cos_sin_basecase(t, wp) m = n & 3 if m == 1: c, s = -s, c elif m == 2: c, s = -c, -s elif m == 3: c, s = s, -c if sign: s = -s if which == 0: c = from_man_exp(c, -wp, prec, rnd) s = from_man_exp(s, -wp, prec, rnd) return c, s if which == 1: return from_man_exp(c, -wp, prec, rnd) if which == 2: return from_man_exp(s, -wp, prec, rnd) if which == 3: return from_rational(s, c, prec, rnd) def mpf_cos(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 1) def mpf_sin(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 2) def mpf_tan(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 3) def mpf_cos_sin_pi(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 0, 1) def mpf_cos_pi(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 1, 1) def mpf_sin_pi(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 2, 1) def mpf_cosh(x, prec, rnd=round_fast): return mpf_cosh_sinh(x, prec, rnd)[0] def mpf_sinh(x, prec, rnd=round_fast): return mpf_cosh_sinh(x, prec, rnd)[1] def mpf_tanh(x, prec, rnd=round_fast): return mpf_cosh_sinh(x, prec, rnd, tanh=1) # Low-overhead fixed-point versions def cos_sin_fixed(x, prec, pi2=None): if pi2 is None: pi2 = pi_fixed(prec-1) n, t = divmod(x, pi2) n = int(n) c, s = cos_sin_basecase(t, prec) m = n & 3 if m == 0: return c, s if m == 1: return -s, c if m == 2: return -c, -s if m == 3: return s, -c def exp_fixed(x, prec, ln2=None): if ln2 is None: ln2 = ln2_fixed(prec) n, t = divmod(x, ln2) n = int(n) v = exp_basecase(t, prec) if n >= 0: return v << n else: return v >> (-n) if BACKEND == 'sage': try: import sage.libs.mpmath.ext_libmp as _lbmp mpf_sqrt = _lbmp.mpf_sqrt mpf_exp = _lbmp.mpf_exp mpf_log = _lbmp.mpf_log mpf_cos = _lbmp.mpf_cos mpf_sin = _lbmp.mpf_sin mpf_pow = _lbmp.mpf_pow exp_fixed = _lbmp.exp_fixed cos_sin_fixed = _lbmp.cos_sin_fixed log_int_fixed = _lbmp.log_int_fixed except (ImportError, AttributeError): print("Warning: Sage imports in libelefun failed") mpmath-1.1.0/mpmath/libmp/libhyper.py000066400000000000000000001074201340375245600175750ustar00rootroot00000000000000""" This module implements computation of hypergeometric and related functions. In particular, it provides code for generic summation of hypergeometric series. Optimized versions for various special cases are also provided. """ import operator import math from .backend import MPZ_ZERO, MPZ_ONE, BACKEND, xrange, exec_ from .libintmath import gcd from .libmpf import (\ ComplexResult, round_fast, round_nearest, negative_rnd, bitcount, to_fixed, from_man_exp, from_int, to_int, from_rational, fzero, fone, fnone, ftwo, finf, fninf, fnan, mpf_sign, mpf_add, mpf_abs, mpf_pos, mpf_cmp, mpf_lt, mpf_le, mpf_gt, mpf_min_max, mpf_perturb, mpf_neg, mpf_shift, mpf_sub, mpf_mul, mpf_div, sqrt_fixed, mpf_sqrt, mpf_rdiv_int, mpf_pow_int, to_rational, ) from .libelefun import (\ mpf_pi, mpf_exp, mpf_log, pi_fixed, mpf_cos_sin, mpf_cos, mpf_sin, mpf_sqrt, agm_fixed, ) from .libmpc import (\ mpc_one, mpc_sub, mpc_mul_mpf, mpc_mul, mpc_neg, complex_int_pow, mpc_div, mpc_add_mpf, mpc_sub_mpf, mpc_log, mpc_add, mpc_pos, mpc_shift, mpc_is_infnan, mpc_zero, mpc_sqrt, mpc_abs, mpc_mpf_div, mpc_square, mpc_exp ) from .libintmath import ifac from .gammazeta import mpf_gamma_int, mpf_euler, euler_fixed class NoConvergence(Exception): pass #-----------------------------------------------------------------------# # # # Generic hypergeometric series # # # #-----------------------------------------------------------------------# """ TODO: 1. proper mpq parsing 2. imaginary z special-cased (also: rational, integer?) 3. more clever handling of series that don't converge because of stupid upwards rounding 4. checking for cancellation """ def make_hyp_summator(key): """ Returns a function that sums a generalized hypergeometric series, for given parameter types (integer, rational, real, complex). """ p, q, param_types, ztype = key pstring = "".join(param_types) fname = "hypsum_%i_%i_%s_%s_%s" % (p, q, pstring[:p], pstring[p:], ztype) #print "generating hypsum", fname have_complex_param = 'C' in param_types have_complex_arg = ztype == 'C' have_complex = have_complex_param or have_complex_arg source = [] add = source.append aint = [] arat = [] bint = [] brat = [] areal = [] breal = [] acomplex = [] bcomplex = [] #add("wp = prec + 40") add("MAX = kwargs.get('maxterms', wp*100)") add("HIGH = MPZ_ONE<= 0:") add(" ZRE = xm << offset") add("else:") add(" ZRE = xm >> (-offset)") if have_complex_arg: add("offset = ye + wp") add("if offset >= 0:") add(" ZIM = ym << offset") add("else:") add(" ZIM = ym >> (-offset)") for i, flag in enumerate(param_types): W = ["A", "B"][i >= p] if flag == 'Z': ([aint,bint][i >= p]).append(i) add("%sINT_%i = coeffs[%i]" % (W, i, i)) elif flag == 'Q': ([arat,brat][i >= p]).append(i) add("%sP_%i, %sQ_%i = coeffs[%i]._mpq_" % (W, i, W, i, i)) elif flag == 'R': ([areal,breal][i >= p]).append(i) add("xsign, xm, xe, xbc = coeffs[%i]._mpf_" % i) add("if xsign: xm = -xm") add("offset = xe + wp") add("if offset >= 0:") add(" %sREAL_%i = xm << offset" % (W, i)) add("else:") add(" %sREAL_%i = xm >> (-offset)" % (W, i)) elif flag == 'C': ([acomplex,bcomplex][i >= p]).append(i) add("__re, __im = coeffs[%i]._mpc_" % i) add("xsign, xm, xe, xbc = __re") add("if xsign: xm = -xm") add("ysign, ym, ye, ybc = __im") add("if ysign: ym = -ym") add("offset = xe + wp") add("if offset >= 0:") add(" %sCRE_%i = xm << offset" % (W, i)) add("else:") add(" %sCRE_%i = xm >> (-offset)" % (W, i)) add("offset = ye + wp") add("if offset >= 0:") add(" %sCIM_%i = ym << offset" % (W, i)) add("else:") add(" %sCIM_%i = ym >> (-offset)" % (W, i)) else: raise ValueError l_areal = len(areal) l_breal = len(breal) cancellable_real = min(l_areal, l_breal) noncancellable_real_num = areal[cancellable_real:] noncancellable_real_den = breal[cancellable_real:] # LOOP add("for n in xrange(1,10**8):") add(" if n in magnitude_check:") add(" p_mag = bitcount(abs(PRE))") if have_complex: add(" p_mag = max(p_mag, bitcount(abs(PIM)))") add(" magnitude_check[n] = wp-p_mag") # Real factors multiplier = " * ".join(["AINT_#".replace("#", str(i)) for i in aint] + \ ["AP_#".replace("#", str(i)) for i in arat] + \ ["BQ_#".replace("#", str(i)) for i in brat]) divisor = " * ".join(["BINT_#".replace("#", str(i)) for i in bint] + \ ["BP_#".replace("#", str(i)) for i in brat] + \ ["AQ_#".replace("#", str(i)) for i in arat] + ["n"]) if multiplier: add(" mul = " + multiplier) add(" div = " + divisor) # Check for singular terms add(" if not div:") if multiplier: add(" if not mul:") add(" break") add(" raise ZeroDivisionError") # Update product if have_complex: # TODO: when there are several real parameters and just a few complex # (maybe just the complex argument), we only need to do about # half as many ops if we accumulate the real factor in a single real variable for k in range(cancellable_real): add(" PRE = PRE * AREAL_%i // BREAL_%i" % (areal[k], breal[k])) for i in noncancellable_real_num: add(" PRE = (PRE * AREAL_#) >> wp".replace("#", str(i))) for i in noncancellable_real_den: add(" PRE = (PRE << wp) // BREAL_#".replace("#", str(i))) for k in range(cancellable_real): add(" PIM = PIM * AREAL_%i // BREAL_%i" % (areal[k], breal[k])) for i in noncancellable_real_num: add(" PIM = (PIM * AREAL_#) >> wp".replace("#", str(i))) for i in noncancellable_real_den: add(" PIM = (PIM << wp) // BREAL_#".replace("#", str(i))) if multiplier: if have_complex_arg: add(" PRE, PIM = (mul*(PRE*ZRE-PIM*ZIM))//div, (mul*(PIM*ZRE+PRE*ZIM))//div") add(" PRE >>= wp") add(" PIM >>= wp") else: add(" PRE = ((mul * PRE * ZRE) >> wp) // div") add(" PIM = ((mul * PIM * ZRE) >> wp) // div") else: if have_complex_arg: add(" PRE, PIM = (PRE*ZRE-PIM*ZIM)//div, (PIM*ZRE+PRE*ZIM)//div") add(" PRE >>= wp") add(" PIM >>= wp") else: add(" PRE = ((PRE * ZRE) >> wp) // div") add(" PIM = ((PIM * ZRE) >> wp) // div") for i in acomplex: add(" PRE, PIM = PRE*ACRE_#-PIM*ACIM_#, PIM*ACRE_#+PRE*ACIM_#".replace("#", str(i))) add(" PRE >>= wp") add(" PIM >>= wp") for i in bcomplex: add(" mag = BCRE_#*BCRE_#+BCIM_#*BCIM_#".replace("#", str(i))) add(" re = PRE*BCRE_# + PIM*BCIM_#".replace("#", str(i))) add(" im = PIM*BCRE_# - PRE*BCIM_#".replace("#", str(i))) add(" PRE = (re << wp) // mag".replace("#", str(i))) add(" PIM = (im << wp) // mag".replace("#", str(i))) else: for k in range(cancellable_real): add(" PRE = PRE * AREAL_%i // BREAL_%i" % (areal[k], breal[k])) for i in noncancellable_real_num: add(" PRE = (PRE * AREAL_#) >> wp".replace("#", str(i))) for i in noncancellable_real_den: add(" PRE = (PRE << wp) // BREAL_#".replace("#", str(i))) if multiplier: add(" PRE = ((PRE * mul * ZRE) >> wp) // div") else: add(" PRE = ((PRE * ZRE) >> wp) // div") # Add product to sum if have_complex: add(" SRE += PRE") add(" SIM += PIM") add(" if (HIGH > PRE > LOW) and (HIGH > PIM > LOW):") add(" break") else: add(" SRE += PRE") add(" if HIGH > PRE > LOW:") add(" break") #add(" from mpmath import nprint, log, ldexp") #add(" nprint([n, log(abs(PRE),2), ldexp(PRE,-wp)])") add(" if n > MAX:") add(" raise NoConvergence('Hypergeometric series converges too slowly. Try increasing maxterms.')") # +1 all parameters for next loop for i in aint: add(" AINT_# += 1".replace("#", str(i))) for i in bint: add(" BINT_# += 1".replace("#", str(i))) for i in arat: add(" AP_# += AQ_#".replace("#", str(i))) for i in brat: add(" BP_# += BQ_#".replace("#", str(i))) for i in areal: add(" AREAL_# += one".replace("#", str(i))) for i in breal: add(" BREAL_# += one".replace("#", str(i))) for i in acomplex: add(" ACRE_# += one".replace("#", str(i))) for i in bcomplex: add(" BCRE_# += one".replace("#", str(i))) if have_complex: add("a = from_man_exp(SRE, -wp, prec, 'n')") add("b = from_man_exp(SIM, -wp, prec, 'n')") add("if SRE:") add(" if SIM:") add(" magn = max(a[2]+a[3], b[2]+b[3])") add(" else:") add(" magn = a[2]+a[3]") add("elif SIM:") add(" magn = b[2]+b[3]") add("else:") add(" magn = -wp+1") add("return (a, b), True, magn") else: add("a = from_man_exp(SRE, -wp, prec, 'n')") add("if SRE:") add(" magn = a[2]+a[3]") add("else:") add(" magn = -wp+1") add("return a, False, magn") source = "\n".join((" " + line) for line in source) source = ("def %s(coeffs, z, prec, wp, epsshift, magnitude_check, **kwargs):\n" % fname) + source namespace = {} exec_(source, globals(), namespace) #print source return source, namespace[fname] if BACKEND == 'sage': def make_hyp_summator(key): """ Returns a function that sums a generalized hypergeometric series, for given parameter types (integer, rational, real, complex). """ from sage.libs.mpmath.ext_main import hypsum_internal p, q, param_types, ztype = key def _hypsum(coeffs, z, prec, wp, epsshift, magnitude_check, **kwargs): return hypsum_internal(p, q, param_types, ztype, coeffs, z, prec, wp, epsshift, magnitude_check, kwargs) return "(none)", _hypsum #-----------------------------------------------------------------------# # # # Error functions # # # #-----------------------------------------------------------------------# # TODO: mpf_erf should call mpf_erfc when appropriate (currently # only the converse delegation is implemented) def mpf_erf(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if x == fzero: return fzero if x == finf: return fone if x== fninf: return fnone return fnan size = exp + bc lg = math.log # The approximation erf(x) = 1 is accurate to > x^2 * log(e,2) bits if size > 3 and 2*(size-1) + 0.528766 > lg(prec,2): if sign: return mpf_perturb(fnone, 0, prec, rnd) else: return mpf_perturb(fone, 1, prec, rnd) # erf(x) ~ 2*x/sqrt(pi) close to 0 if size < -prec: # 2*x x = mpf_shift(x,1) c = mpf_sqrt(mpf_pi(prec+20), prec+20) # TODO: interval rounding return mpf_div(x, c, prec, rnd) wp = prec + abs(size) + 25 # Taylor series for erf, fixed-point summation t = abs(to_fixed(x, wp)) t2 = (t*t) >> wp s, term, k = t, 12345, 1 while term: t = ((t * t2) >> wp) // k term = t // (2*k+1) if k & 1: s -= term else: s += term k += 1 s = (s << (wp+1)) // sqrt_fixed(pi_fixed(wp), wp) if sign: s = -s return from_man_exp(s, -wp, prec, rnd) # If possible, we use the asymptotic series for erfc. # This is an alternating divergent asymptotic series, so # the error is at most equal to the first omitted term. # Here we check if the smallest term is small enough # for a given x and precision def erfc_check_series(x, prec): n = to_int(x) if n**2 * 1.44 > prec: return True return False def mpf_erfc(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if x == fzero: return fone if x == finf: return fzero if x == fninf: return ftwo return fnan wp = prec + 20 mag = bc+exp # Preserve full accuracy when exponent grows huge wp += max(0, 2*mag) regular_erf = sign or mag < 2 if regular_erf or not erfc_check_series(x, wp): if regular_erf: return mpf_sub(fone, mpf_erf(x, prec+10, negative_rnd[rnd]), prec, rnd) # 1-erf(x) ~ exp(-x^2), increase prec to deal with cancellation n = to_int(x)+1 return mpf_sub(fone, mpf_erf(x, prec + int(n**2*1.44) + 10), prec, rnd) s = term = MPZ_ONE << wp term_prev = 0 t = (2 * to_fixed(x, wp) ** 2) >> wp k = 1 while 1: term = ((term * (2*k - 1)) << wp) // t if k > 4 and term > term_prev or not term: break if k & 1: s -= term else: s += term term_prev = term #print k, to_str(from_man_exp(term, -wp, 50), 10) k += 1 s = (s << wp) // sqrt_fixed(pi_fixed(wp), wp) s = from_man_exp(s, -wp, wp) z = mpf_exp(mpf_neg(mpf_mul(x,x,wp),wp),wp) y = mpf_div(mpf_mul(z, s, wp), x, prec, rnd) return y #-----------------------------------------------------------------------# # # # Exponential integrals # # # #-----------------------------------------------------------------------# def ei_taylor(x, prec): s = t = x k = 2 while t: t = ((t*x) >> prec) // k s += t // k k += 1 return s def complex_ei_taylor(zre, zim, prec): _abs = abs sre = tre = zre sim = tim = zim k = 2 while _abs(tre) + _abs(tim) > 5: tre, tim = ((tre*zre-tim*zim)//k)>>prec, ((tre*zim+tim*zre)//k)>>prec sre += tre // k sim += tim // k k += 1 return sre, sim def ei_asymptotic(x, prec): one = MPZ_ONE << prec x = t = ((one << prec) // x) s = one + x k = 2 while t: t = (k*t*x) >> prec s += t k += 1 return s def complex_ei_asymptotic(zre, zim, prec): _abs = abs one = MPZ_ONE << prec M = (zim*zim + zre*zre) >> prec # 1 / z xre = tre = (zre << prec) // M xim = tim = ((-zim) << prec) // M sre = one + xre sim = xim k = 2 while _abs(tre) + _abs(tim) > 1000: #print tre, tim tre, tim = ((tre*xre-tim*xim)*k)>>prec, ((tre*xim+tim*xre)*k)>>prec sre += tre sim += tim k += 1 if k > prec: raise NoConvergence return sre, sim def mpf_ei(x, prec, rnd=round_fast, e1=False): if e1: x = mpf_neg(x) sign, man, exp, bc = x if e1 and not sign: if x == fzero: return finf raise ComplexResult("E1(x) for x < 0") if man: xabs = 0, man, exp, bc xmag = exp+bc wp = prec + 20 can_use_asymp = xmag > wp if not can_use_asymp: if exp >= 0: xabsint = man << exp else: xabsint = man >> (-exp) can_use_asymp = xabsint > int(wp*0.693) + 10 if can_use_asymp: if xmag > wp: v = fone else: v = from_man_exp(ei_asymptotic(to_fixed(x, wp), wp), -wp) v = mpf_mul(v, mpf_exp(x, wp), wp) v = mpf_div(v, x, prec, rnd) else: wp += 2*int(to_int(xabs)) u = to_fixed(x, wp) v = ei_taylor(u, wp) + euler_fixed(wp) t1 = from_man_exp(v,-wp) t2 = mpf_log(xabs,wp) v = mpf_add(t1, t2, prec, rnd) else: if x == fzero: v = fninf elif x == finf: v = finf elif x == fninf: v = fzero else: v = fnan if e1: v = mpf_neg(v) return v def mpc_ei(z, prec, rnd=round_fast, e1=False): if e1: z = mpc_neg(z) a, b = z asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b if b == fzero: if e1: x = mpf_neg(mpf_ei(a, prec, rnd)) if not asign: y = mpf_neg(mpf_pi(prec, rnd)) else: y = fzero return x, y else: return mpf_ei(a, prec, rnd), fzero if a != fzero: if not aman or not bman: return (fnan, fnan) wp = prec + 40 amag = aexp+abc bmag = bexp+bbc zmag = max(amag, bmag) can_use_asymp = zmag > wp if not can_use_asymp: zabsint = abs(to_int(a)) + abs(to_int(b)) can_use_asymp = zabsint > int(wp*0.693) + 20 try: if can_use_asymp: if zmag > wp: v = fone, fzero else: zre = to_fixed(a, wp) zim = to_fixed(b, wp) vre, vim = complex_ei_asymptotic(zre, zim, wp) v = from_man_exp(vre, -wp), from_man_exp(vim, -wp) v = mpc_mul(v, mpc_exp(z, wp), wp) v = mpc_div(v, z, wp) if e1: v = mpc_neg(v, prec, rnd) else: x, y = v if bsign: v = mpf_pos(x, prec, rnd), mpf_sub(y, mpf_pi(wp), prec, rnd) else: v = mpf_pos(x, prec, rnd), mpf_add(y, mpf_pi(wp), prec, rnd) return v except NoConvergence: pass #wp += 2*max(0,zmag) wp += 2*int(to_int(mpc_abs(z, 5))) zre = to_fixed(a, wp) zim = to_fixed(b, wp) vre, vim = complex_ei_taylor(zre, zim, wp) vre += euler_fixed(wp) v = from_man_exp(vre,-wp), from_man_exp(vim,-wp) if e1: u = mpc_log(mpc_neg(z),wp) else: u = mpc_log(z,wp) v = mpc_add(v, u, prec, rnd) if e1: v = mpc_neg(v) return v def mpf_e1(x, prec, rnd=round_fast): return mpf_ei(x, prec, rnd, True) def mpc_e1(x, prec, rnd=round_fast): return mpc_ei(x, prec, rnd, True) def mpf_expint(n, x, prec, rnd=round_fast, gamma=False): """ E_n(x), n an integer, x real With gamma=True, computes Gamma(n,x) (upper incomplete gamma function) Returns (real, None) if real, otherwise (real, imag) The imaginary part is an optional branch cut term """ sign, man, exp, bc = x if not man: if gamma: if x == fzero: # Actually gamma function pole if n <= 0: return finf, None return mpf_gamma_int(n, prec, rnd), None if x == finf: return fzero, None # TODO: could return finite imaginary value at -inf return fnan, fnan else: if x == fzero: if n > 1: return from_rational(1, n-1, prec, rnd), None else: return finf, None if x == finf: return fzero, None return fnan, fnan n_orig = n if gamma: n = 1-n wp = prec + 20 xmag = exp + bc # Beware of near-poles if xmag < -10: raise NotImplementedError nmag = bitcount(abs(n)) have_imag = n > 0 and sign negx = mpf_neg(x) # Skip series if direct convergence if n == 0 or 2*nmag - xmag < -wp: if gamma: v = mpf_exp(negx, wp) re = mpf_mul(v, mpf_pow_int(x, n_orig-1, wp), prec, rnd) else: v = mpf_exp(negx, wp) re = mpf_div(v, x, prec, rnd) else: # Finite number of terms, or... can_use_asymptotic_series = -3*wp < n <= 0 # ...large enough? if not can_use_asymptotic_series: xi = abs(to_int(x)) m = min(max(1, xi-n), 2*wp) siz = -n*nmag + (m+n)*bitcount(abs(m+n)) - m*xmag - (144*m//100) tol = -wp-10 can_use_asymptotic_series = siz < tol if can_use_asymptotic_series: r = ((-MPZ_ONE) << (wp+wp)) // to_fixed(x, wp) m = n t = r*m s = MPZ_ONE << wp while m and t: s += t m += 1 t = (m*r*t) >> wp v = mpf_exp(negx, wp) if gamma: # ~ exp(-x) * x^(n-1) * (1 + ...) v = mpf_mul(v, mpf_pow_int(x, n_orig-1, wp), wp) else: # ~ exp(-x)/x * (1 + ...) v = mpf_div(v, x, wp) re = mpf_mul(v, from_man_exp(s, -wp), prec, rnd) elif n == 1: re = mpf_neg(mpf_ei(negx, prec, rnd)) elif n > 0 and n < 3*wp: T1 = mpf_neg(mpf_ei(negx, wp)) if gamma: if n_orig & 1: T1 = mpf_neg(T1) else: T1 = mpf_mul(T1, mpf_pow_int(negx, n-1, wp), wp) r = t = to_fixed(x, wp) facs = [1] * (n-1) for k in range(1,n-1): facs[k] = facs[k-1] * k facs = facs[::-1] s = facs[0] << wp for k in range(1, n-1): if k & 1: s -= facs[k] * t else: s += facs[k] * t t = (t*r) >> wp T2 = from_man_exp(s, -wp, wp) T2 = mpf_mul(T2, mpf_exp(negx, wp)) if gamma: T2 = mpf_mul(T2, mpf_pow_int(x, n_orig, wp), wp) R = mpf_add(T1, T2) re = mpf_div(R, from_int(ifac(n-1)), prec, rnd) else: raise NotImplementedError if have_imag: M = from_int(-ifac(n-1)) if gamma: im = mpf_div(mpf_pi(wp), M, prec, rnd) if n_orig & 1: im = mpf_neg(im) else: im = mpf_div(mpf_mul(mpf_pi(wp), mpf_pow_int(negx, n_orig-1, wp), wp), M, prec, rnd) return re, im else: return re, None def mpf_ci_si_taylor(x, wp, which=0): """ 0 - Ci(x) - (euler+log(x)) 1 - Si(x) """ x = to_fixed(x, wp) x2 = -(x*x) >> wp if which == 0: s, t, k = 0, (MPZ_ONE<>wp s += t//k k += 2 return from_man_exp(s, -wp) def mpc_ci_si_taylor(re, im, wp, which=0): # The following code is only designed for small arguments, # and not too small arguments (for relative accuracy) if re[1]: mag = re[2]+re[3] elif im[1]: mag = im[2]+im[3] if im[1]: mag = max(mag, im[2]+im[3]) if mag > 2 or mag < -wp: raise NotImplementedError wp += (2-mag) zre = to_fixed(re, wp) zim = to_fixed(im, wp) z2re = (zim*zim-zre*zre)>>wp z2im = (-2*zre*zim)>>wp tre = zre tim = zim one = MPZ_ONE< 2: f = k*(k-1) tre, tim = ((tre*z2re-tim*z2im)//f)>>wp, ((tre*z2im+tim*z2re)//f)>>wp sre += tre//k sim += tim//k k += 2 return from_man_exp(sre, -wp), from_man_exp(sim, -wp) def mpf_ci_si(x, prec, rnd=round_fast, which=2): """ Calculation of Ci(x), Si(x) for real x. which = 0 -- returns (Ci(x), -) which = 1 -- returns (Si(x), -) which = 2 -- returns (Ci(x), Si(x)) Note: if x < 0, Ci(x) needs an additional imaginary term, pi*i. """ wp = prec + 20 sign, man, exp, bc = x ci, si = None, None if not man: if x == fzero: return (fninf, fzero) if x == fnan: return (x, x) ci = fzero if which != 0: if x == finf: si = mpf_shift(mpf_pi(prec, rnd), -1) if x == fninf: si = mpf_neg(mpf_shift(mpf_pi(prec, negative_rnd[rnd]), -1)) return (ci, si) # For small x: Ci(x) ~ euler + log(x), Si(x) ~ x mag = exp+bc if mag < -wp: if which != 0: si = mpf_perturb(x, 1-sign, prec, rnd) if which != 1: y = mpf_euler(wp) xabs = mpf_abs(x) ci = mpf_add(y, mpf_log(xabs, wp), prec, rnd) return ci, si # For huge x: Ci(x) ~ sin(x)/x, Si(x) ~ pi/2 elif mag > wp: if which != 0: if sign: si = mpf_neg(mpf_pi(prec, negative_rnd[rnd])) else: si = mpf_pi(prec, rnd) si = mpf_shift(si, -1) if which != 1: ci = mpf_div(mpf_sin(x, wp), x, prec, rnd) return ci, si else: wp += abs(mag) # Use an asymptotic series? The smallest value of n!/x^n # occurs for n ~ x, where the magnitude is ~ exp(-x). asymptotic = mag-1 > math.log(wp, 2) # Case 1: convergent series near 0 if not asymptotic: if which != 0: si = mpf_pos(mpf_ci_si_taylor(x, wp, 1), prec, rnd) if which != 1: ci = mpf_ci_si_taylor(x, wp, 0) ci = mpf_add(ci, mpf_euler(wp), wp) ci = mpf_add(ci, mpf_log(mpf_abs(x), wp), prec, rnd) return ci, si x = mpf_abs(x) # Case 2: asymptotic series for x >> 1 xf = to_fixed(x, wp) xr = (MPZ_ONE<<(2*wp)) // xf # 1/x s1 = (MPZ_ONE << wp) s2 = xr t = xr k = 2 while t: t = -t t = (t*xr*k)>>wp k += 1 s1 += t t = (t*xr*k)>>wp k += 1 s2 += t s1 = from_man_exp(s1, -wp) s2 = from_man_exp(s2, -wp) s1 = mpf_div(s1, x, wp) s2 = mpf_div(s2, x, wp) cos, sin = mpf_cos_sin(x, wp) # Ci(x) = sin(x)*s1-cos(x)*s2 # Si(x) = pi/2-cos(x)*s1-sin(x)*s2 if which != 0: si = mpf_add(mpf_mul(cos, s1), mpf_mul(sin, s2), wp) si = mpf_sub(mpf_shift(mpf_pi(wp), -1), si, wp) if sign: si = mpf_neg(si) si = mpf_pos(si, prec, rnd) if which != 1: ci = mpf_sub(mpf_mul(sin, s1), mpf_mul(cos, s2), prec, rnd) return ci, si def mpf_ci(x, prec, rnd=round_fast): if mpf_sign(x) < 0: raise ComplexResult return mpf_ci_si(x, prec, rnd, 0)[0] def mpf_si(x, prec, rnd=round_fast): return mpf_ci_si(x, prec, rnd, 1)[1] def mpc_ci(z, prec, rnd=round_fast): re, im = z if im == fzero: ci = mpf_ci_si(re, prec, rnd, 0)[0] if mpf_sign(re) < 0: return (ci, mpf_pi(prec, rnd)) return (ci, fzero) wp = prec + 20 cre, cim = mpc_ci_si_taylor(re, im, wp, 0) cre = mpf_add(cre, mpf_euler(wp), wp) ci = mpc_add((cre, cim), mpc_log(z, wp), prec, rnd) return ci def mpc_si(z, prec, rnd=round_fast): re, im = z if im == fzero: return (mpf_ci_si(re, prec, rnd, 1)[1], fzero) wp = prec + 20 z = mpc_ci_si_taylor(re, im, wp, 1) return mpc_pos(z, prec, rnd) #-----------------------------------------------------------------------# # # # Bessel functions # # # #-----------------------------------------------------------------------# # A Bessel function of the first kind of integer order, J_n(x), is # given by the power series # oo # ___ k 2 k + n # \ (-1) / x \ # J_n(x) = ) ----------- | - | # /___ k! (k + n)! \ 2 / # k = 0 # Simplifying the quotient between two successive terms gives the # ratio x^2 / (-4*k*(k+n)). Hence, we only need one full-precision # multiplication and one division by a small integer per term. # The complex version is very similar, the only difference being # that the multiplication is actually 4 multiplies. # In the general case, we have # J_v(x) = (x/2)**v / v! * 0F1(v+1, (-1/4)*z**2) # TODO: for extremely large x, we could use an asymptotic # trigonometric approximation. # TODO: recompute at higher precision if the fixed-point mantissa # is very small def mpf_besseljn(n, x, prec, rounding=round_fast): prec += 50 negate = n < 0 and n & 1 mag = x[2]+x[3] n = abs(n) wp = prec + 20 + n*bitcount(n) if mag < 0: wp -= n * mag x = to_fixed(x, wp) x2 = (x**2) >> wp if not n: s = t = MPZ_ONE << wp else: s = t = (x**n // ifac(n)) >> ((n-1)*wp + n) k = 1 while t: t = ((t * x2) // (-4*k*(k+n))) >> wp s += t k += 1 if negate: s = -s return from_man_exp(s, -wp, prec, rounding) def mpc_besseljn(n, z, prec, rounding=round_fast): negate = n < 0 and n & 1 n = abs(n) origprec = prec zre, zim = z mag = max(zre[2]+zre[3], zim[2]+zim[3]) prec += 20 + n*bitcount(n) + abs(mag) if mag < 0: prec -= n * mag zre = to_fixed(zre, prec) zim = to_fixed(zim, prec) z2re = (zre**2 - zim**2) >> prec z2im = (zre*zim) >> (prec-1) if not n: sre = tre = MPZ_ONE << prec sim = tim = MPZ_ZERO else: re, im = complex_int_pow(zre, zim, n) sre = tre = (re // ifac(n)) >> ((n-1)*prec + n) sim = tim = (im // ifac(n)) >> ((n-1)*prec + n) k = 1 while abs(tre) + abs(tim) > 3: p = -4*k*(k+n) tre, tim = tre*z2re - tim*z2im, tim*z2re + tre*z2im tre = (tre // p) >> prec tim = (tim // p) >> prec sre += tre sim += tim k += 1 if negate: sre = -sre sim = -sim re = from_man_exp(sre, -prec, origprec, rounding) im = from_man_exp(sim, -prec, origprec, rounding) return (re, im) def mpf_agm(a, b, prec, rnd=round_fast): """ Computes the arithmetic-geometric mean agm(a,b) for nonnegative mpf values a, b. """ asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b if asign or bsign: raise ComplexResult("agm of a negative number") # Handle inf, nan or zero in either operand if not (aman and bman): if a == fnan or b == fnan: return fnan if a == finf: if b == fzero: return fnan return finf if b == finf: if a == fzero: return fnan return finf # agm(0,x) = agm(x,0) = 0 return fzero wp = prec + 20 amag = aexp+abc bmag = bexp+bbc mag_delta = amag - bmag # Reduce to roughly the same magnitude using floating-point AGM abs_mag_delta = abs(mag_delta) if abs_mag_delta > 10: while abs_mag_delta > 10: a, b = mpf_shift(mpf_add(a,b,wp),-1), \ mpf_sqrt(mpf_mul(a,b,wp),wp) abs_mag_delta //= 2 asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b amag = aexp+abc bmag = bexp+bbc mag_delta = amag - bmag #print to_float(a), to_float(b) # Use agm(a,b) = agm(x*a,x*b)/x to obtain a, b ~= 1 min_mag = min(amag,bmag) max_mag = max(amag,bmag) n = 0 # If too small, we lose precision when going to fixed-point if min_mag < -8: n = -min_mag # If too large, we waste time using fixed-point with large numbers elif max_mag > 20: n = -max_mag if n: a = mpf_shift(a, n) b = mpf_shift(b, n) #print to_float(a), to_float(b) af = to_fixed(a, wp) bf = to_fixed(b, wp) g = agm_fixed(af, bf, wp) return from_man_exp(g, -wp-n, prec, rnd) def mpf_agm1(a, prec, rnd=round_fast): """ Computes the arithmetic-geometric mean agm(1,a) for a nonnegative mpf value a. """ return mpf_agm(fone, a, prec, rnd) def mpc_agm(a, b, prec, rnd=round_fast): """ Complex AGM. TODO: * check that convergence works as intended * optimize * select a nonarbitrary branch """ if mpc_is_infnan(a) or mpc_is_infnan(b): return fnan, fnan if mpc_zero in (a, b): return fzero, fzero if mpc_neg(a) == b: return fzero, fzero wp = prec+20 eps = mpf_shift(fone, -wp+10) while 1: a1 = mpc_shift(mpc_add(a, b, wp), -1) b1 = mpc_sqrt(mpc_mul(a, b, wp), wp) a, b = a1, b1 size = mpf_min_max([mpc_abs(a,10), mpc_abs(b,10)])[1] err = mpc_abs(mpc_sub(a, b, 10), 10) if size == fzero or mpf_lt(err, mpf_mul(eps, size)): return a def mpc_agm1(a, prec, rnd=round_fast): return mpc_agm(mpc_one, a, prec, rnd) def mpf_ellipk(x, prec, rnd=round_fast): if not x[1]: if x == fzero: return mpf_shift(mpf_pi(prec, rnd), -1) if x == fninf: return fzero if x == fnan: return x if x == fone: return finf # TODO: for |x| << 1/2, one could use fall back to # pi/2 * hyp2f1_rat((1,2),(1,2),(1,1), x) wp = prec + 15 # Use K(x) = pi/2/agm(1,a) where a = sqrt(1-x) # The sqrt raises ComplexResult if x > 0 a = mpf_sqrt(mpf_sub(fone, x, wp), wp) v = mpf_agm1(a, wp) r = mpf_div(mpf_pi(wp), v, prec, rnd) return mpf_shift(r, -1) def mpc_ellipk(z, prec, rnd=round_fast): re, im = z if im == fzero: if re == finf: return mpc_zero if mpf_le(re, fone): return mpf_ellipk(re, prec, rnd), fzero wp = prec + 15 a = mpc_sqrt(mpc_sub(mpc_one, z, wp), wp) v = mpc_agm1(a, wp) r = mpc_mpf_div(mpf_pi(wp), v, prec, rnd) return mpc_shift(r, -1) def mpf_ellipe(x, prec, rnd=round_fast): # http://functions.wolfram.com/EllipticIntegrals/ # EllipticK/20/01/0001/ # E = (1-m)*(K'(m)*2*m + K(m)) sign, man, exp, bc = x if not man: if x == fzero: return mpf_shift(mpf_pi(prec, rnd), -1) if x == fninf: return finf if x == fnan: return x if x == finf: raise ComplexResult if x == fone: return fone wp = prec+20 mag = exp+bc if mag < -wp: return mpf_shift(mpf_pi(prec, rnd), -1) # Compute a finite difference for K' p = max(mag, 0) - wp h = mpf_shift(fone, p) K = mpf_ellipk(x, 2*wp) Kh = mpf_ellipk(mpf_sub(x, h), 2*wp) Kdiff = mpf_shift(mpf_sub(K, Kh), -p) t = mpf_sub(fone, x) b = mpf_mul(Kdiff, mpf_shift(x,1), wp) return mpf_mul(t, mpf_add(K, b), prec, rnd) def mpc_ellipe(z, prec, rnd=round_fast): re, im = z if im == fzero: if re == finf: return (fzero, finf) if mpf_le(re, fone): return mpf_ellipe(re, prec, rnd), fzero wp = prec + 15 mag = mpc_abs(z, 1) p = max(mag[2]+mag[3], 0) - wp h = mpf_shift(fone, p) K = mpc_ellipk(z, 2*wp) Kh = mpc_ellipk(mpc_add_mpf(z, h, 2*wp), 2*wp) Kdiff = mpc_shift(mpc_sub(Kh, K, wp), -p) t = mpc_sub(mpc_one, z, wp) b = mpc_mul(Kdiff, mpc_shift(z,1), wp) return mpc_mul(t, mpc_add(K, b, wp), prec, rnd) mpmath-1.1.0/mpmath/libmp/libintmath.py000066400000000000000000000401161340375245600201100ustar00rootroot00000000000000""" Utility functions for integer math. TODO: rename, cleanup, perhaps move the gmpy wrapper code here from settings.py """ import math from bisect import bisect from .backend import xrange from .backend import BACKEND, gmpy, sage, sage_utils, MPZ, MPZ_ONE, MPZ_ZERO def giant_steps(start, target, n=2): """ Return a list of integers ~= [start, n*start, ..., target/n^2, target/n, target] but conservatively rounded so that the quotient between two successive elements is actually slightly less than n. With n = 2, this describes suitable precision steps for a quadratically convergent algorithm such as Newton's method; with n = 3 steps for cubic convergence (Halley's method), etc. >>> giant_steps(50,1000) [66, 128, 253, 502, 1000] >>> giant_steps(50,1000,4) [65, 252, 1000] """ L = [target] while L[-1] > start*n: L = L + [L[-1]//n + 2] return L[::-1] def rshift(x, n): """For an integer x, calculate x >> n with the fastest (floor) rounding. Unlike the plain Python expression (x >> n), n is allowed to be negative, in which case a left shift is performed.""" if n >= 0: return x >> n else: return x << (-n) def lshift(x, n): """For an integer x, calculate x << n. Unlike the plain Python expression (x << n), n is allowed to be negative, in which case a right shift with default (floor) rounding is performed.""" if n >= 0: return x << n else: return x >> (-n) if BACKEND == 'sage': import operator rshift = operator.rshift lshift = operator.lshift def python_trailing(n): """Count the number of trailing zero bits in abs(n).""" if not n: return 0 t = 0 while not n & 1: n >>= 1 t += 1 return t if BACKEND == 'gmpy': if gmpy.version() >= '2': def gmpy_trailing(n): """Count the number of trailing zero bits in abs(n) using gmpy.""" if n: return MPZ(n).bit_scan1() else: return 0 else: def gmpy_trailing(n): """Count the number of trailing zero bits in abs(n) using gmpy.""" if n: return MPZ(n).scan1() else: return 0 # Small powers of 2 powers = [1<<_ for _ in range(300)] def python_bitcount(n): """Calculate bit size of the nonnegative integer n.""" bc = bisect(powers, n) if bc != 300: return bc bc = int(math.log(n, 2)) - 4 return bc + bctable[n>>bc] def gmpy_bitcount(n): """Calculate bit size of the nonnegative integer n.""" if n: return MPZ(n).numdigits(2) else: return 0 #def sage_bitcount(n): # if n: return MPZ(n).nbits() # else: return 0 def sage_trailing(n): return MPZ(n).trailing_zero_bits() if BACKEND == 'gmpy': bitcount = gmpy_bitcount trailing = gmpy_trailing elif BACKEND == 'sage': sage_bitcount = sage_utils.bitcount bitcount = sage_bitcount trailing = sage_trailing else: bitcount = python_bitcount trailing = python_trailing if BACKEND == 'gmpy' and 'bit_length' in dir(gmpy): bitcount = gmpy.bit_length # Used to avoid slow function calls as far as possible trailtable = [trailing(n) for n in range(256)] bctable = [bitcount(n) for n in range(1024)] # TODO: speed up for bases 2, 4, 8, 16, ... def bin_to_radix(x, xbits, base, bdigits): """Changes radix of a fixed-point number; i.e., converts x * 2**xbits to floor(x * 10**bdigits).""" return x * (MPZ(base)**bdigits) >> xbits stddigits = '0123456789abcdefghijklmnopqrstuvwxyz' def small_numeral(n, base=10, digits=stddigits): """Return the string numeral of a positive integer in an arbitrary base. Most efficient for small input.""" if base == 10: return str(n) digs = [] while n: n, digit = divmod(n, base) digs.append(digits[digit]) return "".join(digs[::-1]) def numeral_python(n, base=10, size=0, digits=stddigits): """Represent the integer n as a string of digits in the given base. Recursive division is used to make this function about 3x faster than Python's str() for converting integers to decimal strings. The 'size' parameters specifies the number of digits in n; this number is only used to determine splitting points and need not be exact.""" if n <= 0: if not n: return "0" return "-" + numeral(-n, base, size, digits) # Fast enough to do directly if size < 250: return small_numeral(n, base, digits) # Divide in half half = (size // 2) + (size & 1) A, B = divmod(n, base**half) ad = numeral(A, base, half, digits) bd = numeral(B, base, half, digits).rjust(half, "0") return ad + bd def numeral_gmpy(n, base=10, size=0, digits=stddigits): """Represent the integer n as a string of digits in the given base. Recursive division is used to make this function about 3x faster than Python's str() for converting integers to decimal strings. The 'size' parameters specifies the number of digits in n; this number is only used to determine splitting points and need not be exact.""" if n < 0: return "-" + numeral(-n, base, size, digits) # gmpy.digits() may cause a segmentation fault when trying to convert # extremely large values to a string. The size limit may need to be # adjusted on some platforms, but 1500000 works on Windows and Linux. if size < 1500000: return gmpy.digits(n, base) # Divide in half half = (size // 2) + (size & 1) A, B = divmod(n, MPZ(base)**half) ad = numeral(A, base, half, digits) bd = numeral(B, base, half, digits).rjust(half, "0") return ad + bd if BACKEND == "gmpy": numeral = numeral_gmpy else: numeral = numeral_python _1_800 = 1<<800 _1_600 = 1<<600 _1_400 = 1<<400 _1_200 = 1<<200 _1_100 = 1<<100 _1_50 = 1<<50 def isqrt_small_python(x): """ Correctly (floor) rounded integer square root, using division. Fast up to ~200 digits. """ if not x: return x if x < _1_800: # Exact with IEEE double precision arithmetic if x < _1_50: return int(x**0.5) # Initial estimate can be any integer >= the true root; round up r = int(x**0.5 * 1.00000000000001) + 1 else: bc = bitcount(x) n = bc//2 r = int((x>>(2*n-100))**0.5+2)<<(n-50) # +2 is to round up # The following iteration now precisely computes floor(sqrt(x)) # See e.g. Crandall & Pomerance, "Prime Numbers: A Computational # Perspective" while 1: y = (r+x//r)>>1 if y >= r: return r r = y def isqrt_fast_python(x): """ Fast approximate integer square root, computed using division-free Newton iteration for large x. For random integers the result is almost always correct (floor(sqrt(x))), but is 1 ulp too small with a roughly 0.1% probability. If x is very close to an exact square, the answer is 1 ulp wrong with high probability. With 0 guard bits, the largest error over a set of 10^5 random inputs of size 1-10^5 bits was 3 ulp. The use of 10 guard bits almost certainly guarantees a max 1 ulp error. """ # Use direct division-based iteration if sqrt(x) < 2^400 # Assume floating-point square root accurate to within 1 ulp, then: # 0 Newton iterations good to 52 bits # 1 Newton iterations good to 104 bits # 2 Newton iterations good to 208 bits # 3 Newton iterations good to 416 bits if x < _1_800: y = int(x**0.5) if x >= _1_100: y = (y + x//y) >> 1 if x >= _1_200: y = (y + x//y) >> 1 if x >= _1_400: y = (y + x//y) >> 1 return y bc = bitcount(x) guard_bits = 10 x <<= 2*guard_bits bc += 2*guard_bits bc += (bc&1) hbc = bc//2 startprec = min(50, hbc) # Newton iteration for 1/sqrt(x), with floating-point starting value r = int(2.0**(2*startprec) * (x >> (bc-2*startprec)) ** -0.5) pp = startprec for p in giant_steps(startprec, hbc): # r**2, scaled from real size 2**(-bc) to 2**p r2 = (r*r) >> (2*pp - p) # x*r**2, scaled from real size ~1.0 to 2**p xr2 = ((x >> (bc-p)) * r2) >> p # New value of r, scaled from real size 2**(-bc/2) to 2**p r = (r * ((3<> (pp+1) pp = p # (1/sqrt(x))*x = sqrt(x) return (r*(x>>hbc)) >> (p+guard_bits) def sqrtrem_python(x): """Correctly rounded integer (floor) square root with remainder.""" # to check cutoff: # plot(lambda x: timing(isqrt, 2**int(x)), [0,2000]) if x < _1_600: y = isqrt_small_python(x) return y, x - y*y y = isqrt_fast_python(x) + 1 rem = x - y*y # Correct remainder while rem < 0: y -= 1 rem += (1+2*y) else: if rem: while rem > 2*(1+y): y += 1 rem -= (1+2*y) return y, rem def isqrt_python(x): """Integer square root with correct (floor) rounding.""" return sqrtrem_python(x)[0] def sqrt_fixed(x, prec): return isqrt_fast(x<= '2': isqrt_small = isqrt_fast = isqrt = gmpy.isqrt sqrtrem = gmpy.isqrt_rem else: isqrt_small = isqrt_fast = isqrt = gmpy.sqrt sqrtrem = gmpy.sqrtrem elif BACKEND == 'sage': isqrt_small = isqrt_fast = isqrt = \ getattr(sage_utils, "isqrt", lambda n: MPZ(n).isqrt()) sqrtrem = lambda n: MPZ(n).sqrtrem() else: isqrt_small = isqrt_small_python isqrt_fast = isqrt_fast_python isqrt = isqrt_python sqrtrem = sqrtrem_python def ifib(n, _cache={}): """Computes the nth Fibonacci number as an integer, for integer n.""" if n < 0: return (-1)**(-n+1) * ifib(-n) if n in _cache: return _cache[n] m = n # Use Dijkstra's logarithmic algorithm # The following implementation is basically equivalent to # http://en.literateprograms.org/Fibonacci_numbers_(Scheme) a, b, p, q = MPZ_ONE, MPZ_ZERO, MPZ_ZERO, MPZ_ONE while n: if n & 1: aq = a*q a, b = b*q+aq+a*p, b*p+aq n -= 1 else: qq = q*q p, q = p*p+qq, qq+2*p*q n >>= 1 if m < 250: _cache[m] = b return b MAX_FACTORIAL_CACHE = 1000 def ifac(n, memo={0:1, 1:1}): """Return n factorial (for integers n >= 0 only).""" f = memo.get(n) if f: return f k = len(memo) p = memo[k-1] MAX = MAX_FACTORIAL_CACHE while k <= n: p *= k if k <= MAX: memo[k] = p k += 1 return p def ifac2(n, memo_pair=[{0:1}, {1:1}]): """Return n!! (double factorial), integers n >= 0 only.""" memo = memo_pair[n&1] f = memo.get(n) if f: return f k = max(memo) p = memo[k] MAX = MAX_FACTORIAL_CACHE while k < n: k += 2 p *= k if k <= MAX: memo[k] = p return p if BACKEND == 'gmpy': ifac = gmpy.fac elif BACKEND == 'sage': ifac = lambda n: int(sage.factorial(n)) ifib = sage.fibonacci def list_primes(n): n = n + 1 sieve = list(xrange(n)) sieve[:2] = [0, 0] for i in xrange(2, int(n**0.5)+1): if sieve[i]: for j in xrange(i**2, n, i): sieve[j] = 0 return [p for p in sieve if p] if BACKEND == 'sage': # Note: it is *VERY* important for performance that we convert # the list to Python ints. def list_primes(n): return [int(_) for _ in sage.primes(n+1)] small_odd_primes = (3,5,7,11,13,17,19,23,29,31,37,41,43,47) small_odd_primes_set = set(small_odd_primes) def isprime(n): """ Determines whether n is a prime number. A probabilistic test is performed if n is very large. No special trick is used for detecting perfect powers. >>> sum(list_primes(100000)) 454396537 >>> sum(n*isprime(n) for n in range(100000)) 454396537 """ n = int(n) if not n & 1: return n == 2 if n < 50: return n in small_odd_primes_set for p in small_odd_primes: if not n % p: return False m = n-1 s = trailing(m) d = m >> s def test(a): x = pow(a,d,n) if x == 1 or x == m: return True for r in xrange(1,s): x = x**2 % n if x == m: return True return False # See http://primes.utm.edu/prove/prove2_3.html if n < 1373653: witnesses = [2,3] elif n < 341550071728321: witnesses = [2,3,5,7,11,13,17] else: witnesses = small_odd_primes for a in witnesses: if not test(a): return False return True def moebius(n): """ Evaluates the Moebius function which is `mu(n) = (-1)^k` if `n` is a product of `k` distinct primes and `mu(n) = 0` otherwise. TODO: speed up using factorization """ n = abs(int(n)) if n < 2: return n factors = [] for p in xrange(2, n+1): if not (n % p): if not (n % p**2): return 0 if not sum(p % f for f in factors): factors.append(p) return (-1)**len(factors) def gcd(*args): a = 0 for b in args: if a: while b: a, b = b, a % b else: a = b return a # Comment by Juan Arias de Reyna: # # I learn this method to compute EulerE[2n] from van de Lune. # # We apply the formula EulerE[2n] = (-1)^n 2**(-2n) sum_{j=0}^n a(2n,2j+1) # # where the numbers a(n,j) vanish for j > n+1 or j <= -1 and satisfies # # a(0,-1) = a(0,0) = 0; a(0,1)= 1; a(0,2) = a(0,3) = 0 # # a(n,j) = a(n-1,j) when n+j is even # a(n,j) = (j-1) a(n-1,j-1) + (j+1) a(n-1,j+1) when n+j is odd # # # But we can use only one array unidimensional a(j) since to compute # a(n,j) we only need to know a(n-1,k) where k and j are of different parity # and we have not to conserve the used values. # # We cached up the values of Euler numbers to sufficiently high order. # # Important Observation: If we pretend to use the numbers # EulerE[1], EulerE[2], ... , EulerE[n] # it is convenient to compute first EulerE[n], since the algorithm # computes first all # the previous ones, and keeps them in the CACHE MAX_EULER_CACHE = 500 def eulernum(m, _cache={0:MPZ_ONE}): r""" Computes the Euler numbers `E(n)`, which can be defined as coefficients of the Taylor expansion of `1/cosh x`: .. math :: \frac{1}{\cosh x} = \sum_{n=0}^\infty \frac{E_n}{n!} x^n Example:: >>> [int(eulernum(n)) for n in range(11)] [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521] >>> [int(eulernum(n)) for n in range(11)] # test cache [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521] """ # for odd m > 1, the Euler numbers are zero if m & 1: return MPZ_ZERO f = _cache.get(m) if f: return f MAX = MAX_EULER_CACHE n = m a = [MPZ(_) for _ in [0,0,1,0,0,0]] for n in range(1, m+1): for j in range(n+1, -1, -2): a[j+1] = (j-1)*a[j] + (j+1)*a[j+2] a.append(0) suma = 0 for k in range(n+1, -1, -2): suma += a[k+1] if n <= MAX: _cache[n] = ((-1)**(n//2))*(suma // 2**n) if n == m: return ((-1)**(n//2))*suma // 2**n def stirling1(n, k): """ Stirling number of the first kind. """ if n < 0 or k < 0: raise ValueError if k >= n: return MPZ(n == k) if k < 1: return MPZ_ZERO L = [MPZ_ZERO] * (k+1) L[1] = MPZ_ONE for m in xrange(2, n+1): for j in xrange(min(k, m), 0, -1): L[j] = (m-1) * L[j] + L[j-1] return (-1)**(n+k) * L[k] def stirling2(n, k): """ Stirling number of the second kind. """ if n < 0 or k < 0: raise ValueError if k >= n: return MPZ(n == k) if k <= 1: return MPZ(k == 1) s = MPZ_ZERO t = MPZ_ONE for j in xrange(k+1): if (k + j) & 1: s -= t * MPZ(j)**n else: s += t * MPZ(j)**n t = t * (k - j) // (j + 1) return s // ifac(k) mpmath-1.1.0/mpmath/libmp/libmpc.py000066400000000000000000000643651340375245600172370ustar00rootroot00000000000000""" Low-level functions for complex arithmetic. """ import sys from .backend import MPZ, MPZ_ZERO, MPZ_ONE, MPZ_TWO, BACKEND from .libmpf import (\ round_floor, round_ceiling, round_down, round_up, round_nearest, round_fast, bitcount, bctable, normalize, normalize1, reciprocal_rnd, rshift, lshift, giant_steps, negative_rnd, to_str, to_fixed, from_man_exp, from_float, to_float, from_int, to_int, fzero, fone, ftwo, fhalf, finf, fninf, fnan, fnone, mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_div, mpf_mul_int, mpf_shift, mpf_sqrt, mpf_hypot, mpf_rdiv_int, mpf_floor, mpf_ceil, mpf_nint, mpf_frac, mpf_sign, mpf_hash, ComplexResult ) from .libelefun import (\ mpf_pi, mpf_exp, mpf_log, mpf_cos_sin, mpf_cosh_sinh, mpf_tan, mpf_pow_int, mpf_log_hypot, mpf_cos_sin_pi, mpf_phi, mpf_cos, mpf_sin, mpf_cos_pi, mpf_sin_pi, mpf_atan, mpf_atan2, mpf_cosh, mpf_sinh, mpf_tanh, mpf_asin, mpf_acos, mpf_acosh, mpf_nthroot, mpf_fibonacci ) # An mpc value is a (real, imag) tuple mpc_one = fone, fzero mpc_zero = fzero, fzero mpc_two = ftwo, fzero mpc_half = (fhalf, fzero) _infs = (finf, fninf) _infs_nan = (finf, fninf, fnan) def mpc_is_inf(z): """Check if either real or imaginary part is infinite""" re, im = z if re in _infs: return True if im in _infs: return True return False def mpc_is_infnan(z): """Check if either real or imaginary part is infinite or nan""" re, im = z if re in _infs_nan: return True if im in _infs_nan: return True return False def mpc_to_str(z, dps, **kwargs): re, im = z rs = to_str(re, dps) if im[0]: return rs + " - " + to_str(mpf_neg(im), dps, **kwargs) + "j" else: return rs + " + " + to_str(im, dps, **kwargs) + "j" def mpc_to_complex(z, strict=False, rnd=round_fast): re, im = z return complex(to_float(re, strict, rnd), to_float(im, strict, rnd)) def mpc_hash(z): if sys.version >= "3.2": re, im = z h = mpf_hash(re) + sys.hash_info.imag * mpf_hash(im) # Need to reduce either module 2^32 or 2^64 h = h % (2**sys.hash_info.width) return int(h) else: try: return hash(mpc_to_complex(z, strict=True)) except OverflowError: return hash(z) def mpc_conjugate(z, prec, rnd=round_fast): re, im = z return re, mpf_neg(im, prec, rnd) def mpc_is_nonzero(z): return z != mpc_zero def mpc_add(z, w, prec, rnd=round_fast): a, b = z c, d = w return mpf_add(a, c, prec, rnd), mpf_add(b, d, prec, rnd) def mpc_add_mpf(z, x, prec, rnd=round_fast): a, b = z return mpf_add(a, x, prec, rnd), b def mpc_sub(z, w, prec=0, rnd=round_fast): a, b = z c, d = w return mpf_sub(a, c, prec, rnd), mpf_sub(b, d, prec, rnd) def mpc_sub_mpf(z, p, prec=0, rnd=round_fast): a, b = z return mpf_sub(a, p, prec, rnd), b def mpc_pos(z, prec, rnd=round_fast): a, b = z return mpf_pos(a, prec, rnd), mpf_pos(b, prec, rnd) def mpc_neg(z, prec=None, rnd=round_fast): a, b = z return mpf_neg(a, prec, rnd), mpf_neg(b, prec, rnd) def mpc_shift(z, n): a, b = z return mpf_shift(a, n), mpf_shift(b, n) def mpc_abs(z, prec, rnd=round_fast): """Absolute value of a complex number, |a+bi|. Returns an mpf value.""" a, b = z return mpf_hypot(a, b, prec, rnd) def mpc_arg(z, prec, rnd=round_fast): """Argument of a complex number. Returns an mpf value.""" a, b = z return mpf_atan2(b, a, prec, rnd) def mpc_floor(z, prec, rnd=round_fast): a, b = z return mpf_floor(a, prec, rnd), mpf_floor(b, prec, rnd) def mpc_ceil(z, prec, rnd=round_fast): a, b = z return mpf_ceil(a, prec, rnd), mpf_ceil(b, prec, rnd) def mpc_nint(z, prec, rnd=round_fast): a, b = z return mpf_nint(a, prec, rnd), mpf_nint(b, prec, rnd) def mpc_frac(z, prec, rnd=round_fast): a, b = z return mpf_frac(a, prec, rnd), mpf_frac(b, prec, rnd) def mpc_mul(z, w, prec, rnd=round_fast): """ Complex multiplication. Returns the real and imaginary part of (a+bi)*(c+di), rounded to the specified precision. The rounding mode applies to the real and imaginary parts separately. """ a, b = z c, d = w p = mpf_mul(a, c) q = mpf_mul(b, d) r = mpf_mul(a, d) s = mpf_mul(b, c) re = mpf_sub(p, q, prec, rnd) im = mpf_add(r, s, prec, rnd) return re, im def mpc_square(z, prec, rnd=round_fast): # (a+b*I)**2 == a**2 - b**2 + 2*I*a*b a, b = z p = mpf_mul(a,a) q = mpf_mul(b,b) r = mpf_mul(a,b, prec, rnd) re = mpf_sub(p, q, prec, rnd) im = mpf_shift(r, 1) return re, im def mpc_mul_mpf(z, p, prec, rnd=round_fast): a, b = z re = mpf_mul(a, p, prec, rnd) im = mpf_mul(b, p, prec, rnd) return re, im def mpc_mul_imag_mpf(z, x, prec, rnd=round_fast): """ Multiply the mpc value z by I*x where x is an mpf value. """ a, b = z re = mpf_neg(mpf_mul(b, x, prec, rnd)) im = mpf_mul(a, x, prec, rnd) return re, im def mpc_mul_int(z, n, prec, rnd=round_fast): a, b = z re = mpf_mul_int(a, n, prec, rnd) im = mpf_mul_int(b, n, prec, rnd) return re, im def mpc_div(z, w, prec, rnd=round_fast): a, b = z c, d = w wp = prec + 10 # mag = c*c + d*d mag = mpf_add(mpf_mul(c, c), mpf_mul(d, d), wp) # (a*c+b*d)/mag, (b*c-a*d)/mag t = mpf_add(mpf_mul(a,c), mpf_mul(b,d), wp) u = mpf_sub(mpf_mul(b,c), mpf_mul(a,d), wp) return mpf_div(t,mag,prec,rnd), mpf_div(u,mag,prec,rnd) def mpc_div_mpf(z, p, prec, rnd=round_fast): """Calculate z/p where p is real""" a, b = z re = mpf_div(a, p, prec, rnd) im = mpf_div(b, p, prec, rnd) return re, im def mpc_reciprocal(z, prec, rnd=round_fast): """Calculate 1/z efficiently""" a, b = z m = mpf_add(mpf_mul(a,a),mpf_mul(b,b),prec+10) re = mpf_div(a, m, prec, rnd) im = mpf_neg(mpf_div(b, m, prec, rnd)) return re, im def mpc_mpf_div(p, z, prec, rnd=round_fast): """Calculate p/z where p is real efficiently""" a, b = z m = mpf_add(mpf_mul(a,a),mpf_mul(b,b), prec+10) re = mpf_div(mpf_mul(a,p), m, prec, rnd) im = mpf_div(mpf_neg(mpf_mul(b,p)), m, prec, rnd) return re, im def complex_int_pow(a, b, n): """Complex integer power: computes (a+b*I)**n exactly for nonnegative n (a and b must be Python ints).""" wre = 1 wim = 0 while n: if n & 1: wre, wim = wre*a - wim*b, wim*a + wre*b n -= 1 a, b = a*a - b*b, 2*a*b n //= 2 return wre, wim def mpc_pow(z, w, prec, rnd=round_fast): if w[1] == fzero: return mpc_pow_mpf(z, w[0], prec, rnd) return mpc_exp(mpc_mul(mpc_log(z, prec+10), w, prec+10), prec, rnd) def mpc_pow_mpf(z, p, prec, rnd=round_fast): psign, pman, pexp, pbc = p if pexp >= 0: return mpc_pow_int(z, (-1)**psign * (pman< 0: aman <<= de aexp = bexp else: bman <<= (-de) bexp = aexp re, im = complex_int_pow(aman, bman, n) re = from_man_exp(re, int(n*aexp), prec, rnd) im = from_man_exp(im, int(n*bexp), prec, rnd) return re, im return mpc_exp(mpc_mul_int(mpc_log(z, prec+10), n, prec+10), prec, rnd) def mpc_sqrt(z, prec, rnd=round_fast): """Complex square root (principal branch). We have sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i where r = abs(a+bi), when a+bi is not a negative real number.""" a, b = z if b == fzero: if a == fzero: return (a, b) # When a+bi is a negative real number, we get a real sqrt times i if a[0]: im = mpf_sqrt(mpf_neg(a), prec, rnd) return (fzero, im) else: re = mpf_sqrt(a, prec, rnd) return (re, fzero) wp = prec+20 if not a[0]: # case a positive t = mpf_add(mpc_abs((a, b), wp), a, wp) # t = abs(a+bi) + a u = mpf_shift(t, -1) # u = t/2 re = mpf_sqrt(u, prec, rnd) # re = sqrt(u) v = mpf_shift(t, 1) # v = 2*t w = mpf_sqrt(v, wp) # w = sqrt(v) im = mpf_div(b, w, prec, rnd) # im = b / w else: # case a negative t = mpf_sub(mpc_abs((a, b), wp), a, wp) # t = abs(a+bi) - a u = mpf_shift(t, -1) # u = t/2 im = mpf_sqrt(u, prec, rnd) # im = sqrt(u) v = mpf_shift(t, 1) # v = 2*t w = mpf_sqrt(v, wp) # w = sqrt(v) re = mpf_div(b, w, prec, rnd) # re = b/w if b[0]: re = mpf_neg(re) im = mpf_neg(im) return re, im def mpc_nthroot_fixed(a, b, n, prec): # a, b signed integers at fixed precision prec start = 50 a1 = int(rshift(a, prec - n*start)) b1 = int(rshift(b, prec - n*start)) try: r = (a1 + 1j * b1)**(1.0/n) re = r.real im = r.imag re = MPZ(int(re)) im = MPZ(int(im)) except OverflowError: a1 = from_int(a1, start) b1 = from_int(b1, start) fn = from_int(n) nth = mpf_rdiv_int(1, fn, start) re, im = mpc_pow((a1, b1), (nth, fzero), start) re = to_int(re) im = to_int(im) extra = 10 prevp = start extra1 = n for p in giant_steps(start, prec+extra): # this is slow for large n, unlike int_pow_fixed re2, im2 = complex_int_pow(re, im, n-1) re2 = rshift(re2, (n-1)*prevp - p - extra1) im2 = rshift(im2, (n-1)*prevp - p - extra1) r4 = (re2*re2 + im2*im2) >> (p + extra1) ap = rshift(a, prec - p) bp = rshift(b, prec - p) rec = (ap * re2 + bp * im2) >> p imc = (-ap * im2 + bp * re2) >> p reb = (rec << p) // r4 imb = (imc << p) // r4 re = (reb + (n-1)*lshift(re, p-prevp))//n im = (imb + (n-1)*lshift(im, p-prevp))//n prevp = p return re, im def mpc_nthroot(z, n, prec, rnd=round_fast): """ Complex n-th root. Use Newton method as in the real case when it is faster, otherwise use z**(1/n) """ a, b = z if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec+5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n <= 20: prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b pf = mpc_abs((a,b), prec) if pf[-2] + pf[-1] > -10 and pf[-2] + pf[-1] < prec: af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2-extra, prec2, rnd) im = from_man_exp(im, -prec2-extra, prec2, rnd) return re, im fn = from_int(n) prec2 = prec+10 + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im def mpc_cbrt(z, prec, rnd=round_fast): """ Complex cubic root. """ return mpc_nthroot(z, 3, prec, rnd) def mpc_exp(z, prec, rnd=round_fast): """ Complex exponential function. We use the direct formula exp(a+bi) = exp(a) * (cos(b) + sin(b)*i) for the computation. This formula is very nice because it is pefectly stable; since we just do real multiplications, the only numerical errors that can creep in are single-ulp rounding errors. The formula is efficient since mpmath's real exp is quite fast and since we can compute cos and sin simultaneously. It is no problem if a and b are large; if the implementations of exp/cos/sin are accurate and efficient for all real numbers, then so is this function for all complex numbers. """ a, b = z if a == fzero: return mpf_cos_sin(b, prec, rnd) if b == fzero: return mpf_exp(a, prec, rnd), fzero mag = mpf_exp(a, prec+4, rnd) c, s = mpf_cos_sin(b, prec+4, rnd) re = mpf_mul(mag, c, prec, rnd) im = mpf_mul(mag, s, prec, rnd) return re, im def mpc_log(z, prec, rnd=round_fast): re = mpf_log_hypot(z[0], z[1], prec, rnd) im = mpc_arg(z, prec, rnd) return re, im def mpc_cos(z, prec, rnd=round_fast): """Complex cosine. The formula used is cos(a+bi) = cos(a)*cosh(b) - sin(a)*sinh(b)*i. The same comments apply as for the complex exp: only real multiplications are pewrormed, so no cancellation errors are possible. The formula is also efficient since we can compute both pairs (cos, sin) and (cosh, sinh) in single stwps.""" a, b = z if b == fzero: return mpf_cos(a, prec, rnd), fzero if a == fzero: return mpf_cosh(b, prec, rnd), fzero wp = prec + 6 c, s = mpf_cos_sin(a, wp) ch, sh = mpf_cosh_sinh(b, wp) re = mpf_mul(c, ch, prec, rnd) im = mpf_mul(s, sh, prec, rnd) return re, mpf_neg(im) def mpc_sin(z, prec, rnd=round_fast): """Complex sine. We have sin(a+bi) = sin(a)*cosh(b) + cos(a)*sinh(b)*i. See the docstring for mpc_cos for additional comments.""" a, b = z if b == fzero: return mpf_sin(a, prec, rnd), fzero if a == fzero: return fzero, mpf_sinh(b, prec, rnd) wp = prec + 6 c, s = mpf_cos_sin(a, wp) ch, sh = mpf_cosh_sinh(b, wp) re = mpf_mul(s, ch, prec, rnd) im = mpf_mul(c, sh, prec, rnd) return re, im def mpc_tan(z, prec, rnd=round_fast): """Complex tangent. Computed as tan(a+bi) = sin(2a)/M + sinh(2b)/M*i where M = cos(2a) + cosh(2b).""" a, b = z asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b if b == fzero: return mpf_tan(a, prec, rnd), fzero if a == fzero: return fzero, mpf_tanh(b, prec, rnd) wp = prec + 15 a = mpf_shift(a, 1) b = mpf_shift(b, 1) c, s = mpf_cos_sin(a, wp) ch, sh = mpf_cosh_sinh(b, wp) # TODO: handle cancellation when c ~= -1 and ch ~= 1 mag = mpf_add(c, ch, wp) re = mpf_div(s, mag, prec, rnd) im = mpf_div(sh, mag, prec, rnd) return re, im def mpc_cos_pi(z, prec, rnd=round_fast): a, b = z if b == fzero: return mpf_cos_pi(a, prec, rnd), fzero b = mpf_mul(b, mpf_pi(prec+5), prec+5) if a == fzero: return mpf_cosh(b, prec, rnd), fzero wp = prec + 6 c, s = mpf_cos_sin_pi(a, wp) ch, sh = mpf_cosh_sinh(b, wp) re = mpf_mul(c, ch, prec, rnd) im = mpf_mul(s, sh, prec, rnd) return re, mpf_neg(im) def mpc_sin_pi(z, prec, rnd=round_fast): a, b = z if b == fzero: return mpf_sin_pi(a, prec, rnd), fzero b = mpf_mul(b, mpf_pi(prec+5), prec+5) if a == fzero: return fzero, mpf_sinh(b, prec, rnd) wp = prec + 6 c, s = mpf_cos_sin_pi(a, wp) ch, sh = mpf_cosh_sinh(b, wp) re = mpf_mul(s, ch, prec, rnd) im = mpf_mul(c, sh, prec, rnd) return re, im def mpc_cos_sin(z, prec, rnd=round_fast): a, b = z if a == fzero: ch, sh = mpf_cosh_sinh(b, prec, rnd) return (ch, fzero), (fzero, sh) if b == fzero: c, s = mpf_cos_sin(a, prec, rnd) return (c, fzero), (s, fzero) wp = prec + 6 c, s = mpf_cos_sin(a, wp) ch, sh = mpf_cosh_sinh(b, wp) cre = mpf_mul(c, ch, prec, rnd) cim = mpf_mul(s, sh, prec, rnd) sre = mpf_mul(s, ch, prec, rnd) sim = mpf_mul(c, sh, prec, rnd) return (cre, mpf_neg(cim)), (sre, sim) def mpc_cos_sin_pi(z, prec, rnd=round_fast): a, b = z if b == fzero: c, s = mpf_cos_sin_pi(a, prec, rnd) return (c, fzero), (s, fzero) b = mpf_mul(b, mpf_pi(prec+5), prec+5) if a == fzero: ch, sh = mpf_cosh_sinh(b, prec, rnd) return (ch, fzero), (fzero, sh) wp = prec + 6 c, s = mpf_cos_sin_pi(a, wp) ch, sh = mpf_cosh_sinh(b, wp) cre = mpf_mul(c, ch, prec, rnd) cim = mpf_mul(s, sh, prec, rnd) sre = mpf_mul(s, ch, prec, rnd) sim = mpf_mul(c, sh, prec, rnd) return (cre, mpf_neg(cim)), (sre, sim) def mpc_cosh(z, prec, rnd=round_fast): """Complex hyperbolic cosine. Computed as cosh(z) = cos(z*i).""" a, b = z return mpc_cos((b, mpf_neg(a)), prec, rnd) def mpc_sinh(z, prec, rnd=round_fast): """Complex hyperbolic sine. Computed as sinh(z) = -i*sin(z*i).""" a, b = z b, a = mpc_sin((b, a), prec, rnd) return a, b def mpc_tanh(z, prec, rnd=round_fast): """Complex hyperbolic tangent. Computed as tanh(z) = -i*tan(z*i).""" a, b = z b, a = mpc_tan((b, a), prec, rnd) return a, b # TODO: avoid loss of accuracy def mpc_atan(z, prec, rnd=round_fast): a, b = z # atan(z) = (I/2)*(log(1-I*z) - log(1+I*z)) # x = 1-I*z = 1 + b - I*a # y = 1+I*z = 1 - b + I*a wp = prec + 15 x = mpf_add(fone, b, wp), mpf_neg(a) y = mpf_sub(fone, b, wp), a l1 = mpc_log(x, wp) l2 = mpc_log(y, wp) a, b = mpc_sub(l1, l2, prec, rnd) # (I/2) * (a+b*I) = (-b/2 + a/2*I) v = mpf_neg(mpf_shift(b,-1)), mpf_shift(a,-1) # Subtraction at infinity gives correct real part but # wrong imaginary part (should be zero) if v[1] == fnan and mpc_is_inf(z): v = (v[0], fzero) return v beta_crossover = from_float(0.6417) alpha_crossover = from_float(1.5) def acos_asin(z, prec, rnd, n): """ complex acos for n = 0, asin for n = 1 The algorithm is described in T.E. Hull, T.F. Fairgrieve and P.T.P. Tang 'Implementing the Complex Arcsine and Arcosine Functions using Exception Handling', ACM Trans. on Math. Software Vol. 23 (1997), p299 The complex acos and asin can be defined as acos(z) = acos(beta) - I*sign(a)* log(alpha + sqrt(alpha**2 -1)) asin(z) = asin(beta) + I*sign(a)* log(alpha + sqrt(alpha**2 -1)) where z = a + I*b alpha = (1/2)*(r + s); beta = (1/2)*(r - s) = a/alpha r = sqrt((a+1)**2 + y**2); s = sqrt((a-1)**2 + y**2) These expressions are rewritten in different ways in different regions, delimited by two crossovers alpha_crossover and beta_crossover, and by abs(a) <= 1, in order to improve the numerical accuracy. """ a, b = z wp = prec + 10 # special cases with real argument if b == fzero: am = mpf_sub(fone, mpf_abs(a), wp) # case abs(a) <= 1 if not am[0]: if n == 0: return mpf_acos(a, prec, rnd), fzero else: return mpf_asin(a, prec, rnd), fzero # cases abs(a) > 1 else: # case a < -1 if a[0]: pi = mpf_pi(prec, rnd) c = mpf_acosh(mpf_neg(a), prec, rnd) if n == 0: return pi, mpf_neg(c) else: return mpf_neg(mpf_shift(pi, -1)), c # case a > 1 else: c = mpf_acosh(a, prec, rnd) if n == 0: return fzero, c else: pi = mpf_pi(prec, rnd) return mpf_shift(pi, -1), mpf_neg(c) asign = bsign = 0 if a[0]: a = mpf_neg(a) asign = 1 if b[0]: b = mpf_neg(b) bsign = 1 am = mpf_sub(fone, a, wp) ap = mpf_add(fone, a, wp) r = mpf_hypot(ap, b, wp) s = mpf_hypot(am, b, wp) alpha = mpf_shift(mpf_add(r, s, wp), -1) beta = mpf_div(a, alpha, wp) b2 = mpf_mul(b,b, wp) # case beta <= beta_crossover if not mpf_sub(beta_crossover, beta, wp)[0]: if n == 0: re = mpf_acos(beta, wp) else: re = mpf_asin(beta, wp) else: # to compute the real part in this region use the identity # asin(beta) = atan(beta/sqrt(1-beta**2)) # beta/sqrt(1-beta**2) = (alpha + a) * (alpha - a) # alpha + a is numerically accurate; alpha - a can have # cancellations leading to numerical inaccuracies, so rewrite # it in differente ways according to the region Ax = mpf_add(alpha, a, wp) # case a <= 1 if not am[0]: # c = b*b/(r + (a+1)); d = (s + (1-a)) # alpha - a = (1/2)*(c + d) # case n=0: re = atan(sqrt((1/2) * Ax * (c + d))/a) # case n=1: re = atan(a/sqrt((1/2) * Ax * (c + d))) c = mpf_div(b2, mpf_add(r, ap, wp), wp) d = mpf_add(s, am, wp) re = mpf_shift(mpf_mul(Ax, mpf_add(c, d, wp), wp), -1) if n == 0: re = mpf_atan(mpf_div(mpf_sqrt(re, wp), a, wp), wp) else: re = mpf_atan(mpf_div(a, mpf_sqrt(re, wp), wp), wp) else: # c = Ax/(r + (a+1)); d = Ax/(s - (1-a)) # alpha - a = (1/2)*(c + d) # case n = 0: re = atan(b*sqrt(c + d)/2/a) # case n = 1: re = atan(a/(b*sqrt(c + d)/2) c = mpf_div(Ax, mpf_add(r, ap, wp), wp) d = mpf_div(Ax, mpf_sub(s, am, wp), wp) re = mpf_shift(mpf_add(c, d, wp), -1) re = mpf_mul(b, mpf_sqrt(re, wp), wp) if n == 0: re = mpf_atan(mpf_div(re, a, wp), wp) else: re = mpf_atan(mpf_div(a, re, wp), wp) # to compute alpha + sqrt(alpha**2 - 1), if alpha <= alpha_crossover # replace it with 1 + Am1 + sqrt(Am1*(alpha+1))) # where Am1 = alpha -1 # if alpha <= alpha_crossover: if not mpf_sub(alpha_crossover, alpha, wp)[0]: c1 = mpf_div(b2, mpf_add(r, ap, wp), wp) # case a < 1 if mpf_neg(am)[0]: # Am1 = (1/2) * (b*b/(r + (a+1)) + b*b/(s + (1-a)) c2 = mpf_add(s, am, wp) c2 = mpf_div(b2, c2, wp) Am1 = mpf_shift(mpf_add(c1, c2, wp), -1) else: # Am1 = (1/2) * (b*b/(r + (a+1)) + (s - (1-a))) c2 = mpf_sub(s, am, wp) Am1 = mpf_shift(mpf_add(c1, c2, wp), -1) # im = log(1 + Am1 + sqrt(Am1*(alpha+1))) im = mpf_mul(Am1, mpf_add(alpha, fone, wp), wp) im = mpf_log(mpf_add(fone, mpf_add(Am1, mpf_sqrt(im, wp), wp), wp), wp) else: # im = log(alpha + sqrt(alpha*alpha - 1)) im = mpf_sqrt(mpf_sub(mpf_mul(alpha, alpha, wp), fone, wp), wp) im = mpf_log(mpf_add(alpha, im, wp), wp) if asign: if n == 0: re = mpf_sub(mpf_pi(wp), re, wp) else: re = mpf_neg(re) if not bsign and n == 0: im = mpf_neg(im) if bsign and n == 1: im = mpf_neg(im) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im def mpc_acos(z, prec, rnd=round_fast): return acos_asin(z, prec, rnd, 0) def mpc_asin(z, prec, rnd=round_fast): return acos_asin(z, prec, rnd, 1) def mpc_asinh(z, prec, rnd=round_fast): # asinh(z) = I * asin(-I z) a, b = z a, b = mpc_asin((b, mpf_neg(a)), prec, rnd) return mpf_neg(b), a def mpc_acosh(z, prec, rnd=round_fast): # acosh(z) = -I * acos(z) for Im(acos(z)) <= 0 # +I * acos(z) otherwise a, b = mpc_acos(z, prec, rnd) if b[0] or b == fzero: return mpf_neg(b), a else: return b, mpf_neg(a) def mpc_atanh(z, prec, rnd=round_fast): # atanh(z) = (log(1+z)-log(1-z))/2 wp = prec + 15 a = mpc_add(z, mpc_one, wp) b = mpc_sub(mpc_one, z, wp) a = mpc_log(a, wp) b = mpc_log(b, wp) v = mpc_shift(mpc_sub(a, b, wp), -1) # Subtraction at infinity gives correct imaginary part but # wrong real part (should be zero) if v[0] == fnan and mpc_is_inf(z): v = (fzero, v[1]) return v def mpc_fibonacci(z, prec, rnd=round_fast): re, im = z if im == fzero: return (mpf_fibonacci(re, prec, rnd), fzero) size = max(abs(re[2]+re[3]), abs(re[2]+re[3])) wp = prec + size + 20 a = mpf_phi(wp) b = mpf_add(mpf_shift(a, 1), fnone, wp) u = mpc_pow((a, fzero), z, wp) v = mpc_cos_pi(z, wp) v = mpc_div(v, u, wp) u = mpc_sub(u, v, wp) u = mpc_div_mpf(u, b, prec, rnd) return u def mpf_expj(x, prec, rnd='f'): raise ComplexResult def mpc_expj(z, prec, rnd='f'): re, im = z if im == fzero: return mpf_cos_sin(re, prec, rnd) if re == fzero: return mpf_exp(mpf_neg(im), prec, rnd), fzero ey = mpf_exp(mpf_neg(im), prec+10) c, s = mpf_cos_sin(re, prec+10) re = mpf_mul(ey, c, prec, rnd) im = mpf_mul(ey, s, prec, rnd) return re, im def mpf_expjpi(x, prec, rnd='f'): raise ComplexResult def mpc_expjpi(z, prec, rnd='f'): re, im = z if im == fzero: return mpf_cos_sin_pi(re, prec, rnd) sign, man, exp, bc = im wp = prec+10 if man: wp += max(0, exp+bc) im = mpf_neg(mpf_mul(mpf_pi(wp), im, wp)) if re == fzero: return mpf_exp(im, prec, rnd), fzero ey = mpf_exp(im, prec+10) c, s = mpf_cos_sin_pi(re, prec+10) re = mpf_mul(ey, c, prec, rnd) im = mpf_mul(ey, s, prec, rnd) return re, im if BACKEND == 'sage': try: import sage.libs.mpmath.ext_libmp as _lbmp mpc_exp = _lbmp.mpc_exp mpc_sqrt = _lbmp.mpc_sqrt except (ImportError, AttributeError): print("Warning: Sage imports in libmpc failed") mpmath-1.1.0/mpmath/libmp/libmpf.py000066400000000000000000001277301340375245600172360ustar00rootroot00000000000000""" Low-level functions for arbitrary-precision floating-point arithmetic. """ __docformat__ = 'plaintext' import math from bisect import bisect import sys # Importing random is slow #from random import getrandbits getrandbits = None from .backend import (MPZ, MPZ_TYPE, MPZ_ZERO, MPZ_ONE, MPZ_TWO, MPZ_FIVE, BACKEND, STRICT, HASH_MODULUS, HASH_BITS, gmpy, sage, sage_utils) from .libintmath import (giant_steps, trailtable, bctable, lshift, rshift, bitcount, trailing, sqrt_fixed, numeral, isqrt, isqrt_fast, sqrtrem, bin_to_radix) # We don't pickle tuples directly for the following reasons: # 1: pickle uses str() for ints, which is inefficient when they are large # 2: pickle doesn't work for gmpy mpzs # Both problems are solved by using hex() if BACKEND == 'sage': def to_pickable(x): sign, man, exp, bc = x return sign, hex(man), exp, bc else: def to_pickable(x): sign, man, exp, bc = x return sign, hex(man)[2:], exp, bc def from_pickable(x): sign, man, exp, bc = x return (sign, MPZ(man, 16), exp, bc) class ComplexResult(ValueError): pass try: intern except NameError: intern = lambda x: x # All supported rounding modes round_nearest = intern('n') round_floor = intern('f') round_ceiling = intern('c') round_up = intern('u') round_down = intern('d') round_fast = round_down def prec_to_dps(n): """Return number of accurate decimals that can be represented with a precision of n bits.""" return max(1, int(round(int(n)/3.3219280948873626)-1)) def dps_to_prec(n): """Return the number of bits required to represent n decimals accurately.""" return max(1, int(round((int(n)+1)*3.3219280948873626))) def repr_dps(n): """Return the number of decimal digits required to represent a number with n-bit precision so that it can be uniquely reconstructed from the representation.""" dps = prec_to_dps(n) if dps == 15: return 17 return dps + 3 #----------------------------------------------------------------------------# # Some commonly needed float values # #----------------------------------------------------------------------------# # Regular number format: # (-1)**sign * mantissa * 2**exponent, plus bitcount of mantissa fzero = (0, MPZ_ZERO, 0, 0) fnzero = (1, MPZ_ZERO, 0, 0) fone = (0, MPZ_ONE, 0, 1) fnone = (1, MPZ_ONE, 0, 1) ftwo = (0, MPZ_ONE, 1, 1) ften = (0, MPZ_FIVE, 1, 3) fhalf = (0, MPZ_ONE, -1, 1) # Arbitrary encoding for special numbers: zero mantissa, nonzero exponent fnan = (0, MPZ_ZERO, -123, -1) finf = (0, MPZ_ZERO, -456, -2) fninf = (1, MPZ_ZERO, -789, -3) # Was 1e1000; this is broken in Python 2.4 math_float_inf = 1e300 * 1e300 #----------------------------------------------------------------------------# # Rounding # #----------------------------------------------------------------------------# # This function can be used to round a mantissa generally. However, # we will try to do most rounding inline for efficiency. def round_int(x, n, rnd): if rnd == round_nearest: if x >= 0: t = x >> (n-1) if t & 1 and ((t & 2) or (x & h_mask[n<300][n])): return (t>>1)+1 else: return t>>1 else: return -round_int(-x, n, rnd) if rnd == round_floor: return x >> n if rnd == round_ceiling: return -((-x) >> n) if rnd == round_down: if x >= 0: return x >> n return -((-x) >> n) if rnd == round_up: if x >= 0: return -((-x) >> n) return x >> n # These masks are used to pick out segments of numbers to determine # which direction to round when rounding to nearest. class h_mask_big: def __getitem__(self, n): return (MPZ_ONE<<(n-1))-1 h_mask_small = [0]+[((MPZ_ONE<<(_-1))-1) for _ in range(1, 300)] h_mask = [h_mask_big(), h_mask_small] # The >> operator rounds to floor. shifts_down[rnd][sign] # tells whether this is the right direction to use, or if the # number should be negated before shifting shifts_down = {round_floor:(1,0), round_ceiling:(0,1), round_down:(1,1), round_up:(0,0)} #----------------------------------------------------------------------------# # Normalization of raw mpfs # #----------------------------------------------------------------------------# # This function is called almost every time an mpf is created. # It has been optimized accordingly. def _normalize(sign, man, exp, bc, prec, rnd): """ Create a raw mpf tuple with value (-1)**sign * man * 2**exp and normalized mantissa. The mantissa is rounded in the specified direction if its size exceeds the precision. Trailing zero bits are also stripped from the mantissa to ensure that the representation is canonical. Conditions on the input: * The input must represent a regular (finite) number * The sign bit must be 0 or 1 * The mantissa must be positive * The exponent must be an integer * The bitcount must be exact If these conditions are not met, use from_man_exp, mpf_pos, or any of the conversion functions to create normalized raw mpf tuples. """ if not man: return fzero # Cut mantissa down to size if larger than target precision n = bc - prec if n > 0: if rnd == round_nearest: t = man >> (n-1) if t & 1 and ((t & 2) or (man & h_mask[n<300][n])): man = (t>>1)+1 else: man = t>>1 elif shifts_down[rnd][sign]: man >>= n else: man = -((-man)>>n) exp += n bc = prec # Strip trailing bits if not man & 1: t = trailtable[int(man & 255)] if not t: while not man & 255: man >>= 8 exp += 8 bc -= 8 t = trailtable[int(man & 255)] man >>= t exp += t bc -= t # Bit count can be wrong if the input mantissa was 1 less than # a power of 2 and got rounded up, thereby adding an extra bit. # With trailing bits removed, all powers of two have mantissa 1, # so this is easy to check for. if man == 1: bc = 1 return sign, man, exp, bc def _normalize1(sign, man, exp, bc, prec, rnd): """same as normalize, but with the added condition that man is odd or zero """ if not man: return fzero if bc <= prec: return sign, man, exp, bc n = bc - prec if rnd == round_nearest: t = man >> (n-1) if t & 1 and ((t & 2) or (man & h_mask[n<300][n])): man = (t>>1)+1 else: man = t>>1 elif shifts_down[rnd][sign]: man >>= n else: man = -((-man)>>n) exp += n bc = prec # Strip trailing bits if not man & 1: t = trailtable[int(man & 255)] if not t: while not man & 255: man >>= 8 exp += 8 bc -= 8 t = trailtable[int(man & 255)] man >>= t exp += t bc -= t # Bit count can be wrong if the input mantissa was 1 less than # a power of 2 and got rounded up, thereby adding an extra bit. # With trailing bits removed, all powers of two have mantissa 1, # so this is easy to check for. if man == 1: bc = 1 return sign, man, exp, bc try: _exp_types = (int, long) except NameError: _exp_types = (int,) def strict_normalize(sign, man, exp, bc, prec, rnd): """Additional checks on the components of an mpf. Enable tests by setting the environment variable MPMATH_STRICT to Y.""" assert type(man) == MPZ_TYPE assert type(bc) in _exp_types assert type(exp) in _exp_types assert bc == bitcount(man) return _normalize(sign, man, exp, bc, prec, rnd) def strict_normalize1(sign, man, exp, bc, prec, rnd): """Additional checks on the components of an mpf. Enable tests by setting the environment variable MPMATH_STRICT to Y.""" assert type(man) == MPZ_TYPE assert type(bc) in _exp_types assert type(exp) in _exp_types assert bc == bitcount(man) assert (not man) or (man & 1) return _normalize1(sign, man, exp, bc, prec, rnd) if BACKEND == 'gmpy' and '_mpmath_normalize' in dir(gmpy): _normalize = gmpy._mpmath_normalize _normalize1 = gmpy._mpmath_normalize if BACKEND == 'sage': _normalize = _normalize1 = sage_utils.normalize if STRICT: normalize = strict_normalize normalize1 = strict_normalize1 else: normalize = _normalize normalize1 = _normalize1 #----------------------------------------------------------------------------# # Conversion functions # #----------------------------------------------------------------------------# def from_man_exp(man, exp, prec=None, rnd=round_fast): """Create raw mpf from (man, exp) pair. The mantissa may be signed. If no precision is specified, the mantissa is stored exactly.""" man = MPZ(man) sign = 0 if man < 0: sign = 1 man = -man if man < 1024: bc = bctable[int(man)] else: bc = bitcount(man) if not prec: if not man: return fzero if not man & 1: if man & 2: return (sign, man >> 1, exp + 1, bc - 1) t = trailtable[int(man & 255)] if not t: while not man & 255: man >>= 8 exp += 8 bc -= 8 t = trailtable[int(man & 255)] man >>= t exp += t bc -= t return (sign, man, exp, bc) return normalize(sign, man, exp, bc, prec, rnd) int_cache = dict((n, from_man_exp(n, 0)) for n in range(-10, 257)) if BACKEND == 'gmpy' and '_mpmath_create' in dir(gmpy): from_man_exp = gmpy._mpmath_create if BACKEND == 'sage': from_man_exp = sage_utils.from_man_exp def from_int(n, prec=0, rnd=round_fast): """Create a raw mpf from an integer. If no precision is specified, the mantissa is stored exactly.""" if not prec: if n in int_cache: return int_cache[n] return from_man_exp(n, 0, prec, rnd) def to_man_exp(s): """Return (man, exp) of a raw mpf. Raise an error if inf/nan.""" sign, man, exp, bc = s if (not man) and exp: raise ValueError("mantissa and exponent are undefined for %s" % man) return man, exp def to_int(s, rnd=None): """Convert a raw mpf to the nearest int. Rounding is done down by default (same as int(float) in Python), but can be changed. If the input is inf/nan, an exception is raised.""" sign, man, exp, bc = s if (not man) and exp: raise ValueError("cannot convert inf or nan to int") if exp >= 0: if sign: return (-man) << exp return man << exp # Make default rounding fast if not rnd: if sign: return -(man >> (-exp)) else: return man >> (-exp) if sign: return round_int(-man, -exp, rnd) else: return round_int(man, -exp, rnd) def mpf_round_int(s, rnd): sign, man, exp, bc = s if (not man) and exp: return s if exp >= 0: return s mag = exp+bc if mag < 1: if rnd == round_ceiling: if sign: return fzero else: return fone elif rnd == round_floor: if sign: return fnone else: return fzero elif rnd == round_nearest: if mag < 0 or man == MPZ_ONE: return fzero elif sign: return fnone else: return fone else: raise NotImplementedError return mpf_pos(s, min(bc, mag), rnd) def mpf_floor(s, prec=0, rnd=round_fast): v = mpf_round_int(s, round_floor) if prec: v = mpf_pos(v, prec, rnd) return v def mpf_ceil(s, prec=0, rnd=round_fast): v = mpf_round_int(s, round_ceiling) if prec: v = mpf_pos(v, prec, rnd) return v def mpf_nint(s, prec=0, rnd=round_fast): v = mpf_round_int(s, round_nearest) if prec: v = mpf_pos(v, prec, rnd) return v def mpf_frac(s, prec=0, rnd=round_fast): return mpf_sub(s, mpf_floor(s), prec, rnd) def from_float(x, prec=53, rnd=round_fast): """Create a raw mpf from a Python float, rounding if necessary. If prec >= 53, the result is guaranteed to represent exactly the same number as the input. If prec is not specified, use prec=53.""" # frexp only raises an exception for nan on some platforms if x != x: return fnan # in Python2.5 math.frexp gives an exception for float infinity # in Python2.6 it returns (float infinity, 0) try: m, e = math.frexp(x) except: if x == math_float_inf: return finf if x == -math_float_inf: return fninf return fnan if x == math_float_inf: return finf if x == -math_float_inf: return fninf return from_man_exp(int(m*(1<<53)), e-53, prec, rnd) def from_npfloat(x, prec=113, rnd=round_fast): """Create a raw mpf from a numpy float, rounding if necessary. If prec >= 113, the result is guaranteed to represent exactly the same number as the input. If prec is not specified, use prec=113.""" y = float(x) if x == y: # ldexp overflows for float16 return from_float(y, prec, rnd) import numpy as np if np.isfinite(x): m, e = np.frexp(x) return from_man_exp(int(np.ldexp(m, 113)), int(e-113), prec, rnd) if np.isposinf(x): return finf if np.isneginf(x): return fninf return fnan def from_Decimal(x, prec=None, rnd=round_fast): """Create a raw mpf from a Decimal, rounding if necessary. If prec is not specified, use the equivalent bit precision of the number of significant digits in x.""" if x.is_nan(): return fnan if x.is_infinite(): return fninf if x.is_signed() else finf if prec is None: prec = int(len(x.as_tuple()[1])*3.3219280948873626) return from_str(str(x), prec, rnd) def to_float(s, strict=False, rnd=round_fast): """ Convert a raw mpf to a Python float. The result is exact if the bitcount of s is <= 53 and no underflow/overflow occurs. If the number is too large or too small to represent as a regular float, it will be converted to inf or 0.0. Setting strict=True forces an OverflowError to be raised instead. Warning: with a directed rounding mode, the correct nearest representable floating-point number in the specified direction might not be computed in case of overflow or (gradual) underflow. """ sign, man, exp, bc = s if not man: if s == fzero: return 0.0 if s == finf: return math_float_inf if s == fninf: return -math_float_inf return math_float_inf/math_float_inf if bc > 53: sign, man, exp, bc = normalize1(sign, man, exp, bc, 53, rnd) if sign: man = -man try: return math.ldexp(man, exp) except OverflowError: if strict: raise # Overflow to infinity if exp + bc > 0: if sign: return -math_float_inf else: return math_float_inf # Underflow to zero return 0.0 def from_rational(p, q, prec, rnd=round_fast): """Create a raw mpf from a rational number p/q, round if necessary.""" return mpf_div(from_int(p), from_int(q), prec, rnd) def to_rational(s): """Convert a raw mpf to a rational number. Return integers (p, q) such that s = p/q exactly.""" sign, man, exp, bc = s if sign: man = -man if bc == -1: raise ValueError("cannot convert %s to a rational number" % man) if exp >= 0: return man * (1<= 0: return (-man) << offset else: return (-man) >> (-offset) else: if offset >= 0: return man << offset else: return man >> (-offset) ############################################################################## ############################################################################## #----------------------------------------------------------------------------# # Arithmetic operations, etc. # #----------------------------------------------------------------------------# def mpf_rand(prec): """Return a raw mpf chosen randomly from [0, 1), with prec bits in the mantissa.""" global getrandbits if not getrandbits: import random getrandbits = random.getrandbits return from_man_exp(getrandbits(prec), -prec, prec, round_floor) def mpf_eq(s, t): """Test equality of two raw mpfs. This is simply tuple comparison unless either number is nan, in which case the result is False.""" if not s[1] or not t[1]: if s == fnan or t == fnan: return False return s == t def mpf_hash(s): # Duplicate the new hash algorithm introduces in Python 3.2. if sys.version >= "3.2": ssign, sman, sexp, sbc = s # Handle special numbers if not sman: if s == fnan: return sys.hash_info.nan if s == finf: return sys.hash_info.inf if s == fninf: return -sys.hash_info.inf h = sman % HASH_MODULUS if sexp >= 0: sexp = sexp % HASH_BITS else: sexp = HASH_BITS - 1 - ((-1 - sexp) % HASH_BITS) h = (h << sexp) % HASH_MODULUS if ssign: h = -h if h == -1: h == -2 return int(h) else: try: # Try to be compatible with hash values for floats and ints return hash(to_float(s, strict=1)) except OverflowError: # We must unfortunately sacrifice compatibility with ints here. # We could do hash(man << exp) when the exponent is positive, but # this would cause unreasonable inefficiency for large numbers. return hash(s) def mpf_cmp(s, t): """Compare the raw mpfs s and t. Return -1 if s < t, 0 if s == t, and 1 if s > t. (Same convention as Python's cmp() function.)""" # In principle, a comparison amounts to determining the sign of s-t. # A full subtraction is relatively slow, however, so we first try to # look at the components. ssign, sman, sexp, sbc = s tsign, tman, texp, tbc = t # Handle zeros and special numbers if not sman or not tman: if s == fzero: return -mpf_sign(t) if t == fzero: return mpf_sign(s) if s == t: return 0 # Follow same convention as Python's cmp for float nan if t == fnan: return 1 if s == finf: return 1 if t == fninf: return 1 return -1 # Different sides of zero if ssign != tsign: if not ssign: return 1 return -1 # This reduces to direct integer comparison if sexp == texp: if sman == tman: return 0 if sman > tman: if ssign: return -1 else: return 1 else: if ssign: return 1 else: return -1 # Check position of the highest set bit in each number. If # different, there is certainly an inequality. a = sbc + sexp b = tbc + texp if ssign: if a < b: return 1 if a > b: return -1 else: if a < b: return -1 if a > b: return 1 # Both numbers have the same highest bit. Subtract to find # how the lower bits compare. delta = mpf_sub(s, t, 5, round_floor) if delta[0]: return -1 return 1 def mpf_lt(s, t): if s == fnan or t == fnan: return False return mpf_cmp(s, t) < 0 def mpf_le(s, t): if s == fnan or t == fnan: return False return mpf_cmp(s, t) <= 0 def mpf_gt(s, t): if s == fnan or t == fnan: return False return mpf_cmp(s, t) > 0 def mpf_ge(s, t): if s == fnan or t == fnan: return False return mpf_cmp(s, t) >= 0 def mpf_min_max(seq): min = max = seq[0] for x in seq[1:]: if mpf_lt(x, min): min = x if mpf_gt(x, max): max = x return min, max def mpf_pos(s, prec=0, rnd=round_fast): """Calculate 0+s for a raw mpf (i.e., just round s to the specified precision).""" if prec: sign, man, exp, bc = s if (not man) and exp: return s return normalize1(sign, man, exp, bc, prec, rnd) return s def mpf_neg(s, prec=None, rnd=round_fast): """Negate a raw mpf (return -s), rounding the result to the specified precision. The prec argument can be omitted to do the operation exactly.""" sign, man, exp, bc = s if not man: if exp: if s == finf: return fninf if s == fninf: return finf return s if not prec: return (1-sign, man, exp, bc) return normalize1(1-sign, man, exp, bc, prec, rnd) def mpf_abs(s, prec=None, rnd=round_fast): """Return abs(s) of the raw mpf s, rounded to the specified precision. The prec argument can be omitted to generate an exact result.""" sign, man, exp, bc = s if (not man) and exp: if s == fninf: return finf return s if not prec: if sign: return (0, man, exp, bc) return s return normalize1(0, man, exp, bc, prec, rnd) def mpf_sign(s): """Return -1, 0, or 1 (as a Python int, not a raw mpf) depending on whether s is negative, zero, or positive. (Nan is taken to give 0.)""" sign, man, exp, bc = s if not man: if s == finf: return 1 if s == fninf: return -1 return 0 return (-1) ** sign def mpf_add(s, t, prec=0, rnd=round_fast, _sub=0): """ Add the two raw mpf values s and t. With prec=0, no rounding is performed. Note that this can produce a very large mantissa (potentially too large to fit in memory) if exponents are far apart. """ ssign, sman, sexp, sbc = s tsign, tman, texp, tbc = t tsign ^= _sub # Standard case: two nonzero, regular numbers if sman and tman: offset = sexp - texp if offset: if offset > 0: # Outside precision range; only need to perturb if offset > 100 and prec: delta = sbc + sexp - tbc - texp if delta > prec + 4: offset = prec + 4 sman <<= offset if tsign == ssign: sman += 1 else: sman -= 1 return normalize1(ssign, sman, sexp-offset, bitcount(sman), prec, rnd) # Add if ssign == tsign: man = tman + (sman << offset) # Subtract else: if ssign: man = tman - (sman << offset) else: man = (sman << offset) - tman if man >= 0: ssign = 0 else: man = -man ssign = 1 bc = bitcount(man) return normalize1(ssign, man, texp, bc, prec or bc, rnd) elif offset < 0: # Outside precision range; only need to perturb if offset < -100 and prec: delta = tbc + texp - sbc - sexp if delta > prec + 4: offset = prec + 4 tman <<= offset if ssign == tsign: tman += 1 else: tman -= 1 return normalize1(tsign, tman, texp-offset, bitcount(tman), prec, rnd) # Add if ssign == tsign: man = sman + (tman << -offset) # Subtract else: if tsign: man = sman - (tman << -offset) else: man = (tman << -offset) - sman if man >= 0: ssign = 0 else: man = -man ssign = 1 bc = bitcount(man) return normalize1(ssign, man, sexp, bc, prec or bc, rnd) # Equal exponents; no shifting necessary if ssign == tsign: man = tman + sman else: if ssign: man = tman - sman else: man = sman - tman if man >= 0: ssign = 0 else: man = -man ssign = 1 bc = bitcount(man) return normalize(ssign, man, texp, bc, prec or bc, rnd) # Handle zeros and special numbers if _sub: t = mpf_neg(t) if not sman: if sexp: if s == t or tman or not texp: return s return fnan if tman: return normalize1(tsign, tman, texp, tbc, prec or tbc, rnd) return t if texp: return t if sman: return normalize1(ssign, sman, sexp, sbc, prec or sbc, rnd) return s def mpf_sub(s, t, prec=0, rnd=round_fast): """Return the difference of two raw mpfs, s-t. This function is simply a wrapper of mpf_add that changes the sign of t.""" return mpf_add(s, t, prec, rnd, 1) def mpf_sum(xs, prec=0, rnd=round_fast, absolute=False): """ Sum a list of mpf values efficiently and accurately (typically no temporary roundoff occurs). If prec=0, the final result will not be rounded either. There may be roundoff error or cancellation if extremely large exponent differences occur. With absolute=True, sums the absolute values. """ man = 0 exp = 0 max_extra_prec = prec*2 or 1000000 # XXX special = None for x in xs: xsign, xman, xexp, xbc = x if xman: if xsign and not absolute: xman = -xman delta = xexp - exp if xexp >= exp: # x much larger than existing sum? # first: quick test if (delta > max_extra_prec) and \ ((not man) or delta-bitcount(abs(man)) > max_extra_prec): man = xman exp = xexp else: man += (xman << delta) else: delta = -delta # x much smaller than existing sum? if delta-xbc > max_extra_prec: if not man: man, exp = xman, xexp else: man = (man << delta) + xman exp = xexp elif xexp: if absolute: x = mpf_abs(x) special = mpf_add(special or fzero, x, 1) # Will be inf or nan if special: return special return from_man_exp(man, exp, prec, rnd) def gmpy_mpf_mul(s, t, prec=0, rnd=round_fast): """Multiply two raw mpfs""" ssign, sman, sexp, sbc = s tsign, tman, texp, tbc = t sign = ssign ^ tsign man = sman*tman if man: bc = bitcount(man) if prec: return normalize1(sign, man, sexp+texp, bc, prec, rnd) else: return (sign, man, sexp+texp, bc) s_special = (not sman) and sexp t_special = (not tman) and texp if not s_special and not t_special: return fzero if fnan in (s, t): return fnan if (not tman) and texp: s, t = t, s if t == fzero: return fnan return {1:finf, -1:fninf}[mpf_sign(s) * mpf_sign(t)] def gmpy_mpf_mul_int(s, n, prec, rnd=round_fast): """Multiply by a Python integer.""" sign, man, exp, bc = s if not man: return mpf_mul(s, from_int(n), prec, rnd) if not n: return fzero if n < 0: sign ^= 1 n = -n man *= n return normalize(sign, man, exp, bitcount(man), prec, rnd) def python_mpf_mul(s, t, prec=0, rnd=round_fast): """Multiply two raw mpfs""" ssign, sman, sexp, sbc = s tsign, tman, texp, tbc = t sign = ssign ^ tsign man = sman*tman if man: bc = sbc + tbc - 1 bc += int(man>>bc) if prec: return normalize1(sign, man, sexp+texp, bc, prec, rnd) else: return (sign, man, sexp+texp, bc) s_special = (not sman) and sexp t_special = (not tman) and texp if not s_special and not t_special: return fzero if fnan in (s, t): return fnan if (not tman) and texp: s, t = t, s if t == fzero: return fnan return {1:finf, -1:fninf}[mpf_sign(s) * mpf_sign(t)] def python_mpf_mul_int(s, n, prec, rnd=round_fast): """Multiply by a Python integer.""" sign, man, exp, bc = s if not man: return mpf_mul(s, from_int(n), prec, rnd) if not n: return fzero if n < 0: sign ^= 1 n = -n man *= n # Generally n will be small if n < 1024: bc += bctable[int(n)] - 1 else: bc += bitcount(n) - 1 bc += int(man>>bc) return normalize(sign, man, exp, bc, prec, rnd) if BACKEND == 'gmpy': mpf_mul = gmpy_mpf_mul mpf_mul_int = gmpy_mpf_mul_int else: mpf_mul = python_mpf_mul mpf_mul_int = python_mpf_mul_int def mpf_shift(s, n): """Quickly multiply the raw mpf s by 2**n without rounding.""" sign, man, exp, bc = s if not man: return s return sign, man, exp+n, bc def mpf_frexp(x): """Convert x = y*2**n to (y, n) with abs(y) in [0.5, 1) if nonzero""" sign, man, exp, bc = x if not man: if x == fzero: return (fzero, 0) else: raise ValueError return mpf_shift(x, -bc-exp), bc+exp def mpf_div(s, t, prec, rnd=round_fast): """Floating-point division""" ssign, sman, sexp, sbc = s tsign, tman, texp, tbc = t if not sman or not tman: if s == fzero: if t == fzero: raise ZeroDivisionError if t == fnan: return fnan return fzero if t == fzero: raise ZeroDivisionError s_special = (not sman) and sexp t_special = (not tman) and texp if s_special and t_special: return fnan if s == fnan or t == fnan: return fnan if not t_special: if t == fzero: return fnan return {1:finf, -1:fninf}[mpf_sign(s) * mpf_sign(t)] return fzero sign = ssign ^ tsign if tman == 1: return normalize1(sign, sman, sexp-texp, sbc, prec, rnd) # Same strategy as for addition: if there is a remainder, perturb # the result a few bits outside the precision range before rounding extra = prec - sbc + tbc + 5 if extra < 5: extra = 5 quot, rem = divmod(sman< sexp+sbc: return s # Another important special case: this allows us to do e.g. x % 1.0 # to find the fractional part of x, and it will work when x is huge. if tman == 1 and sexp > texp+tbc: return fzero base = min(sexp, texp) sman = (-1)**ssign * sman tman = (-1)**tsign * tman man = (sman << (sexp-base)) % (tman << (texp-base)) if man >= 0: sign = 0 else: man = -man sign = 1 return normalize(sign, man, base, bitcount(man), prec, rnd) reciprocal_rnd = { round_down : round_up, round_up : round_down, round_floor : round_ceiling, round_ceiling : round_floor, round_nearest : round_nearest } negative_rnd = { round_down : round_down, round_up : round_up, round_floor : round_ceiling, round_ceiling : round_floor, round_nearest : round_nearest } def mpf_pow_int(s, n, prec, rnd=round_fast): """Compute s**n, where s is a raw mpf and n is a Python integer.""" sign, man, exp, bc = s if (not man) and exp: if s == finf: if n > 0: return s if n == 0: return fnan return fzero if s == fninf: if n > 0: return [finf, fninf][n & 1] if n == 0: return fnan return fzero return fnan n = int(n) if n == 0: return fone if n == 1: return mpf_pos(s, prec, rnd) if n == 2: _, man, exp, bc = s if not man: return fzero man = man*man if man == 1: return (0, MPZ_ONE, exp+exp, 1) bc = bc + bc - 2 bc += bctable[int(man>>bc)] return normalize1(0, man, exp+exp, bc, prec, rnd) if n == -1: return mpf_div(fone, s, prec, rnd) if n < 0: inverse = mpf_pow_int(s, -n, prec+5, reciprocal_rnd[rnd]) return mpf_div(fone, inverse, prec, rnd) result_sign = sign & n # Use exact integer power when the exact mantissa is small if man == 1: return (result_sign, MPZ_ONE, exp*n, 1) if bc*n < 1000: man **= n return normalize1(result_sign, man, exp*n, bitcount(man), prec, rnd) # Use directed rounding all the way through to maintain rigorous # bounds for interval arithmetic rounds_down = (rnd == round_nearest) or \ shifts_down[rnd][result_sign] # Now we perform binary exponentiation. Need to estimate precision # to avoid rounding errors from temporary operations. Roughly log_2(n) # operations are performed. workprec = prec + 4*bitcount(n) + 4 _, pm, pe, pbc = fone while 1: if n & 1: pm = pm*man pe = pe+exp pbc += bc - 2 pbc = pbc + bctable[int(pm >> pbc)] if pbc > workprec: if rounds_down: pm = pm >> (pbc-workprec) else: pm = -((-pm) >> (pbc-workprec)) pe += pbc - workprec pbc = workprec n -= 1 if not n: break man = man*man exp = exp+exp bc = bc + bc - 2 bc = bc + bctable[int(man >> bc)] if bc > workprec: if rounds_down: man = man >> (bc-workprec) else: man = -((-man) >> (bc-workprec)) exp += bc - workprec bc = workprec n = n // 2 return normalize(result_sign, pm, pe, pbc, prec, rnd) def mpf_perturb(x, eps_sign, prec, rnd): """ For nonzero x, calculate x + eps with directed rounding, where eps < prec relatively and eps has the given sign (0 for positive, 1 for negative). With rounding to nearest, this is taken to simply normalize x to the given precision. """ if rnd == round_nearest: return mpf_pos(x, prec, rnd) sign, man, exp, bc = x eps = (eps_sign, MPZ_ONE, exp+bc-prec-1, 1) if sign: away = (rnd in (round_down, round_ceiling)) ^ eps_sign else: away = (rnd in (round_up, round_ceiling)) ^ eps_sign if away: return mpf_add(x, eps, prec, rnd) else: return mpf_pos(x, prec, rnd) #----------------------------------------------------------------------------# # Radix conversion # #----------------------------------------------------------------------------# def to_digits_exp(s, dps): """Helper function for representing the floating-point number s as a decimal with dps digits. Returns (sign, string, exponent) where sign is '' or '-', string is the digit string, and exponent is the decimal exponent as an int. If inexact, the decimal representation is rounded toward zero.""" # Extract sign first so it doesn't mess up the string digit count if s[0]: sign = '-' s = mpf_neg(s) else: sign = '' _sign, man, exp, bc = s if not man: return '', '0', 0 bitprec = int(dps * math.log(10,2)) + 10 # Cut down to size # TODO: account for precision when doing this exp_from_1 = exp + bc if abs(exp_from_1) > 3500: from .libelefun import mpf_ln2, mpf_ln10 # Set b = int(exp * log(2)/log(10)) # If exp is huge, we must use high-precision arithmetic to # find the nearest power of ten expprec = bitcount(abs(exp)) + 5 tmp = from_int(exp) tmp = mpf_mul(tmp, mpf_ln2(expprec)) tmp = mpf_div(tmp, mpf_ln10(expprec), expprec) b = to_int(tmp) s = mpf_div(s, mpf_pow_int(ften, b, bitprec), bitprec) _sign, man, exp, bc = s exponent = b else: exponent = 0 # First, calculate mantissa digits by converting to a binary # fixed-point number and then converting that number to # a decimal fixed-point number. fixprec = max(bitprec - exp - bc, 0) fixdps = int(fixprec / math.log(10,2) + 0.5) sf = to_fixed(s, fixprec) sd = bin_to_radix(sf, fixprec, 10, fixdps) digits = numeral(sd, base=10, size=dps) exponent += len(digits) - fixdps - 1 return sign, digits, exponent def to_str(s, dps, strip_zeros=True, min_fixed=None, max_fixed=None, show_zero_exponent=False): """ Convert a raw mpf to a decimal floating-point literal with at most `dps` decimal digits in the mantissa (not counting extra zeros that may be inserted for visual purposes). The number will be printed in fixed-point format if the position of the leading digit is strictly between min_fixed (default = min(-dps/3,-5)) and max_fixed (default = dps). To force fixed-point format always, set min_fixed = -inf, max_fixed = +inf. To force floating-point format, set min_fixed >= max_fixed. The literal is formatted so that it can be parsed back to a number by to_str, float() or Decimal(). """ # Special numbers if not s[1]: if s == fzero: if dps: t = '0.0' else: t = '.0' if show_zero_exponent: t += 'e+0' return t if s == finf: return '+inf' if s == fninf: return '-inf' if s == fnan: return 'nan' raise ValueError if min_fixed is None: min_fixed = min(-(dps//3), -5) if max_fixed is None: max_fixed = dps # to_digits_exp rounds to floor. # This sometimes kills some instances of "...00001" sign, digits, exponent = to_digits_exp(s, dps+3) # No digits: show only .0; round exponent to nearest if not dps: if digits[0] in '56789': exponent += 1 digits = ".0" else: # Rounding up kills some instances of "...99999" if len(digits) > dps and digits[dps] in '56789': digits = digits[:dps] i = dps - 1 while i >= 0 and digits[i] == '9': i -= 1 if i >= 0: digits = digits[:i] + str(int(digits[i]) + 1) + '0' * (dps - i - 1) else: digits = '1' + '0' * (dps - 1) exponent += 1 else: digits = digits[:dps] # Prettify numbers close to unit magnitude if min_fixed < exponent < max_fixed: if exponent < 0: digits = ("0"*int(-exponent)) + digits split = 1 else: split = exponent + 1 if split > dps: digits += "0"*(split-dps) exponent = 0 else: split = 1 digits = (digits[:split] + "." + digits[split:]) if strip_zeros: # Clean up trailing zeros digits = digits.rstrip('0') if digits[-1] == ".": digits += "0" if exponent == 0 and dps and not show_zero_exponent: return sign + digits if exponent >= 0: return sign + digits + "e+" + str(exponent) if exponent < 0: return sign + digits + "e" + str(exponent) def str_to_man_exp(x, base=10): """Helper function for from_str.""" x = x.lower().rstrip('l') # Verify that the input is a valid float literal float(x) # Split into mantissa, exponent parts = x.split('e') if len(parts) == 1: exp = 0 else: # == 2 x = parts[0] exp = int(parts[1]) # Look for radix point in mantissa parts = x.split('.') if len(parts) == 2: a, b = parts[0], parts[1].rstrip('0') exp -= len(b) x = a + b x = MPZ(int(x, base)) return x, exp special_str = {'inf':finf, '+inf':finf, '-inf':fninf, 'nan':fnan} def from_str(x, prec, rnd=round_fast): """Create a raw mpf from a decimal literal, rounding in the specified direction if the input number cannot be represented exactly as a binary floating-point number with the given number of bits. The literal syntax accepted is the same as for Python floats. TODO: the rounding does not work properly for large exponents. """ x = x.lower().strip() if x in special_str: return special_str[x] if '/' in x: p, q = x.split('/') p, q = p.rstrip('l'), q.rstrip('l') return from_rational(int(p), int(q), prec, rnd) man, exp = str_to_man_exp(x, base=10) # XXX: appropriate cutoffs & track direction # note no factors of 5 if abs(exp) > 400: s = from_int(man, prec+10) s = mpf_mul(s, mpf_pow_int(ften, exp, prec+10), prec, rnd) else: if exp >= 0: s = from_int(man * 10**exp, prec, rnd) else: s = from_rational(man, 10**-exp, prec, rnd) return s # Binary string conversion. These are currently mainly used for debugging # and could use some improvement in the future def from_bstr(x): man, exp = str_to_man_exp(x, base=2) man = MPZ(man) sign = 0 if man < 0: man = -man sign = 1 bc = bitcount(man) return normalize(sign, man, exp, bc, bc, round_floor) def to_bstr(x): sign, man, exp, bc = x return ['','-'][sign] + numeral(man, size=bitcount(man), base=2) + ("e%i" % exp) #----------------------------------------------------------------------------# # Square roots # #----------------------------------------------------------------------------# def mpf_sqrt(s, prec, rnd=round_fast): """ Compute the square root of a nonnegative mpf value. The result is correctly rounded. """ sign, man, exp, bc = s if sign: raise ComplexResult("square root of a negative number") if not man: return s if exp & 1: exp -= 1 man <<= 1 bc += 1 elif man == 1: return normalize1(sign, man, exp//2, bc, prec, rnd) shift = max(4, 2*prec-bc+4) shift += shift & 1 if rnd in 'fd': man = isqrt(man<= 0: a = mpf_pos(sa, prec, round_floor) b = mpf_pos(sb, prec, round_ceiling) # Upper point nonnegative? elif sbs >= 0: a = fzero negsa = mpf_neg(sa) if mpf_lt(negsa, sb): b = mpf_pos(sb, prec, round_ceiling) else: b = mpf_pos(negsa, prec, round_ceiling) # Both negative? else: a = mpf_neg(sb, prec, round_floor) b = mpf_neg(sa, prec, round_ceiling) return a, b # TODO: optimize def mpi_mul_mpf(s, t, prec): return mpi_mul(s, (t, t), prec) def mpi_div_mpf(s, t, prec): return mpi_div(s, (t, t), prec) def mpi_mul(s, t, prec=0): sa, sb = s ta, tb = t sas = mpf_sign(sa) sbs = mpf_sign(sb) tas = mpf_sign(ta) tbs = mpf_sign(tb) if sas == sbs == 0: # Should maybe be undefined if ta == fninf or tb == finf: return fninf, finf return fzero, fzero if tas == tbs == 0: # Should maybe be undefined if sa == fninf or sb == finf: return fninf, finf return fzero, fzero if sas >= 0: # positive * positive if tas >= 0: a = mpf_mul(sa, ta, prec, round_floor) b = mpf_mul(sb, tb, prec, round_ceiling) if a == fnan: a = fzero if b == fnan: b = finf # positive * negative elif tbs <= 0: a = mpf_mul(sb, ta, prec, round_floor) b = mpf_mul(sa, tb, prec, round_ceiling) if a == fnan: a = fninf if b == fnan: b = fzero # positive * both signs else: a = mpf_mul(sb, ta, prec, round_floor) b = mpf_mul(sb, tb, prec, round_ceiling) if a == fnan: a = fninf if b == fnan: b = finf elif sbs <= 0: # negative * positive if tas >= 0: a = mpf_mul(sa, tb, prec, round_floor) b = mpf_mul(sb, ta, prec, round_ceiling) if a == fnan: a = fninf if b == fnan: b = fzero # negative * negative elif tbs <= 0: a = mpf_mul(sb, tb, prec, round_floor) b = mpf_mul(sa, ta, prec, round_ceiling) if a == fnan: a = fzero if b == fnan: b = finf # negative * both signs else: a = mpf_mul(sa, tb, prec, round_floor) b = mpf_mul(sa, ta, prec, round_ceiling) if a == fnan: a = fninf if b == fnan: b = finf else: # General case: perform all cross-multiplications and compare # Since the multiplications can be done exactly, we need only # do 4 (instead of 8: two for each rounding mode) cases = [mpf_mul(sa, ta), mpf_mul(sa, tb), mpf_mul(sb, ta), mpf_mul(sb, tb)] if fnan in cases: a, b = (fninf, finf) else: a, b = mpf_min_max(cases) a = mpf_pos(a, prec, round_floor) b = mpf_pos(b, prec, round_ceiling) return a, b def mpi_square(s, prec=0): sa, sb = s if mpf_ge(sa, fzero): a = mpf_mul(sa, sa, prec, round_floor) b = mpf_mul(sb, sb, prec, round_ceiling) elif mpf_le(sb, fzero): a = mpf_mul(sb, sb, prec, round_floor) b = mpf_mul(sa, sa, prec, round_ceiling) else: sa = mpf_neg(sa) sa, sb = mpf_min_max([sa, sb]) a = fzero b = mpf_mul(sb, sb, prec, round_ceiling) return a, b def mpi_div(s, t, prec): sa, sb = s ta, tb = t sas = mpf_sign(sa) sbs = mpf_sign(sb) tas = mpf_sign(ta) tbs = mpf_sign(tb) # 0 / X if sas == sbs == 0: # 0 / if (tas < 0 and tbs > 0) or (tas == 0 or tbs == 0): return fninf, finf return fzero, fzero # Denominator contains both negative and positive numbers; # this should properly be a multi-interval, but the closest # match is the entire (extended) real line if tas < 0 and tbs > 0: return fninf, finf # Assume denominator to be nonnegative if tas < 0: return mpi_div(mpi_neg(s), mpi_neg(t), prec) # Division by zero # XXX: make sure all results make sense if tas == 0: # Numerator contains both signs? if sas < 0 and sbs > 0: return fninf, finf if tas == tbs: return fninf, finf # Numerator positive? if sas >= 0: a = mpf_div(sa, tb, prec, round_floor) b = finf if sbs <= 0: a = fninf b = mpf_div(sb, tb, prec, round_ceiling) # Division with positive denominator # We still have to handle nans resulting from inf/0 or inf/inf else: # Nonnegative numerator if sas >= 0: a = mpf_div(sa, tb, prec, round_floor) b = mpf_div(sb, ta, prec, round_ceiling) if a == fnan: a = fzero if b == fnan: b = finf # Nonpositive numerator elif sbs <= 0: a = mpf_div(sa, ta, prec, round_floor) b = mpf_div(sb, tb, prec, round_ceiling) if a == fnan: a = fninf if b == fnan: b = fzero # Numerator contains both signs? else: a = mpf_div(sa, ta, prec, round_floor) b = mpf_div(sb, ta, prec, round_ceiling) if a == fnan: a = fninf if b == fnan: b = finf return a, b def mpi_pi(prec): a = mpf_pi(prec, round_floor) b = mpf_pi(prec, round_ceiling) return a, b def mpi_exp(s, prec): sa, sb = s # exp is monotonic a = mpf_exp(sa, prec, round_floor) b = mpf_exp(sb, prec, round_ceiling) return a, b def mpi_log(s, prec): sa, sb = s # log is monotonic a = mpf_log(sa, prec, round_floor) b = mpf_log(sb, prec, round_ceiling) return a, b def mpi_sqrt(s, prec): sa, sb = s # sqrt is monotonic a = mpf_sqrt(sa, prec, round_floor) b = mpf_sqrt(sb, prec, round_ceiling) return a, b def mpi_atan(s, prec): sa, sb = s a = mpf_atan(sa, prec, round_floor) b = mpf_atan(sb, prec, round_ceiling) return a, b def mpi_pow_int(s, n, prec): sa, sb = s if n < 0: return mpi_div((fone, fone), mpi_pow_int(s, -n, prec+20), prec) if n == 0: return (fone, fone) if n == 1: return s if n == 2: return mpi_square(s, prec) # Odd -- signs are preserved if n & 1: a = mpf_pow_int(sa, n, prec, round_floor) b = mpf_pow_int(sb, n, prec, round_ceiling) # Even -- important to ensure positivity else: sas = mpf_sign(sa) sbs = mpf_sign(sb) # Nonnegative? if sas >= 0: a = mpf_pow_int(sa, n, prec, round_floor) b = mpf_pow_int(sb, n, prec, round_ceiling) # Nonpositive? elif sbs <= 0: a = mpf_pow_int(sb, n, prec, round_floor) b = mpf_pow_int(sa, n, prec, round_ceiling) # Mixed signs? else: a = fzero # max(-a,b)**n sa = mpf_neg(sa) if mpf_ge(sa, sb): b = mpf_pow_int(sa, n, prec, round_ceiling) else: b = mpf_pow_int(sb, n, prec, round_ceiling) return a, b def mpi_pow(s, t, prec): ta, tb = t if ta == tb and ta not in (finf, fninf): if ta == from_int(to_int(ta)): return mpi_pow_int(s, to_int(ta), prec) if ta == fhalf: return mpi_sqrt(s, prec) u = mpi_log(s, prec + 20) v = mpi_mul(u, t, prec + 20) return mpi_exp(v, prec) def MIN(x, y): if mpf_le(x, y): return x return y def MAX(x, y): if mpf_ge(x, y): return x return y def cos_sin_quadrant(x, wp): sign, man, exp, bc = x if x == fzero: return fone, fzero, 0 # TODO: combine evaluation code to avoid duplicate modulo c, s = mpf_cos_sin(x, wp) t, n, wp_ = mod_pi2(man, exp, exp+bc, 15) if sign: n = -1-n return c, s, n def mpi_cos_sin(x, prec): a, b = x if a == b == fzero: return (fone, fone), (fzero, fzero) # Guaranteed to contain both -1 and 1 if (finf in x) or (fninf in x): return (fnone, fone), (fnone, fone) wp = prec + 20 ca, sa, na = cos_sin_quadrant(a, wp) cb, sb, nb = cos_sin_quadrant(b, wp) ca, cb = mpf_min_max([ca, cb]) sa, sb = mpf_min_max([sa, sb]) # Both functions are monotonic within one quadrant if na == nb: pass # Guaranteed to contain both -1 and 1 elif nb - na >= 4: return (fnone, fone), (fnone, fone) else: # cos has maximum between a and b if na//4 != nb//4: cb = fone # cos has minimum if (na-2)//4 != (nb-2)//4: ca = fnone # sin has maximum if (na-1)//4 != (nb-1)//4: sb = fone # sin has minimum if (na-3)//4 != (nb-3)//4: sa = fnone # Perturb to force interval rounding more = from_man_exp((MPZ_ONE<= 1: if sign: return fnone return fone return v ca = finalize(ca, round_floor) cb = finalize(cb, round_ceiling) sa = finalize(sa, round_floor) sb = finalize(sb, round_ceiling) return (ca,cb), (sa,sb) def mpi_cos(x, prec): return mpi_cos_sin(x, prec)[0] def mpi_sin(x, prec): return mpi_cos_sin(x, prec)[1] def mpi_tan(x, prec): cos, sin = mpi_cos_sin(x, prec+20) return mpi_div(sin, cos, prec) def mpi_cot(x, prec): cos, sin = mpi_cos_sin(x, prec+20) return mpi_div(cos, sin, prec) def mpi_from_str_a_b(x, y, percent, prec): wp = prec + 20 xa = from_str(x, wp, round_floor) xb = from_str(x, wp, round_ceiling) #ya = from_str(y, wp, round_floor) y = from_str(y, wp, round_ceiling) assert mpf_ge(y, fzero) if percent: y = mpf_mul(MAX(mpf_abs(xa), mpf_abs(xb)), y, wp, round_ceiling) y = mpf_div(y, from_int(100), wp, round_ceiling) a = mpf_sub(xa, y, prec, round_floor) b = mpf_add(xb, y, prec, round_ceiling) return a, b def mpi_from_str(s, prec): """ Parse an interval number given as a string. Allowed forms are "-1.23e-27" Any single decimal floating-point literal. "a +- b" or "a (b)" a is the midpoint of the interval and b is the half-width "a +- b%" or "a (b%)" a is the midpoint of the interval and the half-width is b percent of a (`a \times b / 100`). "[a, b]" The interval indicated directly. "x[y,z]e" x are shared digits, y and z are unequal digits, e is the exponent. """ e = ValueError("Improperly formed interval number '%s'" % s) s = s.replace(" ", "") wp = prec + 20 if "+-" in s: x, y = s.split("+-") return mpi_from_str_a_b(x, y, False, prec) # case 2 elif "(" in s: # Don't confuse with a complex number (x,y) if s[0] == "(" or ")" not in s: raise e s = s.replace(")", "") percent = False if "%" in s: if s[-1] != "%": raise e percent = True s = s.replace("%", "") x, y = s.split("(") return mpi_from_str_a_b(x, y, percent, prec) elif "," in s: if ('[' not in s) or (']' not in s): raise e if s[0] == '[': # case 3 s = s.replace("[", "") s = s.replace("]", "") a, b = s.split(",") a = from_str(a, prec, round_floor) b = from_str(b, prec, round_ceiling) return a, b else: # case 4 x, y = s.split('[') y, z = y.split(',') if 'e' in s: z, e = z.split(']') else: z, e = z.rstrip(']'), '' a = from_str(x+y+e, prec, round_floor) b = from_str(x+z+e, prec, round_ceiling) return a, b else: a = from_str(s, prec, round_floor) b = from_str(s, prec, round_ceiling) return a, b def mpi_to_str(x, dps, use_spaces=True, brackets='[]', mode='brackets', error_dps=4, **kwargs): """ Convert a mpi interval to a string. **Arguments** *dps* decimal places to use for printing *use_spaces* use spaces for more readable output, defaults to true *brackets* pair of strings (or two-character string) giving left and right brackets *mode* mode of display: 'plusminus', 'percent', 'brackets' (default) or 'diff' *error_dps* limit the error to *error_dps* digits (mode 'plusminus and 'percent') Additional keyword arguments are forwarded to the mpf-to-string conversion for the components of the output. **Examples** >>> from mpmath import mpi, mp >>> mp.dps = 30 >>> x = mpi(1, 2)._mpi_ >>> mpi_to_str(x, 2, mode='plusminus') '1.5 +- 0.5' >>> mpi_to_str(x, 2, mode='percent') '1.5 (33.33%)' >>> mpi_to_str(x, 2, mode='brackets') '[1.0, 2.0]' >>> mpi_to_str(x, 2, mode='brackets' , brackets=('<', '>')) '<1.0, 2.0>' >>> x = mpi('5.2582327113062393041', '5.2582327113062749951')._mpi_ >>> mpi_to_str(x, 15, mode='diff') '5.2582327113062[4, 7]' >>> mpi_to_str(mpi(0)._mpi_, 2, mode='percent') '0.0 (0.0%)' """ prec = dps_to_prec(dps) wp = prec + 20 a, b = x mid = mpi_mid(x, prec) delta = mpi_delta(x, prec) a_str = to_str(a, dps, **kwargs) b_str = to_str(b, dps, **kwargs) mid_str = to_str(mid, dps, **kwargs) sp = "" if use_spaces: sp = " " br1, br2 = brackets if mode == 'plusminus': delta_str = to_str(mpf_shift(delta,-1), dps, **kwargs) s = mid_str + sp + "+-" + sp + delta_str elif mode == 'percent': if mid == fzero: p = fzero else: # p = 100 * delta(x) / (2*mid(x)) p = mpf_mul(delta, from_int(100)) p = mpf_div(p, mpf_mul(mid, from_int(2)), wp) s = mid_str + sp + "(" + to_str(p, error_dps) + "%)" elif mode == 'brackets': s = br1 + a_str + "," + sp + b_str + br2 elif mode == 'diff': # use more digits if str(x.a) and str(x.b) are equal if a_str == b_str: a_str = to_str(a, dps+3, **kwargs) b_str = to_str(b, dps+3, **kwargs) # separate mantissa and exponent a = a_str.split('e') if len(a) == 1: a.append('') b = b_str.split('e') if len(b) == 1: b.append('') if a[1] == b[1]: if a[0] != b[0]: for i in xrange(len(a[0]) + 1): if a[0][i] != b[0][i]: break s = (a[0][:i] + br1 + a[0][i:] + ',' + sp + b[0][i:] + br2 + 'e'*min(len(a[1]), 1) + a[1]) else: # no difference s = a[0] + br1 + br2 + 'e'*min(len(a[1]), 1) + a[1] else: s = br1 + 'e'.join(a) + ',' + sp + 'e'.join(b) + br2 else: raise ValueError("'%s' is unknown mode for printing mpi" % mode) return s def mpci_add(x, y, prec): a, b = x c, d = y return mpi_add(a, c, prec), mpi_add(b, d, prec) def mpci_sub(x, y, prec): a, b = x c, d = y return mpi_sub(a, c, prec), mpi_sub(b, d, prec) def mpci_neg(x, prec=0): a, b = x return mpi_neg(a, prec), mpi_neg(b, prec) def mpci_pos(x, prec): a, b = x return mpi_pos(a, prec), mpi_pos(b, prec) def mpci_mul(x, y, prec): # TODO: optimize for real/imag cases a, b = x c, d = y r1 = mpi_mul(a,c) r2 = mpi_mul(b,d) re = mpi_sub(r1,r2,prec) i1 = mpi_mul(a,d) i2 = mpi_mul(b,c) im = mpi_add(i1,i2,prec) return re, im def mpci_div(x, y, prec): # TODO: optimize for real/imag cases a, b = x c, d = y wp = prec+20 m1 = mpi_square(c) m2 = mpi_square(d) m = mpi_add(m1,m2,wp) re = mpi_add(mpi_mul(a,c), mpi_mul(b,d), wp) im = mpi_sub(mpi_mul(b,c), mpi_mul(a,d), wp) re = mpi_div(re, m, prec) im = mpi_div(im, m, prec) return re, im def mpci_exp(x, prec): a, b = x wp = prec+20 r = mpi_exp(a, wp) c, s = mpi_cos_sin(b, wp) a = mpi_mul(r, c, prec) b = mpi_mul(r, s, prec) return a, b def mpi_shift(x, n): a, b = x return mpf_shift(a,n), mpf_shift(b,n) def mpi_cosh_sinh(x, prec): # TODO: accuracy for small x wp = prec+20 e1 = mpi_exp(x, wp) e2 = mpi_div(mpi_one, e1, wp) c = mpi_add(e1, e2, prec) s = mpi_sub(e1, e2, prec) c = mpi_shift(c, -1) s = mpi_shift(s, -1) return c, s def mpci_cos(x, prec): a, b = x wp = prec+10 c, s = mpi_cos_sin(a, wp) ch, sh = mpi_cosh_sinh(b, wp) re = mpi_mul(c, ch, prec) im = mpi_mul(s, sh, prec) return re, mpi_neg(im) def mpci_sin(x, prec): a, b = x wp = prec+10 c, s = mpi_cos_sin(a, wp) ch, sh = mpi_cosh_sinh(b, wp) re = mpi_mul(s, ch, prec) im = mpi_mul(c, sh, prec) return re, im def mpci_abs(x, prec): a, b = x if a == mpi_zero: return mpi_abs(b) if b == mpi_zero: return mpi_abs(a) # Important: nonnegative a = mpi_square(a) b = mpi_square(b) t = mpi_add(a, b, prec+20) return mpi_sqrt(t, prec) def mpi_atan2(y, x, prec): ya, yb = y xa, xb = x # Constrained to the real line if ya == yb == fzero: if mpf_ge(xa, fzero): return mpi_zero return mpi_pi(prec) # Right half-plane if mpf_ge(xa, fzero): if mpf_ge(ya, fzero): a = mpf_atan2(ya, xb, prec, round_floor) else: a = mpf_atan2(ya, xa, prec, round_floor) if mpf_ge(yb, fzero): b = mpf_atan2(yb, xa, prec, round_ceiling) else: b = mpf_atan2(yb, xb, prec, round_ceiling) # Upper half-plane elif mpf_ge(ya, fzero): b = mpf_atan2(ya, xa, prec, round_ceiling) if mpf_le(xb, fzero): a = mpf_atan2(yb, xb, prec, round_floor) else: a = mpf_atan2(ya, xb, prec, round_floor) # Lower half-plane elif mpf_le(yb, fzero): a = mpf_atan2(yb, xa, prec, round_floor) if mpf_le(xb, fzero): b = mpf_atan2(ya, xb, prec, round_ceiling) else: b = mpf_atan2(yb, xb, prec, round_ceiling) # Covering the origin else: b = mpf_pi(prec, round_ceiling) a = mpf_neg(b) return a, b def mpci_arg(z, prec): x, y = z return mpi_atan2(y, x, prec) def mpci_log(z, prec): x, y = z re = mpi_log(mpci_abs(z, prec+20), prec) im = mpci_arg(z, prec) return re, im def mpci_pow(x, y, prec): # TODO: recognize/speed up real cases, integer y yre, yim = y if yim == mpi_zero: ya, yb = yre if ya == yb: sign, man, exp, bc = yb if man and exp >= 0: return mpci_pow_int(x, (-1)**sign * int(man<>= 1 return mpci_pos(result, prec) gamma_min_a = from_float(1.46163214496) gamma_min_b = from_float(1.46163214497) gamma_min = (gamma_min_a, gamma_min_b) gamma_mono_imag_a = from_float(-1.1) gamma_mono_imag_b = from_float(1.1) def mpi_overlap(x, y): a, b = x c, d = y if mpf_lt(d, a): return False if mpf_gt(c, b): return False return True # type = 0 -- gamma # type = 1 -- factorial # type = 2 -- 1/gamma # type = 3 -- log-gamma def mpi_gamma(z, prec, type=0): a, b = z wp = prec+20 if type == 1: return mpi_gamma(mpi_add(z, mpi_one, wp), prec, 0) # increasing if mpf_gt(a, gamma_min_b): if type == 0: c = mpf_gamma(a, prec, round_floor) d = mpf_gamma(b, prec, round_ceiling) elif type == 2: c = mpf_rgamma(b, prec, round_floor) d = mpf_rgamma(a, prec, round_ceiling) elif type == 3: c = mpf_loggamma(a, prec, round_floor) d = mpf_loggamma(b, prec, round_ceiling) # decreasing elif mpf_gt(a, fzero) and mpf_lt(b, gamma_min_a): if type == 0: c = mpf_gamma(b, prec, round_floor) d = mpf_gamma(a, prec, round_ceiling) elif type == 2: c = mpf_rgamma(a, prec, round_floor) d = mpf_rgamma(b, prec, round_ceiling) elif type == 3: c = mpf_loggamma(b, prec, round_floor) d = mpf_loggamma(a, prec, round_ceiling) else: # TODO: reflection formula znew = mpi_add(z, mpi_one, wp) if type == 0: return mpi_div(mpi_gamma(znew, prec+2, 0), z, prec) if type == 2: return mpi_mul(mpi_gamma(znew, prec+2, 2), z, prec) if type == 3: return mpi_sub(mpi_gamma(znew, prec+2, 3), mpi_log(z, prec+2), prec) return c, d def mpci_gamma(z, prec, type=0): (a1,a2), (b1,b2) = z # Real case if b1 == b2 == fzero and (type != 3 or mpf_gt(a1,fzero)): return mpi_gamma(z, prec, type), mpi_zero # Estimate precision wp = prec+20 if type != 3: amag = a2[2]+a2[3] bmag = b2[2]+b2[3] if a2 != fzero: mag = max(amag, bmag) else: mag = bmag an = abs(to_int(a2)) bn = abs(to_int(b2)) absn = max(an, bn) gamma_size = max(0,absn*mag) wp += bitcount(gamma_size) # Assume type != 1 if type == 1: (a1,a2) = mpi_add((a1,a2), mpi_one, wp); z = (a1,a2), (b1,b2) type = 0 # Avoid non-monotonic region near the negative real axis if mpf_lt(a1, gamma_min_b): if mpi_overlap((b1,b2), (gamma_mono_imag_a, gamma_mono_imag_b)): # TODO: reflection formula #if mpf_lt(a2, mpf_shift(fone,-1)): # znew = mpci_sub((mpi_one,mpi_zero),z,wp) # ... # Recurrence: # gamma(z) = gamma(z+1)/z znew = mpi_add((a1,a2), mpi_one, wp), (b1,b2) if type == 0: return mpci_div(mpci_gamma(znew, prec+2, 0), z, prec) if type == 2: return mpci_mul(mpci_gamma(znew, prec+2, 2), z, prec) if type == 3: return mpci_sub(mpci_gamma(znew, prec+2, 3), mpci_log(z,prec+2), prec) # Use monotonicity (except for a small region close to the # origin and near poles) # upper half-plane if mpf_ge(b1, fzero): minre = mpc_loggamma((a1,b2), wp, round_floor) maxre = mpc_loggamma((a2,b1), wp, round_ceiling) minim = mpc_loggamma((a1,b1), wp, round_floor) maxim = mpc_loggamma((a2,b2), wp, round_ceiling) # lower half-plane elif mpf_le(b2, fzero): minre = mpc_loggamma((a1,b1), wp, round_floor) maxre = mpc_loggamma((a2,b2), wp, round_ceiling) minim = mpc_loggamma((a2,b1), wp, round_floor) maxim = mpc_loggamma((a1,b2), wp, round_ceiling) # crosses real axis else: maxre = mpc_loggamma((a2,fzero), wp, round_ceiling) # stretches more into the lower half-plane if mpf_gt(mpf_neg(b1), b2): minre = mpc_loggamma((a1,b1), wp, round_ceiling) else: minre = mpc_loggamma((a1,b2), wp, round_ceiling) minim = mpc_loggamma((a2,b1), wp, round_floor) maxim = mpc_loggamma((a2,b2), wp, round_floor) w = (minre[0], maxre[0]), (minim[1], maxim[1]) if type == 3: return mpi_pos(w[0], prec), mpi_pos(w[1], prec) if type == 2: w = mpci_neg(w) return mpci_exp(w, prec) def mpi_loggamma(z, prec): return mpi_gamma(z, prec, type=3) def mpci_loggamma(z, prec): return mpci_gamma(z, prec, type=3) def mpi_rgamma(z, prec): return mpi_gamma(z, prec, type=2) def mpci_rgamma(z, prec): return mpci_gamma(z, prec, type=2) def mpi_factorial(z, prec): return mpi_gamma(z, prec, type=1) def mpci_factorial(z, prec): return mpci_gamma(z, prec, type=1) mpmath-1.1.0/mpmath/libmp/six.py000066400000000000000000000271171340375245600165660ustar00rootroot00000000000000"""Utilities for writing code that runs on Python 2 and 3""" # Copyright (c) 2010-2012 Benjamin Peterson # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in # the Software without restriction, including without limitation the rights to # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of # the Software, and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import operator import sys import types __author__ = "Benjamin Peterson " __version__ = "1.2.0" # True if we are running on Python 3. PY3 = sys.version_info[0] == 3 if PY3: string_types = str, integer_types = int, class_types = type, text_type = str binary_type = bytes MAXSIZE = sys.maxsize else: string_types = basestring, integer_types = (int, long) class_types = (type, types.ClassType) text_type = unicode binary_type = str if sys.platform.startswith("java"): # Jython always uses 32 bits. MAXSIZE = int((1 << 31) - 1) else: # It's possible to have sizeof(long) != sizeof(Py_ssize_t). class X(object): def __len__(self): return 1 << 31 try: len(X()) except OverflowError: # 32-bit MAXSIZE = int((1 << 31) - 1) else: # 64-bit MAXSIZE = int((1 << 63) - 1) del X def _add_doc(func, doc): """Add documentation to a function.""" func.__doc__ = doc def _import_module(name): """Import module, returning the module after the last dot.""" __import__(name) return sys.modules[name] class _LazyDescr(object): def __init__(self, name): self.name = name def __get__(self, obj, tp): result = self._resolve() setattr(obj, self.name, result) # This is a bit ugly, but it avoids running this again. delattr(tp, self.name) return result class MovedModule(_LazyDescr): def __init__(self, name, old, new=None): super(MovedModule, self).__init__(name) if PY3: if new is None: new = name self.mod = new else: self.mod = old def _resolve(self): return _import_module(self.mod) class MovedAttribute(_LazyDescr): def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): super(MovedAttribute, self).__init__(name) if PY3: if new_mod is None: new_mod = name self.mod = new_mod if new_attr is None: if old_attr is None: new_attr = name else: new_attr = old_attr self.attr = new_attr else: self.mod = old_mod if old_attr is None: old_attr = name self.attr = old_attr def _resolve(self): module = _import_module(self.mod) return getattr(module, self.attr) class _MovedItems(types.ModuleType): """Lazy loading of moved objects""" _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("reload_module", "__builtin__", "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), MovedAttribute("StringIO", "StringIO", "io"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), MovedModule("builtins", "__builtin__"), MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), MovedModule("cPickle", "cPickle", "pickle"), MovedModule("queue", "Queue"), MovedModule("reprlib", "repr"), MovedModule("socketserver", "SocketServer"), MovedModule("tkinter", "Tkinter"), MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), MovedModule("tkinter_tix", "Tix", "tkinter.tix"), MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"), MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"), MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), MovedModule("tkinter_font", "tkFont", "tkinter.font"), MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("winreg", "_winreg"), ] for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) del attr moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves") def add_move(move): """Add an item to six.moves.""" setattr(_MovedItems, move.name, move) def remove_move(name): """Remove item from six.moves.""" try: delattr(_MovedItems, name) except AttributeError: try: del moves.__dict__[name] except KeyError: raise AttributeError("no such move, %r" % (name,)) if PY3: _meth_func = "__func__" _meth_self = "__self__" _func_code = "__code__" _func_defaults = "__defaults__" _iterkeys = "keys" _itervalues = "values" _iteritems = "items" else: _meth_func = "im_func" _meth_self = "im_self" _func_code = "func_code" _func_defaults = "func_defaults" _iterkeys = "iterkeys" _itervalues = "itervalues" _iteritems = "iteritems" try: advance_iterator = next except NameError: def advance_iterator(it): return it.next() next = advance_iterator if PY3: def get_unbound_function(unbound): return unbound Iterator = object def callable(obj): return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) else: def get_unbound_function(unbound): return unbound.im_func class Iterator(object): def next(self): return type(self).__next__(self) callable = callable _add_doc(get_unbound_function, """Get the function out of a possibly unbound function""") get_method_function = operator.attrgetter(_meth_func) get_method_self = operator.attrgetter(_meth_self) get_function_code = operator.attrgetter(_func_code) get_function_defaults = operator.attrgetter(_func_defaults) def iterkeys(d): """Return an iterator over the keys of a dictionary.""" return iter(getattr(d, _iterkeys)()) def itervalues(d): """Return an iterator over the values of a dictionary.""" return iter(getattr(d, _itervalues)()) def iteritems(d): """Return an iterator over the (key, value) pairs of a dictionary.""" return iter(getattr(d, _iteritems)()) if PY3: def b(s): return s.encode("latin-1") def u(s): return s if sys.version_info[1] <= 1: def int2byte(i): return bytes((i,)) else: # This is about 2x faster than the implementation above on 3.2+ int2byte = operator.methodcaller("to_bytes", 1, "big") import io StringIO = io.StringIO BytesIO = io.BytesIO else: def b(s): return s def u(s): return unicode(s, "unicode_escape") int2byte = chr import StringIO StringIO = BytesIO = StringIO.StringIO _add_doc(b, """Byte literal""") _add_doc(u, """Text literal""") if PY3: import builtins exec_ = getattr(builtins, "exec") def reraise(tp, value, tb=None): if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value print_ = getattr(builtins, "print") del builtins else: def exec_(code, globs=None, locs=None): """Execute code in a namespace.""" if globs is None: frame = sys._getframe(1) globs = frame.f_globals if locs is None: locs = frame.f_locals del frame elif locs is None: locs = globs exec("""exec code in globs, locs""") exec_("""def reraise(tp, value, tb=None): raise tp, value, tb """) def print_(*args, **kwargs): """The new-style print function.""" fp = kwargs.pop("file", sys.stdout) if fp is None: return def write(data): if not isinstance(data, basestring): data = str(data) fp.write(data) want_unicode = False sep = kwargs.pop("sep", None) if sep is not None: if isinstance(sep, unicode): want_unicode = True elif not isinstance(sep, str): raise TypeError("sep must be None or a string") end = kwargs.pop("end", None) if end is not None: if isinstance(end, unicode): want_unicode = True elif not isinstance(end, str): raise TypeError("end must be None or a string") if kwargs: raise TypeError("invalid keyword arguments to print()") if not want_unicode: for arg in args: if isinstance(arg, unicode): want_unicode = True break if want_unicode: newline = unicode("\n") space = unicode(" ") else: newline = "\n" space = " " if sep is None: sep = space if end is None: end = newline for i, arg in enumerate(args): if i: write(sep) write(arg) write(end) _add_doc(reraise, """Reraise an exception.""") def with_metaclass(meta, base=object): """Create a base class with a metaclass.""" return meta("NewBase", (base,), {}) mpmath-1.1.0/mpmath/math2.py000066400000000000000000000442011340375245600156640ustar00rootroot00000000000000""" This module complements the math and cmath builtin modules by providing fast machine precision versions of some additional functions (gamma, ...) and wrapping math/cmath functions so that they can be called with either real or complex arguments. """ import operator import math import cmath # Irrational (?) constants pi = 3.1415926535897932385 e = 2.7182818284590452354 sqrt2 = 1.4142135623730950488 sqrt5 = 2.2360679774997896964 phi = 1.6180339887498948482 ln2 = 0.69314718055994530942 ln10 = 2.302585092994045684 euler = 0.57721566490153286061 catalan = 0.91596559417721901505 khinchin = 2.6854520010653064453 apery = 1.2020569031595942854 logpi = 1.1447298858494001741 def _mathfun_real(f_real, f_complex): def f(x, **kwargs): if type(x) is float: return f_real(x) if type(x) is complex: return f_complex(x) try: x = float(x) return f_real(x) except (TypeError, ValueError): x = complex(x) return f_complex(x) f.__name__ = f_real.__name__ return f def _mathfun(f_real, f_complex): def f(x, **kwargs): if type(x) is complex: return f_complex(x) try: return f_real(float(x)) except (TypeError, ValueError): return f_complex(complex(x)) f.__name__ = f_real.__name__ return f def _mathfun_n(f_real, f_complex): def f(*args, **kwargs): try: return f_real(*(float(x) for x in args)) except (TypeError, ValueError): return f_complex(*(complex(x) for x in args)) f.__name__ = f_real.__name__ return f # Workaround for non-raising log and sqrt in Python 2.5 and 2.4 # on Unix system try: math.log(-2.0) def math_log(x): if x <= 0.0: raise ValueError("math domain error") return math.log(x) def math_sqrt(x): if x < 0.0: raise ValueError("math domain error") return math.sqrt(x) except (ValueError, TypeError): math_log = math.log math_sqrt = math.sqrt pow = _mathfun_n(operator.pow, lambda x, y: complex(x)**y) log = _mathfun_n(math_log, cmath.log) sqrt = _mathfun(math_sqrt, cmath.sqrt) exp = _mathfun_real(math.exp, cmath.exp) cos = _mathfun_real(math.cos, cmath.cos) sin = _mathfun_real(math.sin, cmath.sin) tan = _mathfun_real(math.tan, cmath.tan) acos = _mathfun(math.acos, cmath.acos) asin = _mathfun(math.asin, cmath.asin) atan = _mathfun_real(math.atan, cmath.atan) cosh = _mathfun_real(math.cosh, cmath.cosh) sinh = _mathfun_real(math.sinh, cmath.sinh) tanh = _mathfun_real(math.tanh, cmath.tanh) floor = _mathfun_real(math.floor, lambda z: complex(math.floor(z.real), math.floor(z.imag))) ceil = _mathfun_real(math.ceil, lambda z: complex(math.ceil(z.real), math.ceil(z.imag))) cos_sin = _mathfun_real(lambda x: (math.cos(x), math.sin(x)), lambda z: (cmath.cos(z), cmath.sin(z))) cbrt = _mathfun(lambda x: x**(1./3), lambda z: z**(1./3)) def nthroot(x, n): r = 1./n try: return float(x) ** r except (ValueError, TypeError): return complex(x) ** r def _sinpi_real(x): if x < 0: return -_sinpi_real(-x) n, r = divmod(x, 0.5) r *= pi n %= 4 if n == 0: return math.sin(r) if n == 1: return math.cos(r) if n == 2: return -math.sin(r) if n == 3: return -math.cos(r) def _cospi_real(x): if x < 0: x = -x n, r = divmod(x, 0.5) r *= pi n %= 4 if n == 0: return math.cos(r) if n == 1: return -math.sin(r) if n == 2: return -math.cos(r) if n == 3: return math.sin(r) def _sinpi_complex(z): if z.real < 0: return -_sinpi_complex(-z) n, r = divmod(z.real, 0.5) z = pi*complex(r, z.imag) n %= 4 if n == 0: return cmath.sin(z) if n == 1: return cmath.cos(z) if n == 2: return -cmath.sin(z) if n == 3: return -cmath.cos(z) def _cospi_complex(z): if z.real < 0: z = -z n, r = divmod(z.real, 0.5) z = pi*complex(r, z.imag) n %= 4 if n == 0: return cmath.cos(z) if n == 1: return -cmath.sin(z) if n == 2: return -cmath.cos(z) if n == 3: return cmath.sin(z) cospi = _mathfun_real(_cospi_real, _cospi_complex) sinpi = _mathfun_real(_sinpi_real, _sinpi_complex) def tanpi(x): try: return sinpi(x) / cospi(x) except OverflowError: if complex(x).imag > 10: return 1j if complex(x).imag < 10: return -1j raise def cotpi(x): try: return cospi(x) / sinpi(x) except OverflowError: if complex(x).imag > 10: return -1j if complex(x).imag < 10: return 1j raise INF = 1e300*1e300 NINF = -INF NAN = INF-INF EPS = 2.2204460492503131e-16 _exact_gamma = (INF, 1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0, 121645100408832000.0, 2432902008176640000.0) _max_exact_gamma = len(_exact_gamma)-1 # Lanczos coefficients used by the GNU Scientific Library _lanczos_g = 7 _lanczos_p = (0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7) def _gamma_real(x): _intx = int(x) if _intx == x: if _intx <= 0: #return (-1)**_intx * INF raise ZeroDivisionError("gamma function pole") if _intx <= _max_exact_gamma: return _exact_gamma[_intx] if x < 0.5: # TODO: sinpi return pi / (_sinpi_real(x)*_gamma_real(1-x)) else: x -= 1.0 r = _lanczos_p[0] for i in range(1, _lanczos_g+2): r += _lanczos_p[i]/(x+i) t = x + _lanczos_g + 0.5 return 2.506628274631000502417 * t**(x+0.5) * math.exp(-t) * r def _gamma_complex(x): if not x.imag: return complex(_gamma_real(x.real)) if x.real < 0.5: # TODO: sinpi return pi / (_sinpi_complex(x)*_gamma_complex(1-x)) else: x -= 1.0 r = _lanczos_p[0] for i in range(1, _lanczos_g+2): r += _lanczos_p[i]/(x+i) t = x + _lanczos_g + 0.5 return 2.506628274631000502417 * t**(x+0.5) * cmath.exp(-t) * r gamma = _mathfun_real(_gamma_real, _gamma_complex) def rgamma(x): try: return 1./gamma(x) except ZeroDivisionError: return x*0.0 def factorial(x): return gamma(x+1.0) def arg(x): if type(x) is float: return math.atan2(0.0,x) return math.atan2(x.imag,x.real) # XXX: broken for negatives def loggamma(x): if type(x) not in (float, complex): try: x = float(x) except (ValueError, TypeError): x = complex(x) try: xreal = x.real ximag = x.imag except AttributeError: # py2.5 xreal = x ximag = 0.0 # Reflection formula # http://functions.wolfram.com/GammaBetaErf/LogGamma/16/01/01/0003/ if xreal < 0.0: if abs(x) < 0.5: v = log(gamma(x)) if ximag == 0: v = v.conjugate() return v z = 1-x try: re = z.real im = z.imag except AttributeError: # py2.5 re = z im = 0.0 refloor = floor(re) if im == 0.0: imsign = 0 elif im < 0.0: imsign = -1 else: imsign = 1 return (-pi*1j)*abs(refloor)*(1-abs(imsign)) + logpi - \ log(sinpi(z-refloor)) - loggamma(z) + 1j*pi*refloor*imsign if x == 1.0 or x == 2.0: return x*0 p = 0. while abs(x) < 11: p -= log(x) x += 1.0 s = 0.918938533204672742 + (x-0.5)*log(x) - x r = 1./x r2 = r*r s += 0.083333333333333333333*r; r *= r2 s += -0.0027777777777777777778*r; r *= r2 s += 0.00079365079365079365079*r; r *= r2 s += -0.0005952380952380952381*r; r *= r2 s += 0.00084175084175084175084*r; r *= r2 s += -0.0019175269175269175269*r; r *= r2 s += 0.0064102564102564102564*r; r *= r2 s += -0.02955065359477124183*r return s + p _psi_coeff = [ 0.083333333333333333333, -0.0083333333333333333333, 0.003968253968253968254, -0.0041666666666666666667, 0.0075757575757575757576, -0.021092796092796092796, 0.083333333333333333333, -0.44325980392156862745, 3.0539543302701197438, -26.456212121212121212] def _digamma_real(x): _intx = int(x) if _intx == x: if _intx <= 0: raise ZeroDivisionError("polygamma pole") if x < 0.5: x = 1.0-x s = pi*cotpi(x) else: s = 0.0 while x < 10.0: s -= 1.0/x x += 1.0 x2 = x**-2 t = x2 for c in _psi_coeff: s -= c*t if t < 1e-20: break t *= x2 return s + math_log(x) - 0.5/x def _digamma_complex(x): if not x.imag: return complex(_digamma_real(x.real)) if x.real < 0.5: x = 1.0-x s = pi*cotpi(x) else: s = 0.0 while abs(x) < 10.0: s -= 1.0/x x += 1.0 x2 = x**-2 t = x2 for c in _psi_coeff: s -= c*t if abs(t) < 1e-20: break t *= x2 return s + cmath.log(x) - 0.5/x digamma = _mathfun_real(_digamma_real, _digamma_complex) # TODO: could implement complex erf and erfc here. Need # to find an accurate method (avoiding cancellation) # for approx. 1 < abs(x) < 9. _erfc_coeff_P = [ 1.0000000161203922312, 2.1275306946297962644, 2.2280433377390253297, 1.4695509105618423961, 0.66275911699770787537, 0.20924776504163751585, 0.045459713768411264339, 0.0063065951710717791934, 0.00044560259661560421715][::-1] _erfc_coeff_Q = [ 1.0000000000000000000, 3.2559100272784894318, 4.9019435608903239131, 4.4971472894498014205, 2.7845640601891186528, 1.2146026030046904138, 0.37647108453729465912, 0.080970149639040548613, 0.011178148899483545902, 0.00078981003831980423513][::-1] def _polyval(coeffs, x): p = coeffs[0] for c in coeffs[1:]: p = c + x*p return p def _erf_taylor(x): # Taylor series assuming 0 <= x <= 1 x2 = x*x s = t = x n = 1 while abs(t) > 1e-17: t *= x2/n s -= t/(n+n+1) n += 1 t *= x2/n s += t/(n+n+1) n += 1 return 1.1283791670955125739*s def _erfc_mid(x): # Rational approximation assuming 0 <= x <= 9 return exp(-x*x)*_polyval(_erfc_coeff_P,x)/_polyval(_erfc_coeff_Q,x) def _erfc_asymp(x): # Asymptotic expansion assuming x >= 9 x2 = x*x v = exp(-x2)/x*0.56418958354775628695 r = t = 0.5 / x2 s = 1.0 for n in range(1,22,4): s -= t t *= r * (n+2) s += t t *= r * (n+4) if abs(t) < 1e-17: break return s * v def erf(x): """ erf of a real number. """ x = float(x) if x != x: return x if x < 0.0: return -erf(-x) if x >= 1.0: if x >= 6.0: return 1.0 return 1.0 - _erfc_mid(x) return _erf_taylor(x) def erfc(x): """ erfc of a real number. """ x = float(x) if x != x: return x if x < 0.0: if x < -6.0: return 2.0 return 2.0-erfc(-x) if x > 9.0: return _erfc_asymp(x) if x >= 1.0: return _erfc_mid(x) return 1.0 - _erf_taylor(x) gauss42 = [\ (0.99839961899006235, 0.0041059986046490839), (-0.99839961899006235, 0.0041059986046490839), (0.9915772883408609, 0.009536220301748501), (-0.9915772883408609,0.009536220301748501), (0.97934250806374812, 0.014922443697357493), (-0.97934250806374812, 0.014922443697357493), (0.96175936533820439,0.020227869569052644), (-0.96175936533820439, 0.020227869569052644), (0.93892355735498811, 0.025422959526113047), (-0.93892355735498811,0.025422959526113047), (0.91095972490412735, 0.030479240699603467), (-0.91095972490412735, 0.030479240699603467), (0.87802056981217269,0.03536907109759211), (-0.87802056981217269, 0.03536907109759211), (0.8402859832618168, 0.040065735180692258), (-0.8402859832618168,0.040065735180692258), (0.7979620532554873, 0.044543577771965874), (-0.7979620532554873, 0.044543577771965874), (0.75127993568948048,0.048778140792803244), (-0.75127993568948048, 0.048778140792803244), (0.70049459055617114, 0.052746295699174064), (-0.70049459055617114,0.052746295699174064), (0.64588338886924779, 0.056426369358018376), (-0.64588338886924779, 0.056426369358018376), (0.58774459748510932, 0.059798262227586649), (-0.58774459748510932, 0.059798262227586649), (0.5263957499311922, 0.062843558045002565), (-0.5263957499311922, 0.062843558045002565), (0.46217191207042191, 0.065545624364908975), (-0.46217191207042191, 0.065545624364908975), (0.39542385204297503, 0.067889703376521934), (-0.39542385204297503, 0.067889703376521934), (0.32651612446541151, 0.069862992492594159), (-0.32651612446541151, 0.069862992492594159), (0.25582507934287907, 0.071454714265170971), (-0.25582507934287907, 0.071454714265170971), (0.18373680656485453, 0.072656175243804091), (-0.18373680656485453, 0.072656175243804091), (0.11064502720851986, 0.073460813453467527), (-0.11064502720851986, 0.073460813453467527), (0.036948943165351772, 0.073864234232172879), (-0.036948943165351772, 0.073864234232172879)] EI_ASYMP_CONVERGENCE_RADIUS = 40.0 def ei_asymp(z, _e1=False): r = 1./z s = t = 1.0 k = 1 while 1: t *= k*r s += t if abs(t) < 1e-16: break k += 1 v = s*exp(z)/z if _e1: if type(z) is complex: zreal = z.real zimag = z.imag else: zreal = z zimag = 0.0 if zimag == 0.0 and zreal > 0.0: v += pi*1j else: if type(z) is complex: if z.imag > 0: v += pi*1j if z.imag < 0: v -= pi*1j return v def ei_taylor(z, _e1=False): s = t = z k = 2 while 1: t = t*z/k term = t/k if abs(term) < 1e-17: break s += term k += 1 s += euler if _e1: s += log(-z) else: if type(z) is float or z.imag == 0.0: s += math_log(abs(z)) else: s += cmath.log(z) return s def ei(z, _e1=False): typez = type(z) if typez not in (float, complex): try: z = float(z) typez = float except (TypeError, ValueError): z = complex(z) typez = complex if not z: return -INF absz = abs(z) if absz > EI_ASYMP_CONVERGENCE_RADIUS: return ei_asymp(z, _e1) elif absz <= 2.0 or (typez is float and z > 0.0): return ei_taylor(z, _e1) # Integrate, starting from whichever is smaller of a Taylor # series value or an asymptotic series value if typez is complex and z.real > 0.0: zref = z / absz ref = ei_taylor(zref, _e1) else: zref = EI_ASYMP_CONVERGENCE_RADIUS * z / absz ref = ei_asymp(zref, _e1) C = (zref-z)*0.5 D = (zref+z)*0.5 s = 0.0 if type(z) is complex: _exp = cmath.exp else: _exp = math.exp for x,w in gauss42: t = C*x+D s += w*_exp(t)/t ref -= C*s return ref def e1(z): # hack to get consistent signs if the imaginary part if 0 # and signed typez = type(z) if type(z) not in (float, complex): try: z = float(z) typez = float except (TypeError, ValueError): z = complex(z) typez = complex if typez is complex and not z.imag: z = complex(z.real, 0.0) # end hack return -ei(-z, _e1=True) _zeta_int = [\ -0.5, 0.0, 1.6449340668482264365,1.2020569031595942854,1.0823232337111381915, 1.0369277551433699263,1.0173430619844491397,1.0083492773819228268, 1.0040773561979443394,1.0020083928260822144,1.0009945751278180853, 1.0004941886041194646,1.0002460865533080483,1.0001227133475784891, 1.0000612481350587048,1.0000305882363070205,1.0000152822594086519, 1.0000076371976378998,1.0000038172932649998,1.0000019082127165539, 1.0000009539620338728,1.0000004769329867878,1.0000002384505027277, 1.0000001192199259653,1.0000000596081890513,1.0000000298035035147, 1.0000000149015548284] _zeta_P = [-3.50000000087575873, -0.701274355654678147, -0.0672313458590012612, -0.00398731457954257841, -0.000160948723019303141, -4.67633010038383371e-6, -1.02078104417700585e-7, -1.68030037095896287e-9, -1.85231868742346722e-11][::-1] _zeta_Q = [1.00000000000000000, -0.936552848762465319, -0.0588835413263763741, -0.00441498861482948666, -0.000143416758067432622, -5.10691659585090782e-6, -9.58813053268913799e-8, -1.72963791443181972e-9, -1.83527919681474132e-11][::-1] _zeta_1 = [3.03768838606128127e-10, -1.21924525236601262e-8, 2.01201845887608893e-7, -1.53917240683468381e-6, -5.09890411005967954e-7, 0.000122464707271619326, -0.000905721539353130232, -0.00239315326074843037, 0.084239750013159168, 0.418938517907442414, 0.500000001921884009] _zeta_0 = [-3.46092485016748794e-10, -6.42610089468292485e-9, 1.76409071536679773e-7, -1.47141263991560698e-6, -6.38880222546167613e-7, 0.000122641099800668209, -0.000905894913516772796, -0.00239303348507992713, 0.0842396947501199816, 0.418938533204660256, 0.500000000000000052] def zeta(s): """ Riemann zeta function, real argument """ if not isinstance(s, (float, int)): try: s = float(s) except (ValueError, TypeError): try: s = complex(s) if not s.imag: return complex(zeta(s.real)) except (ValueError, TypeError): pass raise NotImplementedError if s == 1: raise ValueError("zeta(1) pole") if s >= 27: return 1.0 + 2.0**(-s) + 3.0**(-s) n = int(s) if n == s: if n >= 0: return _zeta_int[n] if not (n % 2): return 0.0 if s <= 0.0: return 2.**s*pi**(s-1)*_sinpi_real(0.5*s)*_gamma_real(1-s)*zeta(1-s) if s <= 2.0: if s <= 1.0: return _polyval(_zeta_0,s)/(s-1) return _polyval(_zeta_1,s)/(s-1) z = _polyval(_zeta_P,s) / _polyval(_zeta_Q,s) return 1.0 + 2.0**(-s) + 3.0**(-s) + 4.0**(-s)*z mpmath-1.1.0/mpmath/matrices/000077500000000000000000000000001340375245600161055ustar00rootroot00000000000000mpmath-1.1.0/mpmath/matrices/__init__.py000066400000000000000000000001361340375245600202160ustar00rootroot00000000000000from . import eigen # to set methods from . import eigen_symmetric # to set methods mpmath-1.1.0/mpmath/matrices/calculus.py000066400000000000000000000442611340375245600203010ustar00rootroot00000000000000from ..libmp.backend import xrange # TODO: should use diagonalization-based algorithms class MatrixCalculusMethods(object): def _exp_pade(ctx, a): """ Exponential of a matrix using Pade approximants. See G. H. Golub, C. F. van Loan 'Matrix Computations', third Ed., page 572 TODO: - find a good estimate for q - reduce the number of matrix multiplications to improve performance """ def eps_pade(p): return ctx.mpf(2)**(3-2*p) * \ ctx.factorial(p)**2/(ctx.factorial(2*p)**2 * (2*p + 1)) q = 4 extraq = 8 while 1: if eps_pade(q) < ctx.eps: break q += 1 q += extraq j = int(max(1, ctx.mag(ctx.mnorm(a,'inf')))) extra = q prec = ctx.prec ctx.dps += extra + 3 try: a = a/2**j na = a.rows den = ctx.eye(na) num = ctx.eye(na) x = ctx.eye(na) c = ctx.mpf(1) for k in range(1, q+1): c *= ctx.mpf(q - k + 1)/((2*q - k + 1) * k) x = a*x cx = c*x num += cx den += (-1)**k * cx f = ctx.lu_solve_mat(den, num) for k in range(j): f = f*f finally: ctx.prec = prec return f*1 def expm(ctx, A, method='taylor'): r""" Computes the matrix exponential of a square matrix `A`, which is defined by the power series .. math :: \exp(A) = I + A + \frac{A^2}{2!} + \frac{A^3}{3!} + \ldots With method='taylor', the matrix exponential is computed using the Taylor series. With method='pade', Pade approximants are used instead. **Examples** Basic examples:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> expm(zeros(3)) [1.0 0.0 0.0] [0.0 1.0 0.0] [0.0 0.0 1.0] >>> expm(eye(3)) [2.71828182845905 0.0 0.0] [ 0.0 2.71828182845905 0.0] [ 0.0 0.0 2.71828182845905] >>> expm([[1,1,0],[1,0,1],[0,1,0]]) [ 3.86814500615414 2.26812870852145 0.841130841230196] [ 2.26812870852145 2.44114713886289 1.42699786729125] [0.841130841230196 1.42699786729125 1.6000162976327] >>> expm([[1,1,0],[1,0,1],[0,1,0]], method='pade') [ 3.86814500615414 2.26812870852145 0.841130841230196] [ 2.26812870852145 2.44114713886289 1.42699786729125] [0.841130841230196 1.42699786729125 1.6000162976327] >>> expm([[1+j, 0], [1+j,1]]) [(1.46869393991589 + 2.28735528717884j) 0.0] [ (1.03776739863568 + 3.536943175722j) (2.71828182845905 + 0.0j)] Matrices with large entries are allowed:: >>> expm(matrix([[1,2],[2,3]])**25) [5.65024064048415e+2050488462815550 9.14228140091932e+2050488462815550] [9.14228140091932e+2050488462815550 1.47925220414035e+2050488462815551] The identity `\exp(A+B) = \exp(A) \exp(B)` does not hold for noncommuting matrices:: >>> A = hilbert(3) >>> B = A + eye(3) >>> chop(mnorm(A*B - B*A)) 0.0 >>> chop(mnorm(expm(A+B) - expm(A)*expm(B))) 0.0 >>> B = A + ones(3) >>> mnorm(A*B - B*A) 1.8 >>> mnorm(expm(A+B) - expm(A)*expm(B)) 42.0927851137247 """ if method == 'pade': prec = ctx.prec try: A = ctx.matrix(A) ctx.prec += 2*A.rows res = ctx._exp_pade(A) finally: ctx.prec = prec return res A = ctx.matrix(A) prec = ctx.prec j = int(max(1, ctx.mag(ctx.mnorm(A,'inf')))) j += int(0.5*prec**0.5) try: ctx.prec += 10 + 2*j tol = +ctx.eps A = A/2**j T = A Y = A**0 + A k = 2 while 1: T *= A * (1/ctx.mpf(k)) if ctx.mnorm(T, 'inf') < tol: break Y += T k += 1 for k in xrange(j): Y = Y*Y finally: ctx.prec = prec Y *= 1 return Y def cosm(ctx, A): r""" Gives the cosine of a square matrix `A`, defined in analogy with the matrix exponential. Examples:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> X = eye(3) >>> cosm(X) [0.54030230586814 0.0 0.0] [ 0.0 0.54030230586814 0.0] [ 0.0 0.0 0.54030230586814] >>> X = hilbert(3) >>> cosm(X) [ 0.424403834569555 -0.316643413047167 -0.221474945949293] [-0.316643413047167 0.820646708837824 -0.127183694770039] [-0.221474945949293 -0.127183694770039 0.909236687217541] >>> X = matrix([[1+j,-2],[0,-j]]) >>> cosm(X) [(0.833730025131149 - 0.988897705762865j) (1.07485840848393 - 0.17192140544213j)] [ 0.0 (1.54308063481524 + 0.0j)] """ B = 0.5 * (ctx.expm(A*ctx.j) + ctx.expm(A*(-ctx.j))) if not sum(A.apply(ctx.im).apply(abs)): B = B.apply(ctx.re) return B def sinm(ctx, A): r""" Gives the sine of a square matrix `A`, defined in analogy with the matrix exponential. Examples:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> X = eye(3) >>> sinm(X) [0.841470984807897 0.0 0.0] [ 0.0 0.841470984807897 0.0] [ 0.0 0.0 0.841470984807897] >>> X = hilbert(3) >>> sinm(X) [0.711608512150994 0.339783913247439 0.220742837314741] [0.339783913247439 0.244113865695532 0.187231271174372] [0.220742837314741 0.187231271174372 0.155816730769635] >>> X = matrix([[1+j,-2],[0,-j]]) >>> sinm(X) [(1.29845758141598 + 0.634963914784736j) (-1.96751511930922 + 0.314700021761367j)] [ 0.0 (0.0 - 1.1752011936438j)] """ B = (-0.5j) * (ctx.expm(A*ctx.j) - ctx.expm(A*(-ctx.j))) if not sum(A.apply(ctx.im).apply(abs)): B = B.apply(ctx.re) return B def _sqrtm_rot(ctx, A, _may_rotate): # If the iteration fails to converge, cheat by performing # a rotation by a complex number u = ctx.j**0.3 return ctx.sqrtm(u*A, _may_rotate) / ctx.sqrt(u) def sqrtm(ctx, A, _may_rotate=2): r""" Computes a square root of the square matrix `A`, i.e. returns a matrix `B = A^{1/2}` such that `B^2 = A`. The square root of a matrix, if it exists, is not unique. **Examples** Square roots of some simple matrices:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> sqrtm([[1,0], [0,1]]) [1.0 0.0] [0.0 1.0] >>> sqrtm([[0,0], [0,0]]) [0.0 0.0] [0.0 0.0] >>> sqrtm([[2,0],[0,1]]) [1.4142135623731 0.0] [ 0.0 1.0] >>> sqrtm([[1,1],[1,0]]) [ (0.920442065259926 - 0.21728689675164j) (0.568864481005783 + 0.351577584254143j)] [(0.568864481005783 + 0.351577584254143j) (0.351577584254143 - 0.568864481005783j)] >>> sqrtm([[1,0],[0,1]]) [1.0 0.0] [0.0 1.0] >>> sqrtm([[-1,0],[0,1]]) [(0.0 - 1.0j) 0.0] [ 0.0 (1.0 + 0.0j)] >>> sqrtm([[j,0],[0,j]]) [(0.707106781186547 + 0.707106781186547j) 0.0] [ 0.0 (0.707106781186547 + 0.707106781186547j)] A square root of a rotation matrix, giving the corresponding half-angle rotation matrix:: >>> t1 = 0.75 >>> t2 = t1 * 0.5 >>> A1 = matrix([[cos(t1), -sin(t1)], [sin(t1), cos(t1)]]) >>> A2 = matrix([[cos(t2), -sin(t2)], [sin(t2), cos(t2)]]) >>> sqrtm(A1) [0.930507621912314 -0.366272529086048] [0.366272529086048 0.930507621912314] >>> A2 [0.930507621912314 -0.366272529086048] [0.366272529086048 0.930507621912314] The identity `(A^2)^{1/2} = A` does not necessarily hold:: >>> A = matrix([[4,1,4],[7,8,9],[10,2,11]]) >>> sqrtm(A**2) [ 4.0 1.0 4.0] [ 7.0 8.0 9.0] [10.0 2.0 11.0] >>> sqrtm(A)**2 [ 4.0 1.0 4.0] [ 7.0 8.0 9.0] [10.0 2.0 11.0] >>> A = matrix([[-4,1,4],[7,-8,9],[10,2,11]]) >>> sqrtm(A**2) [ 7.43715112194995 -0.324127569985474 1.8481718827526] [-0.251549715716942 9.32699765900402 2.48221180985147] [ 4.11609388833616 0.775751877098258 13.017955697342] >>> chop(sqrtm(A)**2) [-4.0 1.0 4.0] [ 7.0 -8.0 9.0] [10.0 2.0 11.0] For some matrices, a square root does not exist:: >>> sqrtm([[0,1], [0,0]]) Traceback (most recent call last): ... ZeroDivisionError: matrix is numerically singular Two examples from the documentation for Matlab's ``sqrtm``:: >>> mp.dps = 15; mp.pretty = True >>> sqrtm([[7,10],[15,22]]) [1.56669890360128 1.74077655955698] [2.61116483933547 4.17786374293675] >>> >>> X = matrix(\ ... [[5,-4,1,0,0], ... [-4,6,-4,1,0], ... [1,-4,6,-4,1], ... [0,1,-4,6,-4], ... [0,0,1,-4,5]]) >>> Y = matrix(\ ... [[2,-1,-0,-0,-0], ... [-1,2,-1,0,-0], ... [0,-1,2,-1,0], ... [-0,0,-1,2,-1], ... [-0,-0,-0,-1,2]]) >>> mnorm(sqrtm(X) - Y) 4.53155328326114e-19 """ A = ctx.matrix(A) # Trivial if A*0 == A: return A prec = ctx.prec if _may_rotate: d = ctx.det(A) if abs(ctx.im(d)) < 16*ctx.eps and ctx.re(d) < 0: return ctx._sqrtm_rot(A, _may_rotate-1) try: ctx.prec += 10 tol = ctx.eps * 128 Y = A Z = I = A**0 k = 0 # Denman-Beavers iteration while 1: Yprev = Y try: Y, Z = 0.5*(Y+ctx.inverse(Z)), 0.5*(Z+ctx.inverse(Y)) except ZeroDivisionError: if _may_rotate: Y = ctx._sqrtm_rot(A, _may_rotate-1) break else: raise mag1 = ctx.mnorm(Y-Yprev, 'inf') mag2 = ctx.mnorm(Y, 'inf') if mag1 <= mag2*tol: break if _may_rotate and k > 6 and not mag1 < mag2 * 0.001: return ctx._sqrtm_rot(A, _may_rotate-1) k += 1 if k > ctx.prec: raise ctx.NoConvergence finally: ctx.prec = prec Y *= 1 return Y def logm(ctx, A): r""" Computes a logarithm of the square matrix `A`, i.e. returns a matrix `B = \log(A)` such that `\exp(B) = A`. The logarithm of a matrix, if it exists, is not unique. **Examples** Logarithms of some simple matrices:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> X = eye(3) >>> logm(X) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] >>> logm(2*X) [0.693147180559945 0.0 0.0] [ 0.0 0.693147180559945 0.0] [ 0.0 0.0 0.693147180559945] >>> logm(expm(X)) [1.0 0.0 0.0] [0.0 1.0 0.0] [0.0 0.0 1.0] A logarithm of a complex matrix:: >>> X = matrix([[2+j, 1, 3], [1-j, 1-2*j, 1], [-4, -5, j]]) >>> B = logm(X) >>> nprint(B) [ (0.808757 + 0.107759j) (2.20752 + 0.202762j) (1.07376 - 0.773874j)] [ (0.905709 - 0.107795j) (0.0287395 - 0.824993j) (0.111619 + 0.514272j)] [(-0.930151 + 0.399512j) (-2.06266 - 0.674397j) (0.791552 + 0.519839j)] >>> chop(expm(B)) [(2.0 + 1.0j) 1.0 3.0] [(1.0 - 1.0j) (1.0 - 2.0j) 1.0] [ -4.0 -5.0 (0.0 + 1.0j)] A matrix `X` close to the identity matrix, for which `\log(\exp(X)) = \exp(\log(X)) = X` holds:: >>> X = eye(3) + hilbert(3)/4 >>> X [ 1.25 0.125 0.0833333333333333] [ 0.125 1.08333333333333 0.0625] [0.0833333333333333 0.0625 1.05] >>> logm(expm(X)) [ 1.25 0.125 0.0833333333333333] [ 0.125 1.08333333333333 0.0625] [0.0833333333333333 0.0625 1.05] >>> expm(logm(X)) [ 1.25 0.125 0.0833333333333333] [ 0.125 1.08333333333333 0.0625] [0.0833333333333333 0.0625 1.05] A logarithm of a rotation matrix, giving back the angle of the rotation:: >>> t = 3.7 >>> A = matrix([[cos(t),sin(t)],[-sin(t),cos(t)]]) >>> chop(logm(A)) [ 0.0 -2.58318530717959] [2.58318530717959 0.0] >>> (2*pi-t) 2.58318530717959 For some matrices, a logarithm does not exist:: >>> logm([[1,0], [0,0]]) Traceback (most recent call last): ... ZeroDivisionError: matrix is numerically singular Logarithm of a matrix with large entries:: >>> logm(hilbert(3) * 10**20).apply(re) [ 45.5597513593433 1.27721006042799 0.317662687717978] [ 1.27721006042799 42.5222778973542 2.24003708791604] [0.317662687717978 2.24003708791604 42.395212822267] """ A = ctx.matrix(A) prec = ctx.prec try: ctx.prec += 10 tol = ctx.eps * 128 I = A**0 B = A n = 0 while 1: B = ctx.sqrtm(B) n += 1 if ctx.mnorm(B-I, 'inf') < 0.125: break T = X = B-I L = X*0 k = 1 while 1: if k & 1: L += T / k else: L -= T / k T *= X if ctx.mnorm(T, 'inf') < tol: break k += 1 if k > ctx.prec: raise ctx.NoConvergence finally: ctx.prec = prec L *= 2**n return L def powm(ctx, A, r): r""" Computes `A^r = \exp(A \log r)` for a matrix `A` and complex number `r`. **Examples** Powers and inverse powers of a matrix:: >>> from mpmath import * >>> mp.dps = 15; mp.pretty = True >>> A = matrix([[4,1,4],[7,8,9],[10,2,11]]) >>> powm(A, 2) [ 63.0 20.0 69.0] [174.0 89.0 199.0] [164.0 48.0 179.0] >>> chop(powm(powm(A, 4), 1/4.)) [ 4.0 1.0 4.0] [ 7.0 8.0 9.0] [10.0 2.0 11.0] >>> powm(extraprec(20)(powm)(A, -4), -1/4.) [ 4.0 1.0 4.0] [ 7.0 8.0 9.0] [10.0 2.0 11.0] >>> chop(powm(powm(A, 1+0.5j), 1/(1+0.5j))) [ 4.0 1.0 4.0] [ 7.0 8.0 9.0] [10.0 2.0 11.0] >>> powm(extraprec(5)(powm)(A, -1.5), -1/(1.5)) [ 4.0 1.0 4.0] [ 7.0 8.0 9.0] [10.0 2.0 11.0] A Fibonacci-generating matrix:: >>> powm([[1,1],[1,0]], 10) [89.0 55.0] [55.0 34.0] >>> fib(10) 55.0 >>> powm([[1,1],[1,0]], 6.5) [(16.5166626964253 - 0.0121089837381789j) (10.2078589271083 + 0.0195927472575932j)] [(10.2078589271083 + 0.0195927472575932j) (6.30880376931698 - 0.0317017309957721j)] >>> (phi**6.5 - (1-phi)**6.5)/sqrt(5) (10.2078589271083 - 0.0195927472575932j) >>> powm([[1,1],[1,0]], 6.2) [ (14.3076953002666 - 0.008222855781077j) (8.81733464837593 + 0.0133048601383712j)] [(8.81733464837593 + 0.0133048601383712j) (5.49036065189071 - 0.0215277159194482j)] >>> (phi**6.2 - (1-phi)**6.2)/sqrt(5) (8.81733464837593 - 0.0133048601383712j) """ A = ctx.matrix(A) r = ctx.convert(r) prec = ctx.prec try: ctx.prec += 10 if ctx.isint(r): v = A ** int(r) elif ctx.isint(r*2): y = int(r*2) v = ctx.sqrtm(A) ** y else: v = ctx.expm(r*ctx.logm(A)) finally: ctx.prec = prec v *= 1 return v mpmath-1.1.0/mpmath/matrices/eigen.py000066400000000000000000000574761340375245600175710ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- ################################################################################################## # module for the eigenvalue problem # Copyright 2013 Timo Hartmann (thartmann15 at gmail.com) # # todo: # - implement balancing # - agressive early deflation # ################################################################################################## """ The eigenvalue problem ---------------------- This file contains routines for the eigenvalue problem. high level routines: hessenberg : reduction of a real or complex square matrix to upper Hessenberg form schur : reduction of a real or complex square matrix to upper Schur form eig : eigenvalues and eigenvectors of a real or complex square matrix low level routines: hessenberg_reduce_0 : reduction of a real or complex square matrix to upper Hessenberg form hessenberg_reduce_1 : auxiliary routine to hessenberg_reduce_0 qr_step : a single implicitly shifted QR step for an upper Hessenberg matrix hessenberg_qr : Schur decomposition of an upper Hessenberg matrix eig_tr_r : right eigenvectors of an upper triangular matrix eig_tr_l : left eigenvectors of an upper triangular matrix """ from ..libmp.backend import xrange class Eigen(object): pass def defun(f): setattr(Eigen, f.__name__, f) def hessenberg_reduce_0(ctx, A, T): """ This routine computes the (upper) Hessenberg decomposition of a square matrix A. Given A, an unitary matrix Q is calculated such that Q' A Q = H and Q' Q = Q Q' = 1 where H is an upper Hessenberg matrix, meaning that it only contains zeros below the first subdiagonal. Here ' denotes the hermitian transpose (i.e. transposition and conjugation). parameters: A (input/output) On input, A contains the square matrix A of dimension (n,n). On output, A contains a compressed representation of Q and H. T (output) An array of length n containing the first elements of the Householder reflectors. """ # internally we work with householder reflections from the right. # let u be a row vector (i.e. u[i]=A[i,:i]). then # Q is build up by reflectors of the type (1-v'v) where v is a suitable # modification of u. these reflectors are applyed to A from the right. # because we work with reflectors from the right we have to start with # the bottom row of A and work then upwards (this corresponds to # some kind of RQ decomposition). # the first part of the vectors v (i.e. A[i,:(i-1)]) are stored as row vectors # in the lower left part of A (excluding the diagonal and subdiagonal). # the last entry of v is stored in T. # the upper right part of A (including diagonal and subdiagonal) becomes H. n = A.rows if n <= 2: return for i in xrange(n-1, 1, -1): # scale the vector scale = 0 for k in xrange(0, i): scale += abs(ctx.re(A[i,k])) + abs(ctx.im(A[i,k])) scale_inv = 0 if scale != 0: scale_inv = 1 / scale if scale == 0 or ctx.isinf(scale_inv): # sadly there are floating point numbers not equal to zero whose reciprocal is infinity T[i] = 0 A[i,i-1] = 0 continue # calculate parameters for housholder transformation H = 0 for k in xrange(0, i): A[i,k] *= scale_inv rr = ctx.re(A[i,k]) ii = ctx.im(A[i,k]) H += rr * rr + ii * ii F = A[i,i-1] f = abs(F) G = ctx.sqrt(H) A[i,i-1] = - G * scale if f == 0: T[i] = G else: ff = F / f T[i] = F + G * ff A[i,i-1] *= ff H += G * f H = 1 / ctx.sqrt(H) T[i] *= H for k in xrange(0, i - 1): A[i,k] *= H for j in xrange(0, i): # apply housholder transformation (from right) G = ctx.conj(T[i]) * A[j,i-1] for k in xrange(0, i-1): G += ctx.conj(A[i,k]) * A[j,k] A[j,i-1] -= G * T[i] for k in xrange(0, i-1): A[j,k] -= G * A[i,k] for j in xrange(0, n): # apply housholder transformation (from left) G = T[i] * A[i-1,j] for k in xrange(0, i-1): G += A[i,k] * A[k,j] A[i-1,j] -= G * ctx.conj(T[i]) for k in xrange(0, i-1): A[k,j] -= G * ctx.conj(A[i,k]) def hessenberg_reduce_1(ctx, A, T): """ This routine forms the unitary matrix Q described in hessenberg_reduce_0. parameters: A (input/output) On input, A is the same matrix as delivered by hessenberg_reduce_0. On output, A is set to Q. T (input) On input, T is the same array as delivered by hessenberg_reduce_0. """ n = A.rows if n == 1: A[0,0] = 1 return A[0,0] = A[1,1] = 1 A[0,1] = A[1,0] = 0 for i in xrange(2, n): if T[i] != 0: for j in xrange(0, i): G = T[i] * A[i-1,j] for k in xrange(0, i-1): G += A[i,k] * A[k,j] A[i-1,j] -= G * ctx.conj(T[i]) for k in xrange(0, i-1): A[k,j] -= G * ctx.conj(A[i,k]) A[i,i] = 1 for j in xrange(0, i): A[j,i] = A[i,j] = 0 @defun def hessenberg(ctx, A, overwrite_a = False): """ This routine computes the Hessenberg decomposition of a square matrix A. Given A, an unitary matrix Q is determined such that Q' A Q = H and Q' Q = Q Q' = 1 where H is an upper right Hessenberg matrix. Here ' denotes the hermitian transpose (i.e. transposition and conjugation). input: A : a real or complex square matrix overwrite_a : if true, allows modification of A which may improve performance. if false, A is not modified. output: Q : an unitary matrix H : an upper right Hessenberg matrix example: >>> from mpmath import mp >>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]]) >>> Q, H = mp.hessenberg(A) >>> mp.nprint(H, 3) # doctest:+SKIP [ 3.15 2.23 4.44] [-0.769 4.85 3.05] [ 0.0 3.61 7.0] >>> print(mp.chop(A - Q * H * Q.transpose_conj())) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] return value: (Q, H) """ n = A.rows if n == 1: return (ctx.matrix([[1]]), A) if not overwrite_a: A = A.copy() T = ctx.matrix(n, 1) hessenberg_reduce_0(ctx, A, T) Q = A.copy() hessenberg_reduce_1(ctx, Q, T) for x in xrange(n): for y in xrange(x+2, n): A[y,x] = 0 return Q, A ########################################################################### def qr_step(ctx, n0, n1, A, Q, shift): """ This subroutine executes a single implicitly shifted QR step applied to an upper Hessenberg matrix A. Given A and shift as input, first an QR decomposition is calculated: Q R = A - shift * 1 . The output is then following matrix: R Q + shift * 1 parameters: n0, n1 (input) Two integers which specify the submatrix A[n0:n1,n0:n1] on which this subroutine operators. The subdiagonal elements to the left and below this submatrix must be deflated (i.e. zero). following restriction is imposed: n1>=n0+2 A (input/output) On input, A is an upper Hessenberg matrix. On output, A is replaced by "R Q + shift * 1" Q (input/output) The parameter Q is multiplied by the unitary matrix Q arising from the QR decomposition. Q can also be false, in which case the unitary matrix Q is not computated. shift (input) a complex number specifying the shift. idealy close to an eigenvalue of the bottemmost part of the submatrix A[n0:n1,n0:n1]. references: Stoer, Bulirsch - Introduction to Numerical Analysis. Kresser : Numerical Methods for General and Structured Eigenvalue Problems """ # implicitly shifted and bulge chasing is explained at p.398/399 in "Stoer, Bulirsch - Introduction to Numerical Analysis" # for bulge chasing see also "Watkins - The Matrix Eigenvalue Problem" sec.4.5,p.173 # the Givens rotation we used is determined as follows: let c,s be two complex # numbers. then we have following relation: # # v = sqrt(|c|^2 + |s|^2) # # 1/v [ c~ s~] [c] = [v] # [-s c ] [s] [0] # # the matrix on the left is our Givens rotation. n = A.rows # first step # calculate givens rotation c = A[n0 ,n0] - shift s = A[n0+1,n0] v = ctx.hypot(ctx.hypot(ctx.re(c), ctx.im(c)), ctx.hypot(ctx.re(s), ctx.im(s))) if v == 0: v = 1 c = 1 s = 0 else: c /= v s /= v cc = ctx.conj(c) cs = ctx.conj(s) for k in xrange(n0, n): # apply givens rotation from the left x = A[n0 ,k] y = A[n0+1,k] A[n0 ,k] = cc * x + cs * y A[n0+1,k] = c * y - s * x for k in xrange(min(n1, n0+3)): # apply givens rotation from the right x = A[k,n0 ] y = A[k,n0+1] A[k,n0 ] = c * x + s * y A[k,n0+1] = cc * y - cs * x if not isinstance(Q, bool): for k in xrange(n): # eigenvectors x = Q[k,n0 ] y = Q[k,n0+1] Q[k,n0 ] = c * x + s * y Q[k,n0+1] = cc * y - cs * x # chase the bulge for j in xrange(n0, n1 - 2): # calculate givens rotation c = A[j+1,j] s = A[j+2,j] v = ctx.hypot(ctx.hypot(ctx.re(c), ctx.im(c)), ctx.hypot(ctx.re(s), ctx.im(s))) if v == 0: A[j+1,j] = 0 v = 1 c = 1 s = 0 else: A[j+1,j] = v c /= v s /= v A[j+2,j] = 0 cc = ctx.conj(c) cs = ctx.conj(s) for k in xrange(j+1, n): # apply givens rotation from the left x = A[j+1,k] y = A[j+2,k] A[j+1,k] = cc * x + cs * y A[j+2,k] = c * y - s * x for k in xrange(0, min(n1, j+4)): # apply givens rotation from the right x = A[k,j+1] y = A[k,j+2] A[k,j+1] = c * x + s * y A[k,j+2] = cc * y - cs * x if not isinstance(Q, bool): for k in xrange(0, n): # eigenvectors x = Q[k,j+1] y = Q[k,j+2] Q[k,j+1] = c * x + s * y Q[k,j+2] = cc * y - cs * x def hessenberg_qr(ctx, A, Q): """ This routine computes the Schur decomposition of an upper Hessenberg matrix A. Given A, an unitary matrix Q is determined such that Q' A Q = R and Q' Q = Q Q' = 1 where R is an upper right triangular matrix. Here ' denotes the hermitian transpose (i.e. transposition and conjugation). parameters: A (input/output) On input, A contains an upper Hessenberg matrix. On output, A is replace by the upper right triangluar matrix R. Q (input/output) The parameter Q is multiplied by the unitary matrix Q arising from the Schur decomposition. Q can also be false, in which case the unitary matrix Q is not computated. """ n = A.rows norm = 0 for x in xrange(n): for y in xrange(min(x+2, n)): norm += ctx.re(A[y,x]) ** 2 + ctx.im(A[y,x]) ** 2 norm = ctx.sqrt(norm) / n if norm == 0: return n0 = 0 n1 = n eps = ctx.eps / (100 * n) maxits = ctx.dps * 4 its = totalits = 0 while 1: # kressner p.32 algo 3 # the active submatrix is A[n0:n1,n0:n1] k = n0 while k + 1 < n1: s = abs(ctx.re(A[k,k])) + abs(ctx.im(A[k,k])) + abs(ctx.re(A[k+1,k+1])) + abs(ctx.im(A[k+1,k+1])) if s < eps * norm: s = norm if abs(A[k+1,k]) < eps * s: break k += 1 if k + 1 < n1: # deflation found at position (k+1, k) A[k+1,k] = 0 n0 = k + 1 its = 0 if n0 + 1 >= n1: # block of size at most two has converged n0 = 0 n1 = k + 1 if n1 < 2: # QR algorithm has converged return else: if (its % 30) == 10: # exceptional shift shift = A[n1-1,n1-2] elif (its % 30) == 20: # exceptional shift shift = abs(A[n1-1,n1-2]) elif (its % 30) == 29: # exceptional shift shift = norm else: # A = [ a b ] det(x-A)=x*x-x*tr(A)+det(A) # [ c d ] # # eigenvalues bad: (tr(A)+sqrt((tr(A))**2-4*det(A)))/2 # bad because of cancellation if |c| is small and |a-d| is small, too. # # eigenvalues good: (a+d+sqrt((a-d)**2+4*b*c))/2 t = A[n1-2,n1-2] + A[n1-1,n1-1] s = (A[n1-1,n1-1] - A[n1-2,n1-2]) ** 2 + 4 * A[n1-1,n1-2] * A[n1-2,n1-1] if ctx.re(s) > 0: s = ctx.sqrt(s) else: s = ctx.sqrt(-s) * 1j a = (t + s) / 2 b = (t - s) / 2 if abs(A[n1-1,n1-1] - a) > abs(A[n1-1,n1-1] - b): shift = b else: shift = a its += 1 totalits += 1 qr_step(ctx, n0, n1, A, Q, shift) if its > maxits: raise RuntimeError("qr: failed to converge after %d steps" % its) @defun def schur(ctx, A, overwrite_a = False): """ This routine computes the Schur decomposition of a square matrix A. Given A, an unitary matrix Q is determined such that Q' A Q = R and Q' Q = Q Q' = 1 where R is an upper right triangular matrix. Here ' denotes the hermitian transpose (i.e. transposition and conjugation). input: A : a real or complex square matrix overwrite_a : if true, allows modification of A which may improve performance. if false, A is not modified. output: Q : an unitary matrix R : an upper right triangular matrix return value: (Q, R) example: >>> from mpmath import mp >>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]]) >>> Q, R = mp.schur(A) >>> mp.nprint(R, 3) # doctest:+SKIP [2.0 0.417 -2.53] [0.0 4.0 -4.74] [0.0 0.0 9.0] >>> print(mp.chop(A - Q * R * Q.transpose_conj())) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] warning: The Schur decomposition is not unique. """ n = A.rows if n == 1: return (ctx.matrix([[1]]), A) if not overwrite_a: A = A.copy() T = ctx.matrix(n, 1) hessenberg_reduce_0(ctx, A, T) Q = A.copy() hessenberg_reduce_1(ctx, Q, T) for x in xrange(n): for y in xrange(x + 2, n): A[y,x] = 0 hessenberg_qr(ctx, A, Q) return Q, A def eig_tr_r(ctx, A): """ This routine calculates the right eigenvectors of an upper right triangular matrix. input: A an upper right triangular matrix output: ER a matrix whose columns form the right eigenvectors of A return value: ER """ # this subroutine is inspired by the lapack routines ctrevc.f,clatrs.f n = A.rows ER = ctx.eye(n) eps = ctx.eps unfl = ctx.ldexp(ctx.one, -ctx.prec * 30) # since mpmath effectively has no limits on the exponent, we simply scale doubles up # original double has prec*20 smlnum = unfl * (n / eps) simin = 1 / ctx.sqrt(eps) rmax = 1 for i in xrange(1, n): s = A[i,i] smin = max(eps * abs(s), smlnum) for j in xrange(i - 1, -1, -1): r = 0 for k in xrange(j + 1, i + 1): r += A[j,k] * ER[k,i] t = A[j,j] - s if abs(t) < smin: t = smin r = -r / t ER[j,i] = r rmax = max(rmax, abs(r)) if rmax > simin: for k in xrange(j, i+1): ER[k,i] /= rmax rmax = 1 if rmax != 1: for k in xrange(0, i + 1): ER[k,i] /= rmax return ER def eig_tr_l(ctx, A): """ This routine calculates the left eigenvectors of an upper right triangular matrix. input: A an upper right triangular matrix output: EL a matrix whose rows form the left eigenvectors of A return value: EL """ n = A.rows EL = ctx.eye(n) eps = ctx.eps unfl = ctx.ldexp(ctx.one, -ctx.prec * 30) # since mpmath effectively has no limits on the exponent, we simply scale doubles up # original double has prec*20 smlnum = unfl * (n / eps) simin = 1 / ctx.sqrt(eps) rmax = 1 for i in xrange(0, n - 1): s = A[i,i] smin = max(eps * abs(s), smlnum) for j in xrange(i + 1, n): r = 0 for k in xrange(i, j): r += EL[i,k] * A[k,j] t = A[j,j] - s if abs(t) < smin: t = smin r = -r / t EL[i,j] = r rmax = max(rmax, abs(r)) if rmax > simin: for k in xrange(i, j + 1): EL[i,k] /= rmax rmax = 1 if rmax != 1: for k in xrange(i, n): EL[i,k] /= rmax return EL @defun def eig(ctx, A, left = False, right = True, overwrite_a = False): """ This routine computes the eigenvalues and optionally the left and right eigenvectors of a square matrix A. Given A, a vector E and matrices ER and EL are calculated such that A ER[:,i] = E[i] ER[:,i] EL[i,:] A = EL[i,:] E[i] E contains the eigenvalues of A. The columns of ER contain the right eigenvectors of A whereas the rows of EL contain the left eigenvectors. input: A : a real or complex square matrix of shape (n, n) left : if true, the left eigenvectors are calulated. right : if true, the right eigenvectors are calculated. overwrite_a : if true, allows modification of A which may improve performance. if false, A is not modified. output: E : a list of length n containing the eigenvalues of A. ER : a matrix whose columns contain the right eigenvectors of A. EL : a matrix whose rows contain the left eigenvectors of A. return values: E if left and right are both false. (E, ER) if right is true and left is false. (E, EL) if left is true and right is false. (E, EL, ER) if left and right are true. examples: >>> from mpmath import mp >>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]]) >>> E, ER = mp.eig(A) >>> print(mp.chop(A * ER[:,0] - E[0] * ER[:,0])) [0.0] [0.0] [0.0] >>> E, EL, ER = mp.eig(A,left = True, right = True) >>> E, EL, ER = mp.eig_sort(E, EL, ER) >>> mp.nprint(E) [2.0, 4.0, 9.0] >>> print(mp.chop(A * ER[:,0] - E[0] * ER[:,0])) [0.0] [0.0] [0.0] >>> print(mp.chop( EL[0,:] * A - EL[0,:] * E[0])) [0.0 0.0 0.0] warning: - If there are multiple eigenvalues, the eigenvectors do not necessarily span the whole vectorspace, i.e. ER and EL may have not full rank. Furthermore in that case the eigenvectors are numerical ill-conditioned. - In the general case the eigenvalues have no natural order. see also: - eigh (or eigsy, eighe) for the symmetric eigenvalue problem. - eig_sort for sorting of eigenvalues and eigenvectors """ n = A.rows if n == 1: if left and (not right): return ([A[0]], ctx.matrix([[1]])) if right and (not left): return ([A[0]], ctx.matrix([[1]])) return ([A[0]], ctx.matrix([[1]]), ctx.matrix([[1]])) if not overwrite_a: A = A.copy() T = ctx.zeros(n, 1) hessenberg_reduce_0(ctx, A, T) if left or right: Q = A.copy() hessenberg_reduce_1(ctx, Q, T) else: Q = False for x in xrange(n): for y in xrange(x + 2, n): A[y,x] = 0 hessenberg_qr(ctx, A, Q) E = [0 for i in xrange(n)] for i in xrange(n): E[i] = A[i,i] if not (left or right): return E if left: EL = eig_tr_l(ctx, A) EL = EL * Q.transpose_conj() if right: ER = eig_tr_r(ctx, A) ER = Q * ER if left and (not right): return (E, EL) if right and (not left): return (E, ER) return (E, EL, ER) @defun def eig_sort(ctx, E, EL = False, ER = False, f = "real"): """ This routine sorts the eigenvalues and eigenvectors delivered by ``eig``. parameters: E : the eigenvalues as delivered by eig EL : the left eigenvectors as delivered by eig, or false ER : the right eigenvectors as delivered by eig, or false f : either a string ("real" sort by increasing real part, "imag" sort by increasing imag part, "abs" sort by absolute value) or a function mapping complexs to the reals, i.e. ``f = lambda x: -mp.re(x) `` would sort the eigenvalues by decreasing real part. return values: E if EL and ER are both false. (E, ER) if ER is not false and left is false. (E, EL) if EL is not false and right is false. (E, EL, ER) if EL and ER are not false. example: >>> from mpmath import mp >>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]]) >>> E, EL, ER = mp.eig(A,left = True, right = True) >>> E, EL, ER = mp.eig_sort(E, EL, ER) >>> mp.nprint(E) [2.0, 4.0, 9.0] >>> E, EL, ER = mp.eig_sort(E, EL, ER,f = lambda x: -mp.re(x)) >>> mp.nprint(E) [9.0, 4.0, 2.0] >>> print(mp.chop(A * ER[:,0] - E[0] * ER[:,0])) [0.0] [0.0] [0.0] >>> print(mp.chop( EL[0,:] * A - EL[0,:] * E[0])) [0.0 0.0 0.0] """ if isinstance(f, str): if f == "real": f = ctx.re elif f == "imag": f = ctx.im elif cmp == "abs": f = abs else: raise RuntimeError("unknown function %s" % f) n = len(E) # Sort eigenvalues (bubble-sort) for i in xrange(n): imax = i s = f(E[i]) # s is the current maximal element for j in xrange(i + 1, n): c = f(E[j]) if c < s: s = c imax = j if imax != i: # swap eigenvalues z = E[i] E[i] = E[imax] E[imax] = z if not isinstance(EL, bool): for j in xrange(n): z = EL[i,j] EL[i,j] = EL[imax,j] EL[imax,j] = z if not isinstance(ER, bool): for j in xrange(n): z = ER[j,i] ER[j,i] = ER[j,imax] ER[j,imax] = z if isinstance(EL, bool) and isinstance(ER, bool): return E if isinstance(EL, bool) and not(isinstance(ER, bool)): return (E, ER) if isinstance(ER, bool) and not(isinstance(EL, bool)): return (E, EL) return (E, EL, ER) mpmath-1.1.0/mpmath/matrices/eigen_symmetric.py000066400000000000000000001622341340375245600216520ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- ################################################################################################## # module for the symmetric eigenvalue problem # Copyright 2013 Timo Hartmann (thartmann15 at gmail.com) # # todo: # - implement balancing # ################################################################################################## """ The symmetric eigenvalue problem. --------------------------------- This file contains routines for the symmetric eigenvalue problem. high level routines: eigsy : real symmetric (ordinary) eigenvalue problem eighe : complex hermitian (ordinary) eigenvalue problem eigh : unified interface for eigsy and eighe svd_r : singular value decomposition for real matrices svd_c : singular value decomposition for complex matrices svd : unified interface for svd_r and svd_c low level routines: r_sy_tridiag : reduction of real symmetric matrix to real symmetric tridiagonal matrix c_he_tridiag_0 : reduction of complex hermitian matrix to real symmetric tridiagonal matrix c_he_tridiag_1 : auxiliary routine to c_he_tridiag_0 c_he_tridiag_2 : auxiliary routine to c_he_tridiag_0 tridiag_eigen : solves the real symmetric tridiagonal matrix eigenvalue problem svd_r_raw : raw singular value decomposition for real matrices svd_c_raw : raw singular value decomposition for complex matrices """ from ..libmp.backend import xrange from .eigen import defun def r_sy_tridiag(ctx, A, D, E, calc_ev = True): """ This routine transforms a real symmetric matrix A to a real symmetric tridiagonal matrix T using an orthogonal similarity transformation: Q' * A * Q = T (here ' denotes the matrix transpose). The orthogonal matrix Q is build up from Householder reflectors. parameters: A (input/output) On input, A contains the real symmetric matrix of dimension (n,n). On output, if calc_ev is true, A contains the orthogonal matrix Q, otherwise A is destroyed. D (output) real array of length n, contains the diagonal elements of the tridiagonal matrix E (output) real array of length n, contains the offdiagonal elements of the tridiagonal matrix in E[0:(n-1)] where is the dimension of the matrix A. E[n-1] is undefined. calc_ev (input) If calc_ev is true, this routine explicitly calculates the orthogonal matrix Q which is then returned in A. If calc_ev is false, Q is not explicitly calculated resulting in a shorter run time. This routine is a python translation of the fortran routine tred2.f in the software library EISPACK (see netlib.org) which itself is based on the algol procedure tred2 described in: - Num. Math. 11, p.181-195 (1968) by Martin, Reinsch and Wilkonson - Handbook for auto. comp., Vol II, Linear Algebra, p.212-226 (1971) For a good introduction to Householder reflections, see also Stoer, Bulirsch - Introduction to Numerical Analysis. """ # note : the vector v of the i-th houshoulder reflector is stored in a[(i+1):,i] # whereas v/ is stored in a[i,(i+1):] n = A.rows for i in xrange(n - 1, 0, -1): # scale the vector scale = 0 for k in xrange(0, i): scale += abs(A[k,i]) scale_inv = 0 if scale != 0: scale_inv = 1/scale # sadly there are floating point numbers not equal to zero whose reciprocal is infinity if i == 1 or scale == 0 or ctx.isinf(scale_inv): E[i] = A[i-1,i] # nothing to do D[i] = 0 continue # calculate parameters for housholder transformation H = 0 for k in xrange(0, i): A[k,i] *= scale_inv H += A[k,i] * A[k,i] F = A[i-1,i] G = ctx.sqrt(H) if F > 0: G = -G E[i] = scale * G H -= F * G A[i-1,i] = F - G F = 0 # apply housholder transformation for j in xrange(0, i): if calc_ev: A[i,j] = A[j,i] / H G = 0 # calculate A*U for k in xrange(0, j + 1): G += A[k,j] * A[k,i] for k in xrange(j + 1, i): G += A[j,k] * A[k,i] E[j] = G / H # calculate P F += E[j] * A[j,i] HH = F / (2 * H) for j in xrange(0, i): # calculate reduced A F = A[j,i] G = E[j] - HH * F # calculate Q E[j] = G for k in xrange(0, j + 1): A[k,j] -= F * E[k] + G * A[k,i] D[i] = H for i in xrange(1, n): # better for compatibility E[i-1] = E[i] E[n-1] = 0 if calc_ev: D[0] = 0 for i in xrange(0, n): if D[i] != 0: for j in xrange(0, i): # accumulate transformation matrices G = 0 for k in xrange(0, i): G += A[i,k] * A[k,j] for k in xrange(0, i): A[k,j] -= G * A[k,i] D[i] = A[i,i] A[i,i] = 1 for j in xrange(0, i): A[j,i] = A[i,j] = 0 else: for i in xrange(0, n): D[i] = A[i,i] def c_he_tridiag_0(ctx, A, D, E, T): """ This routine transforms a complex hermitian matrix A to a real symmetric tridiagonal matrix T using an unitary similarity transformation: Q' * A * Q = T (here ' denotes the hermitian matrix transpose, i.e. transposition und conjugation). The unitary matrix Q is build up from Householder reflectors and an unitary diagonal matrix. parameters: A (input/output) On input, A contains the complex hermitian matrix of dimension (n,n). On output, A contains the unitary matrix Q in compressed form. D (output) real array of length n, contains the diagonal elements of the tridiagonal matrix. E (output) real array of length n, contains the offdiagonal elements of the tridiagonal matrix in E[0:(n-1)] where is the dimension of the matrix A. E[n-1] is undefined. T (output) complex array of length n, contains a unitary diagonal matrix. This routine is a python translation (in slightly modified form) of the fortran routine htridi.f in the software library EISPACK (see netlib.org) which itself is a complex version of the algol procedure tred1 described in: - Num. Math. 11, p.181-195 (1968) by Martin, Reinsch and Wilkonson - Handbook for auto. comp., Vol II, Linear Algebra, p.212-226 (1971) For a good introduction to Householder reflections, see also Stoer, Bulirsch - Introduction to Numerical Analysis. """ n = A.rows T[n-1] = 1 for i in xrange(n - 1, 0, -1): # scale the vector scale = 0 for k in xrange(0, i): scale += abs(ctx.re(A[k,i])) + abs(ctx.im(A[k,i])) scale_inv = 0 if scale != 0: scale_inv = 1 / scale # sadly there are floating point numbers not equal to zero whose reciprocal is infinity if scale == 0 or ctx.isinf(scale_inv): E[i] = 0 D[i] = 0 T[i-1] = 1 continue if i == 1: F = A[i-1,i] f = abs(F) E[i] = f D[i] = 0 if f != 0: T[i-1] = T[i] * F / f else: T[i-1] = T[i] continue # calculate parameters for housholder transformation H = 0 for k in xrange(0, i): A[k,i] *= scale_inv rr = ctx.re(A[k,i]) ii = ctx.im(A[k,i]) H += rr * rr + ii * ii F = A[i-1,i] f = abs(F) G = ctx.sqrt(H) H += G * f E[i] = scale * G if f != 0: F = F / f TZ = - T[i] * F # T[i-1]=-T[i]*F, but we need T[i-1] as temporary storage G *= F else: TZ = -T[i] # T[i-1]=-T[i] A[i-1,i] += G F = 0 # apply housholder transformation for j in xrange(0, i): A[i,j] = A[j,i] / H G = 0 # calculate A*U for k in xrange(0, j + 1): G += ctx.conj(A[k,j]) * A[k,i] for k in xrange(j + 1, i): G += A[j,k] * A[k,i] T[j] = G / H # calculate P F += ctx.conj(T[j]) * A[j,i] HH = F / (2 * H) for j in xrange(0, i): # calculate reduced A F = A[j,i] G = T[j] - HH * F # calculate Q T[j] = G for k in xrange(0, j + 1): A[k,j] -= ctx.conj(F) * T[k] + ctx.conj(G) * A[k,i] # as we use the lower left part for storage # we have to use the transpose of the normal formula T[i-1] = TZ D[i] = H for i in xrange(1, n): # better for compatibility E[i-1] = E[i] E[n-1] = 0 D[0] = 0 for i in xrange(0, n): zw = D[i] D[i] = ctx.re(A[i,i]) A[i,i] = zw def c_he_tridiag_1(ctx, A, T): """ This routine forms the unitary matrix Q described in c_he_tridiag_0. parameters: A (input/output) On input, A is the same matrix as delivered by c_he_tridiag_0. On output, A is set to Q. T (input) On input, T is the same array as delivered by c_he_tridiag_0. """ n = A.rows for i in xrange(0, n): if A[i,i] != 0: for j in xrange(0, i): G = 0 for k in xrange(0, i): G += ctx.conj(A[i,k]) * A[k,j] for k in xrange(0, i): A[k,j] -= G * A[k,i] A[i,i] = 1 for j in xrange(0, i): A[j,i] = A[i,j] = 0 for i in xrange(0, n): for k in xrange(0, n): A[i,k] *= T[k] def c_he_tridiag_2(ctx, A, T, B): """ This routine applied the unitary matrix Q described in c_he_tridiag_0 onto the the matrix B, i.e. it forms Q*B. parameters: A (input) On input, A is the same matrix as delivered by c_he_tridiag_0. T (input) On input, T is the same array as delivered by c_he_tridiag_0. B (input/output) On input, B is a complex matrix. On output B is replaced by Q*B. This routine is a python translation of the fortran routine htribk.f in the software library EISPACK (see netlib.org). See c_he_tridiag_0 for more references. """ n = A.rows for i in xrange(0, n): for k in xrange(0, n): B[k,i] *= T[k] for i in xrange(0, n): if A[i,i] != 0: for j in xrange(0, n): G = 0 for k in xrange(0, i): G += ctx.conj(A[i,k]) * B[k,j] for k in xrange(0, i): B[k,j] -= G * A[k,i] def tridiag_eigen(ctx, d, e, z = False): """ This subroutine find the eigenvalues and the first components of the eigenvectors of a real symmetric tridiagonal matrix using the implicit QL method. parameters: d (input/output) real array of length n. on input, d contains the diagonal elements of the input matrix. on output, d contains the eigenvalues in ascending order. e (input) real array of length n. on input, e contains the offdiagonal elements of the input matrix in e[0:(n-1)]. On output, e has been destroyed. z (input/output) If z is equal to False, no eigenvectors will be computed. Otherwise on input z should have the format z[0:m,0:n] (i.e. a real or complex matrix of dimension (m,n) ). On output this matrix will be multiplied by the matrix of the eigenvectors (i.e. the columns of this matrix are the eigenvectors): z --> z*EV That means if z[i,j]={1 if j==j; 0 otherwise} on input, then on output z will contain the first m components of the eigenvectors. That means if m is equal to n, the i-th eigenvector will be z[:,i]. This routine is a python translation (in slightly modified form) of the fortran routine imtql2.f in the software library EISPACK (see netlib.org) which itself is based on the algol procudure imtql2 desribed in: - num. math. 12, p. 377-383(1968) by matrin and wilkinson - modified in num. math. 15, p. 450(1970) by dubrulle - handbook for auto. comp., vol. II-linear algebra, p. 241-248 (1971) See also the routine gaussq.f in netlog.org or acm algorithm 726. """ n = len(d) e[n-1] = 0 iterlim = 2 * ctx.dps for l in xrange(n): j = 0 while 1: m = l while 1: # look for a small subdiagonal element if m + 1 == n: break if abs(e[m]) <= ctx.eps * (abs(d[m]) + abs(d[m + 1])): break m = m + 1 if m == l: break if j >= iterlim: raise RuntimeError("tridiag_eigen: no convergence to an eigenvalue after %d iterations" % iterlim) j += 1 # form shift p = d[l] g = (d[l + 1] - p) / (2 * e[l]) r = ctx.hypot(g, 1) if g < 0: s = g - r else: s = g + r g = d[m] - p + e[l] / s s, c, p = 1, 1, 0 for i in xrange(m - 1, l - 1, -1): f = s * e[i] b = c * e[i] if abs(f) > abs(g): # this here is a slight improvement also used in gaussq.f or acm algorithm 726. c = g / f r = ctx.hypot(c, 1) e[i + 1] = f * r s = 1 / r c = c * s else: s = f / g r = ctx.hypot(s, 1) e[i + 1] = g * r c = 1 / r s = s * c g = d[i + 1] - p r = (d[i] - g) * s + 2 * c * b p = s * r d[i + 1] = g + p g = c * r - b if not isinstance(z, bool): # calculate eigenvectors for w in xrange(z.rows): f = z[w,i+1] z[w,i+1] = s * z[w,i] + c * f z[w,i ] = c * z[w,i] - s * f d[l] = d[l] - p e[l] = g e[m] = 0 for ii in xrange(1, n): # sort eigenvalues and eigenvectors (bubble-sort) i = ii - 1 k = i p = d[i] for j in xrange(ii, n): if d[j] >= p: continue k = j p = d[k] if k == i: continue d[k] = d[i] d[i] = p if not isinstance(z, bool): for w in xrange(z.rows): p = z[w,i] z[w,i] = z[w,k] z[w,k] = p ######################################################################################## @defun def eigsy(ctx, A, eigvals_only = False, overwrite_a = False): """ This routine solves the (ordinary) eigenvalue problem for a real symmetric square matrix A. Given A, an orthogonal matrix Q is calculated which diagonalizes A: Q' A Q = diag(E) and Q Q' = Q' Q = 1 Here diag(E) is a diagonal matrix whose diagonal is E. ' denotes the transpose. The columns of Q are the eigenvectors of A and E contains the eigenvalues: A Q[:,i] = E[i] Q[:,i] input: A: real matrix of format (n,n) which is symmetric (i.e. A=A' or A[i,j]=A[j,i]) eigvals_only: if true, calculates only the eigenvalues E. if false, calculates both eigenvectors and eigenvalues. overwrite_a: if true, allows modification of A which may improve performance. if false, A is not modified. output: E: vector of format (n). contains the eigenvalues of A in ascending order. Q: orthogonal matrix of format (n,n). contains the eigenvectors of A as columns. return value: E if eigvals_only is true (E, Q) if eigvals_only is false example: >>> from mpmath import mp >>> A = mp.matrix([[3, 2], [2, 0]]) >>> E = mp.eigsy(A, eigvals_only = True) >>> print(E) [-1.0] [ 4.0] >>> A = mp.matrix([[1, 2], [2, 3]]) >>> E, Q = mp.eigsy(A) >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0])) [0.0] [0.0] see also: eighe, eigh, eig """ if not overwrite_a: A = A.copy() d = ctx.zeros(A.rows, 1) e = ctx.zeros(A.rows, 1) if eigvals_only: r_sy_tridiag(ctx, A, d, e, calc_ev = False) tridiag_eigen(ctx, d, e, False) return d else: r_sy_tridiag(ctx, A, d, e, calc_ev = True) tridiag_eigen(ctx, d, e, A) return (d, A) @defun def eighe(ctx, A, eigvals_only = False, overwrite_a = False): """ This routine solves the (ordinary) eigenvalue problem for a complex hermitian square matrix A. Given A, an unitary matrix Q is calculated which diagonalizes A: Q' A Q = diag(E) and Q Q' = Q' Q = 1 Here diag(E) a is diagonal matrix whose diagonal is E. ' denotes the hermitian transpose (i.e. ordinary transposition and complex conjugation). The columns of Q are the eigenvectors of A and E contains the eigenvalues: A Q[:,i] = E[i] Q[:,i] input: A: complex matrix of format (n,n) which is hermitian (i.e. A=A' or A[i,j]=conj(A[j,i])) eigvals_only: if true, calculates only the eigenvalues E. if false, calculates both eigenvectors and eigenvalues. overwrite_a: if true, allows modification of A which may improve performance. if false, A is not modified. output: E: vector of format (n). contains the eigenvalues of A in ascending order. Q: unitary matrix of format (n,n). contains the eigenvectors of A as columns. return value: E if eigvals_only is true (E, Q) if eigvals_only is false example: >>> from mpmath import mp >>> A = mp.matrix([[1, -3 - 1j], [-3 + 1j, -2]]) >>> E = mp.eighe(A, eigvals_only = True) >>> print(E) [-4.0] [ 3.0] >>> A = mp.matrix([[1, 2 + 5j], [2 - 5j, 3]]) >>> E, Q = mp.eighe(A) >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0])) [0.0] [0.0] see also: eigsy, eigh, eig """ if not overwrite_a: A = A.copy() d = ctx.zeros(A.rows, 1) e = ctx.zeros(A.rows, 1) t = ctx.zeros(A.rows, 1) if eigvals_only: c_he_tridiag_0(ctx, A, d, e, t) tridiag_eigen(ctx, d, e, False) return d else: c_he_tridiag_0(ctx, A, d, e, t) B = ctx.eye(A.rows) tridiag_eigen(ctx, d, e, B) c_he_tridiag_2(ctx, A, t, B) return (d, B) @defun def eigh(ctx, A, eigvals_only = False, overwrite_a = False): """ "eigh" is a unified interface for "eigsy" and "eighe". Depending on whether A is real or complex the appropriate function is called. This routine solves the (ordinary) eigenvalue problem for a real symmetric or complex hermitian square matrix A. Given A, an orthogonal (A real) or unitary (A complex) matrix Q is calculated which diagonalizes A: Q' A Q = diag(E) and Q Q' = Q' Q = 1 Here diag(E) a is diagonal matrix whose diagonal is E. ' denotes the hermitian transpose (i.e. ordinary transposition and complex conjugation). The columns of Q are the eigenvectors of A and E contains the eigenvalues: A Q[:,i] = E[i] Q[:,i] input: A: a real or complex square matrix of format (n,n) which is symmetric (i.e. A[i,j]=A[j,i]) or hermitian (i.e. A[i,j]=conj(A[j,i])). eigvals_only: if true, calculates only the eigenvalues E. if false, calculates both eigenvectors and eigenvalues. overwrite_a: if true, allows modification of A which may improve performance. if false, A is not modified. output: E: vector of format (n). contains the eigenvalues of A in ascending order. Q: an orthogonal or unitary matrix of format (n,n). contains the eigenvectors of A as columns. return value: E if eigvals_only is true (E, Q) if eigvals_only is false example: >>> from mpmath import mp >>> A = mp.matrix([[3, 2], [2, 0]]) >>> E = mp.eigh(A, eigvals_only = True) >>> print(E) [-1.0] [ 4.0] >>> A = mp.matrix([[1, 2], [2, 3]]) >>> E, Q = mp.eigh(A) >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0])) [0.0] [0.0] >>> A = mp.matrix([[1, 2 + 5j], [2 - 5j, 3]]) >>> E, Q = mp.eigh(A) >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0])) [0.0] [0.0] see also: eigsy, eighe, eig """ iscomplex = any(type(x) is ctx.mpc for x in A) if iscomplex: return ctx.eighe(A, eigvals_only = eigvals_only, overwrite_a = overwrite_a) else: return ctx.eigsy(A, eigvals_only = eigvals_only, overwrite_a = overwrite_a) @defun def gauss_quadrature(ctx, n, qtype = "legendre", alpha = 0, beta = 0): """ This routine calulates gaussian quadrature rules for different families of orthogonal polynomials. Let (a, b) be an interval, W(x) a positive weight function and n a positive integer. Then the purpose of this routine is to calculate pairs (x_k, w_k) for k=0, 1, 2, ... (n-1) which give int(W(x) * F(x), x = a..b) = sum(w_k * F(x_k),k = 0..(n-1)) exact for all polynomials F(x) of degree (strictly) less than 2*n. For all integrable functions F(x) the sum is a (more or less) good approximation to the integral. The x_k are called nodes (which are the zeros of the related orthogonal polynomials) and the w_k are called the weights. parameters n (input) The degree of the quadrature rule, i.e. its number of nodes. qtype (input) The family of orthogonal polynmomials for which to compute the quadrature rule. See the list below. alpha (input) real number, used as parameter for some orthogonal polynomials beta (input) real number, used as parameter for some orthogonal polynomials. return value (X, W) a pair of two real arrays where x_k = X[k] and w_k = W[k]. orthogonal polynomials: qtype polynomial ----- ---------- "legendre" Legendre polynomials, W(x)=1 on the interval (-1, +1) "legendre01" shifted Legendre polynomials, W(x)=1 on the interval (0, +1) "hermite" Hermite polynomials, W(x)=exp(-x*x) on (-infinity,+infinity) "laguerre" Laguerre polynomials, W(x)=exp(-x) on (0,+infinity) "glaguerre" generalized Laguerre polynomials, W(x)=exp(-x)*x**alpha on (0, +infinity) "chebyshev1" Chebyshev polynomials of the first kind, W(x)=1/sqrt(1-x*x) on (-1, +1) "chebyshev2" Chebyshev polynomials of the second kind, W(x)=sqrt(1-x*x) on (-1, +1) "jacobi" Jacobi polynomials, W(x)=(1-x)**alpha * (1+x)**beta on (-1, +1) with alpha>-1 and beta>-1 examples: >>> from mpmath import mp >>> f = lambda x: x**8 + 2 * x**6 - 3 * x**4 + 5 * x**2 - 7 >>> X, W = mp.gauss_quadrature(5, "hermite") >>> A = mp.fdot([(f(x), w) for x, w in zip(X, W)]) >>> B = mp.sqrt(mp.pi) * 57 / 16 >>> C = mp.quad(lambda x: mp.exp(- x * x) * f(x), [-mp.inf, +mp.inf]) >>> print mp.chop(A-B, tol = 1e-10), mp.chop(A-C, tol = 1e-10) 0.0 0.0 >>> f = lambda x: x**5 - 2 * x**4 + 3 * x**3 - 5 * x**2 + 7 * x - 11 >>> X, W = mp.gauss_quadrature(3, "laguerre") >>> A = mp.fdot([(f(x), w) for x, w in zip(X, W)]) >>> B = 76 >>> C = mp.quad(lambda x: mp.exp(-x) * f(x), [0, +mp.inf]) >>> print mp.chop(A-B, tol = 1e-10), mp.chop(A-C, tol = 1e-10) 0.0 0.0 # orthogonality of the chebyshev polynomials: >>> f = lambda x: mp.chebyt(3, x) * mp.chebyt(2, x) >>> X, W = mp.gauss_quadrature(3, "chebyshev1") >>> A = mp.fdot([(f(x), w) for x, w in zip(X, W)]) >>> print(mp.chop(A, tol = 1e-10)) 0.0 references: - golub and welsch, "calculations of gaussian quadrature rules", mathematics of computation 23, p. 221-230 (1969) - golub, "some modified matrix eigenvalue problems", siam review 15, p. 318-334 (1973) - stroud and secrest, "gaussian quadrature formulas", prentice-hall (1966) See also the routine gaussq.f in netlog.org or ACM Transactions on Mathematical Software algorithm 726. """ d = ctx.zeros(n, 1) e = ctx.zeros(n, 1) z = ctx.zeros(1, n) z[0,0] = 1 if qtype == "legendre": # legendre on the range -1 +1 , abramowitz, table 25.4, p.916 w = 2 for i in xrange(n): j = i + 1 e[i] = ctx.sqrt(j * j / (4 * j * j - ctx.mpf(1))) elif qtype == "legendre01": # legendre shifted to 0 1 , abramowitz, table 25.8, p.921 w = 1 for i in xrange(n): d[i] = 1 / ctx.mpf(2) j = i + 1 e[i] = ctx.sqrt(j * j / (16 * j * j - ctx.mpf(4))) elif qtype == "hermite": # hermite on the range -inf +inf , abramowitz, table 25.10,p.924 w = ctx.sqrt(ctx.pi) for i in xrange(n): j = i + 1 e[i] = ctx.sqrt(j / ctx.mpf(2)) elif qtype == "laguerre": # laguerre on the range 0 +inf , abramowitz, table 25.9, p. 923 w = 1 for i in xrange(n): j = i + 1 d[i] = 2 * j - 1 e[i] = j elif qtype=="chebyshev1": # chebyshev polynimials of the first kind w = ctx.pi for i in xrange(n): e[i] = 1 / ctx.mpf(2) e[0] = ctx.sqrt(1 / ctx.mpf(2)) elif qtype == "chebyshev2": # chebyshev polynimials of the second kind w = ctx.pi / 2 for i in xrange(n): e[i] = 1 / ctx.mpf(2) elif qtype == "glaguerre": # generalized laguerre on the range 0 +inf w = ctx.gamma(1 + alpha) for i in xrange(n): j = i + 1 d[i] = 2 * j - 1 + alpha e[i] = ctx.sqrt(j * (j + alpha)) elif qtype == "jacobi": # jacobi polynomials alpha = ctx.mpf(alpha) beta = ctx.mpf(beta) ab = alpha + beta abi = ab + 2 w = (2**(ab+1)) * ctx.gamma(alpha + 1) * ctx.gamma(beta + 1) / ctx.gamma(abi) d[0] = (beta - alpha) / abi e[0] = ctx.sqrt(4 * (1 + alpha) * (1 + beta) / ((abi + 1) * (abi * abi))) a2b2 = beta * beta - alpha * alpha for i in xrange(1, n): j = i + 1 abi = 2 * j + ab d[i] = a2b2 / ((abi - 2) * abi) e[i] = ctx.sqrt(4 * j * (j + alpha) * (j + beta) * (j + ab) / ((abi * abi - 1) * abi * abi)) elif isinstance(qtype, str): raise ValueError("unknown quadrature rule \"%s\"" % qtype) elif not isinstance(qtype, str): w = qtype(d, e) else: assert 0 tridiag_eigen(ctx, d, e, z) for i in xrange(len(z)): z[i] *= z[i] z = z.transpose() return (d, w * z) ################################################################################################## ################################################################################################## ################################################################################################## def svd_r_raw(ctx, A, V = False, calc_u = False): """ This routine computes the singular value decomposition of a matrix A. Given A, two orthogonal matrices U and V are calculated such that A = U S V where S is a suitable shaped matrix whose off-diagonal elements are zero. The diagonal elements of S are the singular values of A, i.e. the squareroots of the eigenvalues of A' A or A A'. Here ' denotes the transpose. Householder bidiagonalization and a variant of the QR algorithm is used. overview of the matrices : A : m*n A gets replaced by U U : m*n U replaces A. If n>m then only the first m*m block of U is non-zero. column-orthogonal: U' U = B here B is a n*n matrix whose first min(m,n) diagonal elements are 1 and all other elements are zero. S : n*n diagonal matrix, only the diagonal elements are stored in the array S. only the first min(m,n) diagonal elements are non-zero. V : n*n orthogonal: V V' = V' V = 1 parameters: A (input/output) On input, A contains a real matrix of shape m*n. On output, if calc_u is true A contains the column-orthogonal matrix U; otherwise A is simply used as workspace and thus destroyed. V (input/output) if false, the matrix V is not calculated. otherwise V must be a matrix of shape n*n. calc_u (input) If true, the matrix U is calculated and replaces A. if false, U is not calculated and A is simply destroyed return value: S an array of length n containing the singular values of A sorted by decreasing magnitude. only the first min(m,n) elements are non-zero. This routine is a python translation of the fortran routine svd.f in the software library EISPACK (see netlib.org) which itself is based on the algol procedure svd described in: - num. math. 14, 403-420(1970) by golub and reinsch. - wilkinson/reinsch: handbook for auto. comp., vol ii-linear algebra, 134-151(1971). """ m, n = A.rows, A.cols S = ctx.zeros(n, 1) # work is a temporary array of size n work = ctx.zeros(n, 1) g = scale = anorm = 0 maxits = 3 * ctx.dps for i in xrange(n): # householder reduction to bidiagonal form work[i] = scale*g g = s = scale = 0 if i < m: for k in xrange(i, m): scale += ctx.fabs(A[k,i]) if scale != 0: for k in xrange(i, m): A[k,i] /= scale s += A[k,i] * A[k,i] f = A[i,i] g = -ctx.sqrt(s) if f < 0: g = -g h = f * g - s A[i,i] = f - g for j in xrange(i+1, n): s = 0 for k in xrange(i, m): s += A[k,i] * A[k,j] f = s / h for k in xrange(i, m): A[k,j] += f * A[k,i] for k in xrange(i,m): A[k,i] *= scale S[i] = scale * g g = s = scale = 0 if i < m and i != n - 1: for k in xrange(i+1, n): scale += ctx.fabs(A[i,k]) if scale: for k in xrange(i+1, n): A[i,k] /= scale s += A[i,k] * A[i,k] f = A[i,i+1] g = -ctx.sqrt(s) if f < 0: g = -g h = f * g - s A[i,i+1] = f - g for k in xrange(i+1, n): work[k] = A[i,k] / h for j in xrange(i+1, m): s = 0 for k in xrange(i+1, n): s += A[j,k] * A[i,k] for k in xrange(i+1, n): A[j,k] += s * work[k] for k in xrange(i+1, n): A[i,k] *= scale anorm = max(anorm, ctx.fabs(S[i]) + ctx.fabs(work[i])) if not isinstance(V, bool): for i in xrange(n-2, -1, -1): # accumulation of right hand transformations V[i+1,i+1] = 1 if work[i+1] != 0: for j in xrange(i+1, n): V[i,j] = (A[i,j] / A[i,i+1]) / work[i+1] for j in xrange(i+1, n): s = 0 for k in xrange(i+1, n): s += A[i,k] * V[j,k] for k in xrange(i+1, n): V[j,k] += s * V[i,k] for j in xrange(i+1, n): V[j,i] = V[i,j] = 0 V[0,0] = 1 if m= maxits: raise RuntimeError("svd: no convergence to an eigenvalue after %d iterations" % its) x = S[l] # shift from bottom 2 by 2 minor nm = k-1 y = S[nm] g = work[nm] h = work[k] f = ((y - z) * (y + z) + (g - h) * (g + h))/(2 * h * y) g = ctx.hypot(f, 1) if f >= 0: f = ((x - z) * (x + z) + h * ((y / (f + g)) - h)) / x else: f = ((x - z) * (x + z) + h * ((y / (f - g)) - h)) / x c = s = 1 # next qt transformation for j in xrange(l, nm + 1): g = work[j+1] y = S[j+1] h = s * g g = c * g z = ctx.hypot(f, h) work[j] = z c = f / z s = h / z f = x * c + g * s g = g * c - x * s h = y * s y *= c if not isinstance(V, bool): for jj in xrange(n): x = V[j ,jj] z = V[j+1,jj] V[j ,jj]= x * c + z * s V[j+1 ,jj]= z * c - x * s z = ctx.hypot(f, h) S[j] = z if z != 0: # rotation can be arbitray if z=0 z = 1 / z c = f * z s = h * z f = c * g + s * y x = c * y - s * g if calc_u: for jj in xrange(m): y = A[jj,j ] z = A[jj,j+1] A[jj,j ] = y * c + z * s A[jj,j+1 ] = z * c - y * s work[l] = 0 work[k] = f S[k] = x ########################## # Sort singular values into decreasing order (bubble-sort) for i in xrange(n): imax = i s = ctx.fabs(S[i]) # s is the current maximal element for j in xrange(i + 1, n): c = ctx.fabs(S[j]) if c > s: s = c imax = j if imax != i: # swap singular values z = S[i] S[i] = S[imax] S[imax] = z if calc_u: for j in xrange(m): z = A[j,i] A[j,i] = A[j,imax] A[j,imax] = z if not isinstance(V, bool): for j in xrange(n): z = V[i,j] V[i,j] = V[imax,j] V[imax,j] = z return S ####################### def svd_c_raw(ctx, A, V = False, calc_u = False): """ This routine computes the singular value decomposition of a matrix A. Given A, two unitary matrices U and V are calculated such that A = U S V where S is a suitable shaped matrix whose off-diagonal elements are zero. The diagonal elements of S are the singular values of A, i.e. the squareroots of the eigenvalues of A' A or A A'. Here ' denotes the hermitian transpose (i.e. transposition and conjugation). Householder bidiagonalization and a variant of the QR algorithm is used. overview of the matrices : A : m*n A gets replaced by U U : m*n U replaces A. If n>m then only the first m*m block of U is non-zero. column-unitary: U' U = B here B is a n*n matrix whose first min(m,n) diagonal elements are 1 and all other elements are zero. S : n*n diagonal matrix, only the diagonal elements are stored in the array S. only the first min(m,n) diagonal elements are non-zero. V : n*n unitary: V V' = V' V = 1 parameters: A (input/output) On input, A contains a complex matrix of shape m*n. On output, if calc_u is true A contains the column-unitary matrix U; otherwise A is simply used as workspace and thus destroyed. V (input/output) if false, the matrix V is not calculated. otherwise V must be a matrix of shape n*n. calc_u (input) If true, the matrix U is calculated and replaces A. if false, U is not calculated and A is simply destroyed return value: S an array of length n containing the singular values of A sorted by decreasing magnitude. only the first min(m,n) elements are non-zero. This routine is a python translation of the fortran routine svd.f in the software library EISPACK (see netlib.org) which itself is based on the algol procedure svd described in: - num. math. 14, 403-420(1970) by golub and reinsch. - wilkinson/reinsch: handbook for auto. comp., vol ii-linear algebra, 134-151(1971). """ m, n = A.rows, A.cols S = ctx.zeros(n, 1) # work is a temporary array of size n work = ctx.zeros(n, 1) lbeta = ctx.zeros(n, 1) rbeta = ctx.zeros(n, 1) dwork = ctx.zeros(n, 1) g = scale = anorm = 0 maxits = 3 * ctx.dps for i in xrange(n): # householder reduction to bidiagonal form dwork[i] = scale * g # dwork are the side-diagonal elements g = s = scale = 0 if i < m: for k in xrange(i, m): scale += ctx.fabs(ctx.re(A[k,i])) + ctx.fabs(ctx.im(A[k,i])) if scale != 0: for k in xrange(i, m): A[k,i] /= scale ar = ctx.re(A[k,i]) ai = ctx.im(A[k,i]) s += ar * ar + ai * ai f = A[i,i] g = -ctx.sqrt(s) if ctx.re(f) < 0: beta = -g - ctx.conj(f) g = -g else: beta = -g + ctx.conj(f) beta /= ctx.conj(beta) beta += 1 h = 2 * (ctx.re(f) * g - s) A[i,i] = f - g beta /= h lbeta[i] = (beta / scale) / scale for j in xrange(i+1, n): s = 0 for k in xrange(i, m): s += ctx.conj(A[k,i]) * A[k,j] f = beta * s for k in xrange(i, m): A[k,j] += f * A[k,i] for k in xrange(i, m): A[k,i] *= scale S[i] = scale * g # S are the diagonal elements g = s = scale = 0 if i < m and i != n - 1: for k in xrange(i+1, n): scale += ctx.fabs(ctx.re(A[i,k])) + ctx.fabs(ctx.im(A[i,k])) if scale: for k in xrange(i+1, n): A[i,k] /= scale ar = ctx.re(A[i,k]) ai = ctx.im(A[i,k]) s += ar * ar + ai * ai f = A[i,i+1] g = -ctx.sqrt(s) if ctx.re(f) < 0: beta = -g - ctx.conj(f) g = -g else: beta = -g + ctx.conj(f) beta /= ctx.conj(beta) beta += 1 h = 2 * (ctx.re(f) * g - s) A[i,i+1] = f - g beta /= h rbeta[i] = (beta / scale) / scale for k in xrange(i+1, n): work[k] = A[i, k] for j in xrange(i+1, m): s = 0 for k in xrange(i+1, n): s += ctx.conj(A[i,k]) * A[j,k] f = s * beta for k in xrange(i+1,n): A[j,k] += f * work[k] for k in xrange(i+1, n): A[i,k] *= scale anorm = max(anorm,ctx.fabs(S[i]) + ctx.fabs(dwork[i])) if not isinstance(V, bool): for i in xrange(n-2, -1, -1): # accumulation of right hand transformations V[i+1,i+1] = 1 if dwork[i+1] != 0: f = ctx.conj(rbeta[i]) for j in xrange(i+1, n): V[i,j] = A[i,j] * f for j in xrange(i+1, n): s = 0 for k in xrange(i+1, n): s += ctx.conj(A[i,k]) * V[j,k] for k in xrange(i+1, n): V[j,k] += s * V[i,k] for j in xrange(i+1,n): V[j,i] = V[i,j] = 0 V[0,0] = 1 if m < n : minnm = m else : minnm = n if calc_u: for i in xrange(minnm-1, -1, -1): # accumulation of left hand transformations g = S[i] for j in xrange(i+1, n): A[i,j] = 0 if g != 0: g = 1 / g for j in xrange(i+1, n): s = 0 for k in xrange(i+1, m): s += ctx.conj(A[k,i]) * A[k,j] f = s * ctx.conj(lbeta[i]) for k in xrange(i, m): A[k,j] += f * A[k,i] for j in xrange(i, m): A[j,i] *= g else: for j in xrange(i, m): A[j,i] = 0 A[i,i] += 1 for k in xrange(n-1, -1, -1): # diagonalization of the bidiagonal form: # loop over singular values, and over allowed itations its = 0 while 1: its += 1 flag = True for l in xrange(k, -1, -1): nm = l - 1 if ctx.fabs(dwork[l]) + anorm == anorm: flag = False break if ctx.fabs(S[nm]) + anorm == anorm: break if flag: c = 0 s = 1 for i in xrange(l, k+1): f = s * dwork[i] dwork[i] *= c if ctx.fabs(f) + anorm == anorm: break g = S[i] h = ctx.hypot(f, g) S[i] = h h = 1 / h c = g * h s = -f * h if calc_u: for j in xrange(m): y = A[j,nm] z = A[j,i] A[j,nm]= y * c + z * s A[j,i] = z * c - y * s z = S[k] if l == k: # convergence if z < 0: # singular value is made nonnegative S[k] = -z if not isinstance(V, bool): for j in xrange(n): V[k,j] = -V[k,j] break if its >= maxits: raise RuntimeError("svd: no convergence to an eigenvalue after %d iterations" % its) x = S[l] # shift from bottom 2 by 2 minor nm = k-1 y = S[nm] g = dwork[nm] h = dwork[k] f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2 * h * y) g = ctx.hypot(f, 1) if f >=0: f = (( x - z) *( x + z) + h *((y / (f + g)) - h)) / x else: f = (( x - z) *( x + z) + h *((y / (f - g)) - h)) / x c = s = 1 # next qt transformation for j in xrange(l, nm + 1): g = dwork[j+1] y = S[j+1] h = s * g g = c * g z = ctx.hypot(f, h) dwork[j] = z c = f / z s = h / z f = x * c + g * s g = g * c - x * s h = y * s y *= c if not isinstance(V, bool): for jj in xrange(n): x = V[j ,jj] z = V[j+1,jj] V[j ,jj]= x * c + z * s V[j+1,jj ]= z * c - x * s z = ctx.hypot(f, h) S[j] = z if z != 0: # rotation can be arbitray if z=0 z = 1 / z c = f * z s = h * z f = c * g + s * y x = c * y - s * g if calc_u: for jj in xrange(m): y = A[jj,j ] z = A[jj,j+1] A[jj,j ]= y * c + z * s A[jj,j+1 ]= z * c - y * s dwork[l] = 0 dwork[k] = f S[k] = x ########################## # Sort singular values into decreasing order (bubble-sort) for i in xrange(n): imax = i s = ctx.fabs(S[i]) # s is the current maximal element for j in xrange(i + 1, n): c = ctx.fabs(S[j]) if c > s: s = c imax = j if imax != i: # swap singular values z = S[i] S[i] = S[imax] S[imax] = z if calc_u: for j in xrange(m): z = A[j,i] A[j,i] = A[j,imax] A[j,imax] = z if not isinstance(V, bool): for j in xrange(n): z = V[i,j] V[i,j] = V[imax,j] V[imax,j] = z return S ################################################################################################## @defun def svd_r(ctx, A, full_matrices = False, compute_uv = True, overwrite_a = False): """ This routine computes the singular value decomposition of a matrix A. Given A, two orthogonal matrices U and V are calculated such that A = U S V and U' U = 1 and V V' = 1 where S is a suitable shaped matrix whose off-diagonal elements are zero. Here ' denotes the transpose. The diagonal elements of S are the singular values of A, i.e. the squareroots of the eigenvalues of A' A or A A'. input: A : a real matrix of shape (m, n) full_matrices : if true, U and V are of shape (m, m) and (n, n). if false, U and V are of shape (m, min(m, n)) and (min(m, n), n). compute_uv : if true, U and V are calculated. if false, only S is calculated. overwrite_a : if true, allows modification of A which may improve performance. if false, A is not modified. output: U : an orthogonal matrix: U' U = 1. if full_matrices is true, U is of shape (m, m). ortherwise it is of shape (m, min(m, n)). S : an array of length min(m, n) containing the singular values of A sorted by decreasing magnitude. V : an orthogonal matrix: V V' = 1. if full_matrices is true, V is of shape (n, n). ortherwise it is of shape (min(m, n), n). return value: S if compute_uv is false (U, S, V) if compute_uv is true overview of the matrices: full_matrices true: A : m*n U : m*m U' U = 1 S as matrix : m*n V : n*n V V' = 1 full_matrices false: A : m*n U : m*min(n,m) U' U = 1 S as matrix : min(m,n)*min(m,n) V : min(m,n)*n V V' = 1 examples: >>> from mpmath import mp >>> A = mp.matrix([[2, -2, -1], [3, 4, -2], [-2, -2, 0]]) >>> S = mp.svd_r(A, compute_uv = False) >>> print(S) [6.0] [3.0] [1.0] >>> U, S, V = mp.svd_r(A) >>> print(mp.chop(A - U * mp.diag(S) * V)) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] see also: svd, svd_c """ m, n = A.rows, A.cols if not compute_uv: if not overwrite_a: A = A.copy() S = svd_r_raw(ctx, A, V = False, calc_u = False) S = S[:min(m,n)] return S if full_matrices and n < m: V = ctx.zeros(m, m) A0 = ctx.zeros(m, m) A0[:,:n] = A S = svd_r_raw(ctx, A0, V, calc_u = True) S = S[:n] V = V[:n,:n] return (A0, S, V) else: if not overwrite_a: A = A.copy() V = ctx.zeros(n, n) S = svd_r_raw(ctx, A, V, calc_u = True) if n > m: if full_matrices == False: V = V[:m,:] S = S[:m] A = A[:,:m] return (A, S, V) ############################## @defun def svd_c(ctx, A, full_matrices = False, compute_uv = True, overwrite_a = False): """ This routine computes the singular value decomposition of a matrix A. Given A, two unitary matrices U and V are calculated such that A = U S V and U' U = 1 and V V' = 1 where S is a suitable shaped matrix whose off-diagonal elements are zero. Here ' denotes the hermitian transpose (i.e. transposition and complex conjugation). The diagonal elements of S are the singular values of A, i.e. the squareroots of the eigenvalues of A' A or A A'. input: A : a complex matrix of shape (m, n) full_matrices : if true, U and V are of shape (m, m) and (n, n). if false, U and V are of shape (m, min(m, n)) and (min(m, n), n). compute_uv : if true, U and V are calculated. if false, only S is calculated. overwrite_a : if true, allows modification of A which may improve performance. if false, A is not modified. output: U : an unitary matrix: U' U = 1. if full_matrices is true, U is of shape (m, m). ortherwise it is of shape (m, min(m, n)). S : an array of length min(m, n) containing the singular values of A sorted by decreasing magnitude. V : an unitary matrix: V V' = 1. if full_matrices is true, V is of shape (n, n). ortherwise it is of shape (min(m, n), n). return value: S if compute_uv is false (U, S, V) if compute_uv is true overview of the matrices: full_matrices true: A : m*n U : m*m U' U = 1 S as matrix : m*n V : n*n V V' = 1 full_matrices false: A : m*n U : m*min(n,m) U' U = 1 S as matrix : min(m,n)*min(m,n) V : min(m,n)*n V V' = 1 example: >>> from mpmath import mp >>> A = mp.matrix([[-2j, -1-3j, -2+2j], [2-2j, -1-3j, 1], [-3+1j,-2j,0]]) >>> S = mp.svd_c(A, compute_uv = False) >>> print(mp.chop(S - mp.matrix([mp.sqrt(34), mp.sqrt(15), mp.sqrt(6)]))) [0.0] [0.0] [0.0] >>> U, S, V = mp.svd_c(A) >>> print(mp.chop(A - U * mp.diag(S) * V)) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] see also: svd, svd_r """ m, n = A.rows, A.cols if not compute_uv: if not overwrite_a: A = A.copy() S = svd_c_raw(ctx, A, V = False, calc_u = False) S = S[:min(m,n)] return S if full_matrices and n < m: V = ctx.zeros(m, m) A0 = ctx.zeros(m, m) A0[:,:n] = A S = svd_c_raw(ctx, A0, V, calc_u = True) S = S[:n] V = V[:n,:n] return (A0, S, V) else: if not overwrite_a: A = A.copy() V = ctx.zeros(n, n) S = svd_c_raw(ctx, A, V, calc_u = True) if n > m: if full_matrices == False: V = V[:m,:] S = S[:m] A = A[:,:m] return (A, S, V) @defun def svd(ctx, A, full_matrices = False, compute_uv = True, overwrite_a = False): """ "svd" is a unified interface for "svd_r" and "svd_c". Depending on whether A is real or complex the appropriate function is called. This routine computes the singular value decomposition of a matrix A. Given A, two orthogonal (A real) or unitary (A complex) matrices U and V are calculated such that A = U S V and U' U = 1 and V V' = 1 where S is a suitable shaped matrix whose off-diagonal elements are zero. Here ' denotes the hermitian transpose (i.e. transposition and complex conjugation). The diagonal elements of S are the singular values of A, i.e. the squareroots of the eigenvalues of A' A or A A'. input: A : a real or complex matrix of shape (m, n) full_matrices : if true, U and V are of shape (m, m) and (n, n). if false, U and V are of shape (m, min(m, n)) and (min(m, n), n). compute_uv : if true, U and V are calculated. if false, only S is calculated. overwrite_a : if true, allows modification of A which may improve performance. if false, A is not modified. output: U : an orthogonal or unitary matrix: U' U = 1. if full_matrices is true, U is of shape (m, m). ortherwise it is of shape (m, min(m, n)). S : an array of length min(m, n) containing the singular values of A sorted by decreasing magnitude. V : an orthogonal or unitary matrix: V V' = 1. if full_matrices is true, V is of shape (n, n). ortherwise it is of shape (min(m, n), n). return value: S if compute_uv is false (U, S, V) if compute_uv is true overview of the matrices: full_matrices true: A : m*n U : m*m U' U = 1 S as matrix : m*n V : n*n V V' = 1 full_matrices false: A : m*n U : m*min(n,m) U' U = 1 S as matrix : min(m,n)*min(m,n) V : min(m,n)*n V V' = 1 examples: >>> from mpmath import mp >>> A = mp.matrix([[2, -2, -1], [3, 4, -2], [-2, -2, 0]]) >>> S = mp.svd(A, compute_uv = False) >>> print(S) [6.0] [3.0] [1.0] >>> U, S, V = mp.svd(A) >>> print(mp.chop(A - U * mp.diag(S) * V)) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] see also: svd_r, svd_c """ iscomplex = any(type(x) is ctx.mpc for x in A) if iscomplex: return ctx.svd_c(A, full_matrices = full_matrices, compute_uv = compute_uv, overwrite_a = overwrite_a) else: return ctx.svd_r(A, full_matrices = full_matrices, compute_uv = compute_uv, overwrite_a = overwrite_a) mpmath-1.1.0/mpmath/matrices/linalg.py000066400000000000000000000646141340375245600177400ustar00rootroot00000000000000""" Linear algebra -------------- Linear equations ................ Basic linear algebra is implemented; you can for example solve the linear equation system:: x + 2*y = -10 3*x + 4*y = 10 using ``lu_solve``:: >>> from mpmath import * >>> mp.pretty = False >>> A = matrix([[1, 2], [3, 4]]) >>> b = matrix([-10, 10]) >>> x = lu_solve(A, b) >>> x matrix( [['30.0'], ['-20.0']]) If you don't trust the result, use ``residual`` to calculate the residual ||A*x-b||:: >>> residual(A, x, b) matrix( [['3.46944695195361e-18'], ['3.46944695195361e-18']]) >>> str(eps) '2.22044604925031e-16' As you can see, the solution is quite accurate. The error is caused by the inaccuracy of the internal floating point arithmetic. Though, it's even smaller than the current machine epsilon, which basically means you can trust the result. If you need more speed, use NumPy. Or choose a faster data type using the keyword ``force_type``:: >>> lu_solve(A, b, force_type=float) matrix( [['30.0'], ['-20.0']]) ``lu_solve`` accepts overdetermined systems. It is usually not possible to solve such systems, so the residual is minimized instead. Internally this is done using Cholesky decomposition to compute a least squares approximation. This means that that ``lu_solve`` will square the errors. If you can't afford this, use ``qr_solve`` instead. It is twice as slow but more accurate, and it calculates the residual automatically. Matrix factorization .................... The function ``lu`` computes an explicit LU factorization of a matrix:: >>> P, L, U = lu(matrix([[0,2,3],[4,5,6],[7,8,9]])) >>> print(P) [0.0 0.0 1.0] [1.0 0.0 0.0] [0.0 1.0 0.0] >>> print(L) [ 1.0 0.0 0.0] [ 0.0 1.0 0.0] [0.571428571428571 0.214285714285714 1.0] >>> print(U) [7.0 8.0 9.0] [0.0 2.0 3.0] [0.0 0.0 0.214285714285714] >>> print(P.T*L*U) [0.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0] Interval matrices ----------------- Matrices may contain interval elements. This allows one to perform basic linear algebra operations such as matrix multiplication and equation solving with rigorous error bounds:: >>> a = iv.matrix([['0.1','0.3','1.0'], ... ['7.1','5.5','4.8'], ... ['3.2','4.4','5.6']], force_type=mpi) >>> >>> b = iv.matrix(['4','0.6','0.5'], force_type=mpi) >>> c = iv.lu_solve(a, b) >>> print(c) [ [5.2582327113062568605927528666, 5.25823271130625686059275702219]] [[-13.1550493962678375411635581388, -13.1550493962678375411635540152]] [ [7.42069154774972557628979076189, 7.42069154774972557628979190734]] >>> print(a*c) [ [3.99999999999999999999999844904, 4.00000000000000000000000155096]] [[0.599999999999999999999968898009, 0.600000000000000000000031763736]] [[0.499999999999999999999979320485, 0.500000000000000000000020679515]] """ # TODO: # *implement high-level qr() # *test unitvector # *iterative solving from copy import copy from ..libmp.backend import xrange class LinearAlgebraMethods(object): def LU_decomp(ctx, A, overwrite=False, use_cache=True): """ LU-factorization of a n*n matrix using the Gauss algorithm. Returns L and U in one matrix and the pivot indices. Use overwrite to specify whether A will be overwritten with L and U. """ if not A.rows == A.cols: raise ValueError('need n*n matrix') # get from cache if possible if use_cache and isinstance(A, ctx.matrix) and A._LU: return A._LU if not overwrite: orig = A A = A.copy() tol = ctx.absmin(ctx.mnorm(A,1) * ctx.eps) # each pivot element has to be bigger n = A.rows p = [None]*(n - 1) for j in xrange(n - 1): # pivoting, choose max(abs(reciprocal row sum)*abs(pivot element)) biggest = 0 for k in xrange(j, n): s = ctx.fsum([ctx.absmin(A[k,l]) for l in xrange(j, n)]) if ctx.absmin(s) <= tol: raise ZeroDivisionError('matrix is numerically singular') current = 1/s * ctx.absmin(A[k,j]) if current > biggest: # TODO: what if equal? biggest = current p[j] = k # swap rows according to p ctx.swap_row(A, j, p[j]) if ctx.absmin(A[j,j]) <= tol: raise ZeroDivisionError('matrix is numerically singular') # calculate elimination factors and add rows for i in xrange(j + 1, n): A[i,j] /= A[j,j] for k in xrange(j + 1, n): A[i,k] -= A[i,j]*A[j,k] if ctx.absmin(A[n - 1,n - 1]) <= tol: raise ZeroDivisionError('matrix is numerically singular') # cache decomposition if not overwrite and isinstance(orig, ctx.matrix): orig._LU = (A, p) return A, p def L_solve(ctx, L, b, p=None): """ Solve the lower part of a LU factorized matrix for y. """ if L.rows != L.cols: raise RuntimeError("need n*n matrix") n = L.rows if len(b) != n: raise ValueError("Value should be equal to n") b = copy(b) if p: # swap b according to p for k in xrange(0, len(p)): ctx.swap_row(b, k, p[k]) # solve for i in xrange(1, n): for j in xrange(i): b[i] -= L[i,j] * b[j] return b def U_solve(ctx, U, y): """ Solve the upper part of a LU factorized matrix for x. """ if U.rows != U.cols: raise RuntimeError("need n*n matrix") n = U.rows if len(y) != n: raise ValueError("Value should be equal to n") x = copy(y) for i in xrange(n - 1, -1, -1): for j in xrange(i + 1, n): x[i] -= U[i,j] * x[j] x[i] /= U[i,i] return x def lu_solve(ctx, A, b, **kwargs): """ Ax = b => x Solve a determined or overdetermined linear equations system. Fast LU decomposition is used, which is less accurate than QR decomposition (especially for overdetermined systems), but it's twice as efficient. Use qr_solve if you want more precision or have to solve a very ill- conditioned system. If you specify real=True, it does not check for overdeterminded complex systems. """ prec = ctx.prec try: ctx.prec += 10 # do not overwrite A nor b A, b = ctx.matrix(A, **kwargs).copy(), ctx.matrix(b, **kwargs).copy() if A.rows < A.cols: raise ValueError('cannot solve underdetermined system') if A.rows > A.cols: # use least-squares method if overdetermined # (this increases errors) AH = A.H A = AH * A b = AH * b if (kwargs.get('real', False) or not sum(type(i) is ctx.mpc for i in A)): # TODO: necessary to check also b? x = ctx.cholesky_solve(A, b) else: x = ctx.lu_solve(A, b) else: # LU factorization A, p = ctx.LU_decomp(A) b = ctx.L_solve(A, b, p) x = ctx.U_solve(A, b) finally: ctx.prec = prec return x def improve_solution(ctx, A, x, b, maxsteps=1): """ Improve a solution to a linear equation system iteratively. This re-uses the LU decomposition and is thus cheap. Usually 3 up to 4 iterations are giving the maximal improvement. """ if A.rows != A.cols: raise RuntimeError("need n*n matrix") # TODO: really? for _ in xrange(maxsteps): r = ctx.residual(A, x, b) if ctx.norm(r, 2) < 10*ctx.eps: break # this uses cached LU decomposition and is thus cheap dx = ctx.lu_solve(A, -r) x += dx return x def lu(ctx, A): """ A -> P, L, U LU factorisation of a square matrix A. L is the lower, U the upper part. P is the permutation matrix indicating the row swaps. P*A = L*U If you need efficiency, use the low-level method LU_decomp instead, it's much more memory efficient. """ # get factorization A, p = ctx.LU_decomp(A) n = A.rows L = ctx.matrix(n) U = ctx.matrix(n) for i in xrange(n): for j in xrange(n): if i > j: L[i,j] = A[i,j] elif i == j: L[i,j] = 1 U[i,j] = A[i,j] else: U[i,j] = A[i,j] # calculate permutation matrix P = ctx.eye(n) for k in xrange(len(p)): ctx.swap_row(P, k, p[k]) return P, L, U def unitvector(ctx, n, i): """ Return the i-th n-dimensional unit vector. """ assert 0 < i <= n, 'this unit vector does not exist' return [ctx.zero]*(i-1) + [ctx.one] + [ctx.zero]*(n-i) def inverse(ctx, A, **kwargs): """ Calculate the inverse of a matrix. If you want to solve an equation system Ax = b, it's recommended to use solve(A, b) instead, it's about 3 times more efficient. """ prec = ctx.prec try: ctx.prec += 10 # do not overwrite A A = ctx.matrix(A, **kwargs).copy() n = A.rows # get LU factorisation A, p = ctx.LU_decomp(A) cols = [] # calculate unit vectors and solve corresponding system to get columns for i in xrange(1, n + 1): e = ctx.unitvector(n, i) y = ctx.L_solve(A, e, p) cols.append(ctx.U_solve(A, y)) # convert columns to matrix inv = [] for i in xrange(n): row = [] for j in xrange(n): row.append(cols[j][i]) inv.append(row) result = ctx.matrix(inv, **kwargs) finally: ctx.prec = prec return result def householder(ctx, A): """ (A|b) -> H, p, x, res (A|b) is the coefficient matrix with left hand side of an optionally overdetermined linear equation system. H and p contain all information about the transformation matrices. x is the solution, res the residual. """ if not isinstance(A, ctx.matrix): raise TypeError("A should be a type of ctx.matrix") m = A.rows n = A.cols if m < n - 1: raise RuntimeError("Columns should not be less than rows") # calculate Householder matrix p = [] for j in xrange(0, n - 1): s = ctx.fsum(abs(A[i,j])**2 for i in xrange(j, m)) if not abs(s) > ctx.eps: raise ValueError('matrix is numerically singular') p.append(-ctx.sign(ctx.re(A[j,j])) * ctx.sqrt(s)) kappa = ctx.one / (s - p[j] * A[j,j]) A[j,j] -= p[j] for k in xrange(j+1, n): y = ctx.fsum(ctx.conj(A[i,j]) * A[i,k] for i in xrange(j, m)) * kappa for i in xrange(j, m): A[i,k] -= A[i,j] * y # solve Rx = c1 x = [A[i,n - 1] for i in xrange(n - 1)] for i in xrange(n - 2, -1, -1): x[i] -= ctx.fsum(A[i,j] * x[j] for j in xrange(i + 1, n - 1)) x[i] /= p[i] # calculate residual if not m == n - 1: r = [A[m-1-i, n-1] for i in xrange(m - n + 1)] else: # determined system, residual should be 0 r = [0]*m # maybe a bad idea, changing r[i] will change all elements return A, p, x, r #def qr(ctx, A): # """ # A -> Q, R # # QR factorisation of a square matrix A using Householder decomposition. # Q is orthogonal, this leads to very few numerical errors. # # A = Q*R # """ # H, p, x, res = householder(A) # TODO: implement this def residual(ctx, A, x, b, **kwargs): """ Calculate the residual of a solution to a linear equation system. r = A*x - b for A*x = b """ oldprec = ctx.prec try: ctx.prec *= 2 A, x, b = ctx.matrix(A, **kwargs), ctx.matrix(x, **kwargs), ctx.matrix(b, **kwargs) return A*x - b finally: ctx.prec = oldprec def qr_solve(ctx, A, b, norm=None, **kwargs): """ Ax = b => x, ||Ax - b|| Solve a determined or overdetermined linear equations system and calculate the norm of the residual (error). QR decomposition using Householder factorization is applied, which gives very accurate results even for ill-conditioned matrices. qr_solve is twice as efficient. """ if norm is None: norm = ctx.norm prec = ctx.prec try: ctx.prec += 10 # do not overwrite A nor b A, b = ctx.matrix(A, **kwargs).copy(), ctx.matrix(b, **kwargs).copy() if A.rows < A.cols: raise ValueError('cannot solve underdetermined system') H, p, x, r = ctx.householder(ctx.extend(A, b)) res = ctx.norm(r) # calculate residual "manually" for determined systems if res == 0: res = ctx.norm(ctx.residual(A, x, b)) return ctx.matrix(x, **kwargs), res finally: ctx.prec = prec def cholesky(ctx, A, tol=None): r""" Cholesky decomposition of a symmetric positive-definite matrix `A`. Returns a lower triangular matrix `L` such that `A = L \times L^T`. More generally, for a complex Hermitian positive-definite matrix, a Cholesky decomposition satisfying `A = L \times L^H` is returned. The Cholesky decomposition can be used to solve linear equation systems twice as efficiently as LU decomposition, or to test whether `A` is positive-definite. The optional parameter ``tol`` determines the tolerance for verifying positive-definiteness. **Examples** Cholesky decomposition of a positive-definite symmetric matrix:: >>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> A = eye(3) + hilbert(3) >>> nprint(A) [ 2.0 0.5 0.333333] [ 0.5 1.33333 0.25] [0.333333 0.25 1.2] >>> L = cholesky(A) >>> nprint(L) [ 1.41421 0.0 0.0] [0.353553 1.09924 0.0] [0.235702 0.15162 1.05899] >>> chop(A - L*L.T) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] Cholesky decomposition of a Hermitian matrix:: >>> A = eye(3) + matrix([[0,0.25j,-0.5j],[-0.25j,0,0],[0.5j,0,0]]) >>> L = cholesky(A) >>> nprint(L) [ 1.0 0.0 0.0] [(0.0 - 0.25j) (0.968246 + 0.0j) 0.0] [ (0.0 + 0.5j) (0.129099 + 0.0j) (0.856349 + 0.0j)] >>> chop(A - L*L.H) [0.0 0.0 0.0] [0.0 0.0 0.0] [0.0 0.0 0.0] Attempted Cholesky decomposition of a matrix that is not positive definite:: >>> A = -eye(3) + hilbert(3) >>> L = cholesky(A) Traceback (most recent call last): ... ValueError: matrix is not positive-definite **References** 1. [Wikipedia]_ http://en.wikipedia.org/wiki/Cholesky_decomposition """ if not isinstance(A, ctx.matrix): raise RuntimeError("A should be a type of ctx.matrix") if not A.rows == A.cols: raise ValueError('need n*n matrix') if tol is None: tol = +ctx.eps n = A.rows L = ctx.matrix(n) for j in xrange(n): c = ctx.re(A[j,j]) if abs(c-A[j,j]) > tol: raise ValueError('matrix is not Hermitian') s = c - ctx.fsum((L[j,k] for k in xrange(j)), absolute=True, squared=True) if s < tol: raise ValueError('matrix is not positive-definite') L[j,j] = ctx.sqrt(s) for i in xrange(j, n): it1 = (L[i,k] for k in xrange(j)) it2 = (L[j,k] for k in xrange(j)) t = ctx.fdot(it1, it2, conjugate=True) L[i,j] = (A[i,j] - t) / L[j,j] return L def cholesky_solve(ctx, A, b, **kwargs): """ Ax = b => x Solve a symmetric positive-definite linear equation system. This is twice as efficient as lu_solve. Typical use cases: * A.T*A * Hessian matrix * differential equations """ prec = ctx.prec try: ctx.prec += 10 # do not overwrite A nor b A, b = ctx.matrix(A, **kwargs).copy(), ctx.matrix(b, **kwargs).copy() if A.rows != A.cols: raise ValueError('can only solve determined system') # Cholesky factorization L = ctx.cholesky(A) # solve n = L.rows if len(b) != n: raise ValueError("Value should be equal to n") for i in xrange(n): b[i] -= ctx.fsum(L[i,j] * b[j] for j in xrange(i)) b[i] /= L[i,i] x = ctx.U_solve(L.T, b) return x finally: ctx.prec = prec def det(ctx, A): """ Calculate the determinant of a matrix. """ prec = ctx.prec try: # do not overwrite A A = ctx.matrix(A).copy() # use LU factorization to calculate determinant try: R, p = ctx.LU_decomp(A) except ZeroDivisionError: return 0 z = 1 for i, e in enumerate(p): if i != e: z *= -1 for i in xrange(A.rows): z *= R[i,i] return z finally: ctx.prec = prec def cond(ctx, A, norm=None): """ Calculate the condition number of a matrix using a specified matrix norm. The condition number estimates the sensitivity of a matrix to errors. Example: small input errors for ill-conditioned coefficient matrices alter the solution of the system dramatically. For ill-conditioned matrices it's recommended to use qr_solve() instead of lu_solve(). This does not help with input errors however, it just avoids to add additional errors. Definition: cond(A) = ||A|| * ||A**-1|| """ if norm is None: norm = lambda x: ctx.mnorm(x,1) return norm(A) * norm(ctx.inverse(A)) def lu_solve_mat(ctx, a, b): """Solve a * x = b where a and b are matrices.""" r = ctx.matrix(a.rows, b.cols) for i in range(b.cols): c = ctx.lu_solve(a, b.column(i)) for j in range(len(c)): r[j, i] = c[j] return r def qr(ctx, A, mode = 'full', edps = 10): """ Compute a QR factorization $A = QR$ where A is an m x n matrix of real or complex numbers where m >= n mode has following meanings: (1) mode = 'raw' returns two matrixes (A, tau) in the internal format used by LAPACK (2) mode = 'skinny' returns the leading n columns of Q and n rows of R (3) Any other value returns the leading m columns of Q and m rows of R edps is the increase in mp precision used for calculations **Examples** >>> from mpmath import * >>> mp.dps = 15 >>> mp.pretty = True >>> A = matrix([[1, 2], [3, 4], [1, 1]]) >>> Q, R = qr(A) >>> Q [-0.301511344577764 0.861640436855329 0.408248290463863] [-0.904534033733291 -0.123091490979333 -0.408248290463863] [-0.301511344577764 -0.492365963917331 0.816496580927726] >>> R [-3.3166247903554 -4.52267016866645] [ 0.0 0.738548945875996] [ 0.0 0.0] >>> Q * R [1.0 2.0] [3.0 4.0] [1.0 1.0] >>> chop(Q.T * Q) [1.0 0.0 0.0] [0.0 1.0 0.0] [0.0 0.0 1.0] >>> B = matrix([[1+0j, 2-3j], [3+j, 4+5j]]) >>> Q, R = qr(B) >>> nprint(Q) [ (-0.301511 + 0.0j) (0.0695795 - 0.95092j)] [(-0.904534 - 0.301511j) (-0.115966 + 0.278318j)] >>> nprint(R) [(-3.31662 + 0.0j) (-5.72872 - 2.41209j)] [ 0.0 (3.91965 + 0.0j)] >>> Q * R [(1.0 + 0.0j) (2.0 - 3.0j)] [(3.0 + 1.0j) (4.0 + 5.0j)] >>> chop(Q.T * Q.conjugate()) [1.0 0.0] [0.0 1.0] """ # check values before continuing assert isinstance(A, ctx.matrix) m = A.rows n = A.cols assert n > 1 assert m >= n assert edps >= 0 # check for complex data type cmplx = any(type(x) is ctx.mpc for x in A) # temporarily increase the precision and initialize with ctx.extradps(edps): tau = ctx.matrix(n,1) A = A.copy() # --------------- # FACTOR MATRIX A # --------------- if cmplx: one = ctx.mpc('1.0', '0.0') zero = ctx.mpc('0.0', '0.0') rzero = ctx.mpf('0.0') # main loop to factor A (complex) for j in xrange(0, n): alpha = A[j,j] alphr = ctx.re(alpha) alphi = ctx.im(alpha) if (m-j) >= 2: xnorm = ctx.fsum( A[i,j]*ctx.conj(A[i,j]) for i in xrange(j+1, m) ) xnorm = ctx.re( ctx.sqrt(xnorm) ) else: xnorm = rzero if (xnorm == rzero) and (alphi == rzero): tau[j] = zero continue if alphr < rzero: beta = ctx.sqrt(alphr**2 + alphi**2 + xnorm**2) else: beta = -ctx.sqrt(alphr**2 + alphi**2 + xnorm**2) tau[j] = ctx.mpc( (beta - alphr) / beta, -alphi / beta ) t = -ctx.conj(tau[j]) za = one / (alpha - beta) for i in xrange(j+1, m): A[i,j] *= za A[j,j] = one for k in xrange(j+1, n): y = ctx.fsum(A[i,j] * ctx.conj(A[i,k]) for i in xrange(j, m)) temp = t * ctx.conj(y) for i in xrange(j, m): A[i,k] += A[i,j] * temp A[j,j] = ctx.mpc(beta, '0.0') else: one = ctx.mpf('1.0') zero = ctx.mpf('0.0') # main loop to factor A (real) for j in xrange(0, n): alpha = A[j,j] if (m-j) > 2: xnorm = ctx.fsum( (A[i,j])**2 for i in xrange(j+1, m) ) xnorm = ctx.sqrt(xnorm) elif (m-j) == 2: xnorm = abs( A[m-1,j] ) else: xnorm = zero if xnorm == zero: tau[j] = zero continue if alpha < zero: beta = ctx.sqrt(alpha**2 + xnorm**2) else: beta = -ctx.sqrt(alpha**2 + xnorm**2) tau[j] = (beta - alpha) / beta t = -tau[j] da = one / (alpha - beta) for i in xrange(j+1, m): A[i,j] *= da A[j,j] = one for k in xrange(j+1, n): y = ctx.fsum( A[i,j] * A[i,k] for i in xrange(j, m) ) temp = t * y for i in xrange(j,m): A[i,k] += A[i,j] * temp A[j,j] = beta # return factorization in same internal format as LAPACK if (mode == 'raw') or (mode == 'RAW'): return A, tau # ---------------------------------- # FORM Q USING BACKWARD ACCUMULATION # ---------------------------------- # form R before the values are overwritten R = A.copy() for j in xrange(0, n): for i in xrange(j+1, m): R[i,j] = zero # set the value of p (number of columns of Q to return) p = m if (mode == 'skinny') or (mode == 'SKINNY'): p = n # add columns to A if needed and initialize A.cols += (p-n) for j in xrange(0, p): A[j,j] = one for i in xrange(0, j): A[i,j] = zero # main loop to form Q for j in xrange(n-1, -1, -1): t = -tau[j] A[j,j] += t for k in xrange(j+1, p): if cmplx: y = ctx.fsum(A[i,j] * ctx.conj(A[i,k]) for i in xrange(j+1, m)) temp = t * ctx.conj(y) else: y = ctx.fsum(A[i,j] * A[i,k] for i in xrange(j+1, m)) temp = t * y A[j,k] = temp for i in xrange(j+1, m): A[i,k] += A[i,j] * temp for i in xrange(j+1, m): A[i, j] *= t return A, R[0:p,0:n] # ------------------ # END OF FUNCTION QR # ------------------ mpmath-1.1.0/mpmath/matrices/matrices.py000066400000000000000000000755531340375245600203050ustar00rootroot00000000000000from ..libmp.backend import xrange # TODO: interpret list as vectors (for multiplication) rowsep = '\n' colsep = ' ' class _matrix(object): """ Numerical matrix. Specify the dimensions or the data as a nested list. Elements default to zero. Use a flat list to create a column vector easily. By default, only mpf is used to store the data. You can specify another type using force_type=type. It's possible to specify None. Make sure force_type(force_type()) is fast. Creating matrices ----------------- Matrices in mpmath are implemented using dictionaries. Only non-zero values are stored, so it is cheap to represent sparse matrices. The most basic way to create one is to use the ``matrix`` class directly. You can create an empty matrix specifying the dimensions: >>> from mpmath import * >>> mp.dps = 15 >>> matrix(2) matrix( [['0.0', '0.0'], ['0.0', '0.0']]) >>> matrix(2, 3) matrix( [['0.0', '0.0', '0.0'], ['0.0', '0.0', '0.0']]) Calling ``matrix`` with one dimension will create a square matrix. To access the dimensions of a matrix, use the ``rows`` or ``cols`` keyword: >>> A = matrix(3, 2) >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0'], ['0.0', '0.0']]) >>> A.rows 3 >>> A.cols 2 You can also change the dimension of an existing matrix. This will set the new elements to 0. If the new dimension is smaller than before, the concerning elements are discarded: >>> A.rows = 2 >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0']]) Internally ``mpmathify`` is used every time an element is set. This is done using the syntax A[row,column], counting from 0: >>> A = matrix(2) >>> A[1,1] = 1 + 1j >>> A matrix( [['0.0', '0.0'], ['0.0', mpc(real='1.0', imag='1.0')]]) You can use the keyword ``force_type`` to change the function which is called on every new element: >>> matrix(2, 5, force_type=int) # doctest: +SKIP matrix( [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) A more comfortable way to create a matrix lets you use nested lists: >>> matrix([[1, 2], [3, 4]]) matrix( [['1.0', '2.0'], ['3.0', '4.0']]) If you want to preserve the type of the elements you can use ``force_type=None``: >>> matrix([[1, 2.5], [1j, mpf(2)]], force_type=None) matrix( [['1.0', '2.5'], [mpc(real='0.0', imag='1.0'), '2.0']]) Convenient advanced functions are available for creating various standard matrices, see ``zeros``, ``ones``, ``diag``, ``eye``, ``randmatrix`` and ``hilbert``. Vectors ....... Vectors may also be represented by the ``matrix`` class (with rows = 1 or cols = 1). For vectors there are some things which make life easier. A column vector can be created using a flat list, a row vectors using an almost flat nested list:: >>> matrix([1, 2, 3]) matrix( [['1.0'], ['2.0'], ['3.0']]) >>> matrix([[1, 2, 3]]) matrix( [['1.0', '2.0', '3.0']]) Optionally vectors can be accessed like lists, using only a single index:: >>> x = matrix([1, 2, 3]) >>> x[1] mpf('2.0') >>> x[1,0] mpf('2.0') Other ..... Like you probably expected, matrices can be printed:: >>> print randmatrix(3) # doctest:+SKIP [ 0.782963853573023 0.802057689719883 0.427895717335467] [0.0541876859348597 0.708243266653103 0.615134039977379] [ 0.856151514955773 0.544759264818486 0.686210904770947] Use ``nstr`` or ``nprint`` to specify the number of digits to print:: >>> nprint(randmatrix(5), 3) # doctest:+SKIP [2.07e-1 1.66e-1 5.06e-1 1.89e-1 8.29e-1] [6.62e-1 6.55e-1 4.47e-1 4.82e-1 2.06e-2] [4.33e-1 7.75e-1 6.93e-2 2.86e-1 5.71e-1] [1.01e-1 2.53e-1 6.13e-1 3.32e-1 2.59e-1] [1.56e-1 7.27e-2 6.05e-1 6.67e-2 2.79e-1] As matrices are mutable, you will need to copy them sometimes:: >>> A = matrix(2) >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0']]) >>> B = A.copy() >>> B[0,0] = 1 >>> B matrix( [['1.0', '0.0'], ['0.0', '0.0']]) >>> A matrix( [['0.0', '0.0'], ['0.0', '0.0']]) Finally, it is possible to convert a matrix to a nested list. This is very useful, as most Python libraries involving matrices or arrays (namely NumPy or SymPy) support this format:: >>> B.tolist() [[mpf('1.0'), mpf('0.0')], [mpf('0.0'), mpf('0.0')]] Matrix operations ----------------- You can add and subtract matrices of compatible dimensions:: >>> A = matrix([[1, 2], [3, 4]]) >>> B = matrix([[-2, 4], [5, 9]]) >>> A + B matrix( [['-1.0', '6.0'], ['8.0', '13.0']]) >>> A - B matrix( [['3.0', '-2.0'], ['-2.0', '-5.0']]) >>> A + ones(3) # doctest:+ELLIPSIS Traceback (most recent call last): ... ValueError: incompatible dimensions for addition It is possible to multiply or add matrices and scalars. In the latter case the operation will be done element-wise:: >>> A * 2 matrix( [['2.0', '4.0'], ['6.0', '8.0']]) >>> A / 4 matrix( [['0.25', '0.5'], ['0.75', '1.0']]) >>> A - 1 matrix( [['0.0', '1.0'], ['2.0', '3.0']]) Of course you can perform matrix multiplication, if the dimensions are compatible:: >>> A * B matrix( [['8.0', '22.0'], ['14.0', '48.0']]) >>> matrix([[1, 2, 3]]) * matrix([[-6], [7], [-2]]) matrix( [['2.0']]) You can raise powers of square matrices:: >>> A**2 matrix( [['7.0', '10.0'], ['15.0', '22.0']]) Negative powers will calculate the inverse:: >>> A**-1 matrix( [['-2.0', '1.0'], ['1.5', '-0.5']]) >>> A * A**-1 matrix( [['1.0', '1.0842021724855e-19'], ['-2.16840434497101e-19', '1.0']]) Matrix transposition is straightforward:: >>> A = ones(2, 3) >>> A matrix( [['1.0', '1.0', '1.0'], ['1.0', '1.0', '1.0']]) >>> A.T matrix( [['1.0', '1.0'], ['1.0', '1.0'], ['1.0', '1.0']]) Norms ..... Sometimes you need to know how "large" a matrix or vector is. Due to their multidimensional nature it's not possible to compare them, but there are several functions to map a matrix or a vector to a positive real number, the so called norms. For vectors the p-norm is intended, usually the 1-, the 2- and the oo-norm are used. >>> x = matrix([-10, 2, 100]) >>> norm(x, 1) mpf('112.0') >>> norm(x, 2) mpf('100.5186549850325') >>> norm(x, inf) mpf('100.0') Please note that the 2-norm is the most used one, though it is more expensive to calculate than the 1- or oo-norm. It is possible to generalize some vector norms to matrix norm:: >>> A = matrix([[1, -1000], [100, 50]]) >>> mnorm(A, 1) mpf('1050.0') >>> mnorm(A, inf) mpf('1001.0') >>> mnorm(A, 'F') mpf('1006.2310867787777') The last norm (the "Frobenius-norm") is an approximation for the 2-norm, which is hard to calculate and not available. The Frobenius-norm lacks some mathematical properties you might expect from a norm. """ def __init__(self, *args, **kwargs): self.__data = {} # LU decompostion cache, this is useful when solving the same system # multiple times, when calculating the inverse and when calculating the # determinant self._LU = None convert = kwargs.get('force_type', self.ctx.convert) if not convert: convert = lambda x: x if isinstance(args[0], (list, tuple)): if isinstance(args[0][0], (list, tuple)): # interpret nested list as matrix A = args[0] self.__rows = len(A) self.__cols = len(A[0]) for i, row in enumerate(A): for j, a in enumerate(row): self[i, j] = convert(a) else: # interpret list as row vector v = args[0] self.__rows = len(v) self.__cols = 1 for i, e in enumerate(v): self[i, 0] = e elif isinstance(args[0], int): # create empty matrix of given dimensions if len(args) == 1: self.__rows = self.__cols = args[0] else: if not isinstance(args[1], int): raise TypeError("expected int") self.__rows = args[0] self.__cols = args[1] elif isinstance(args[0], _matrix): A = args[0].copy() self.__data = A._matrix__data self.__rows = A._matrix__rows self.__cols = A._matrix__cols for i in xrange(A.__rows): for j in xrange(A.__cols): A[i,j] = convert(A[i,j]) elif hasattr(args[0], 'tolist'): A = self.ctx.matrix(args[0].tolist()) self.__data = A._matrix__data self.__rows = A._matrix__rows self.__cols = A._matrix__cols else: raise TypeError('could not interpret given arguments') def apply(self, f): """ Return a copy of self with the function `f` applied elementwise. """ new = self.ctx.matrix(self.__rows, self.__cols) for i in xrange(self.__rows): for j in xrange(self.__cols): new[i,j] = f(self[i,j]) return new def __nstr__(self, n=None, **kwargs): # Build table of string representations of the elements res = [] # Track per-column max lengths for pretty alignment maxlen = [0] * self.cols for i in range(self.rows): res.append([]) for j in range(self.cols): if n: string = self.ctx.nstr(self[i,j], n, **kwargs) else: string = str(self[i,j]) res[-1].append(string) maxlen[j] = max(len(string), maxlen[j]) # Patch strings together for i, row in enumerate(res): for j, elem in enumerate(row): # Pad each element up to maxlen so the columns line up row[j] = elem.rjust(maxlen[j]) res[i] = "[" + colsep.join(row) + "]" return rowsep.join(res) def __str__(self): return self.__nstr__() def _toliststr(self, avoid_type=False): """ Create a list string from a matrix. If avoid_type: avoid multiple 'mpf's. """ # XXX: should be something like self.ctx._types typ = self.ctx.mpf s = '[' for i in xrange(self.__rows): s += '[' for j in xrange(self.__cols): if not avoid_type or not isinstance(self[i,j], typ): a = repr(self[i,j]) else: a = "'" + str(self[i,j]) + "'" s += a + ', ' s = s[:-2] s += '],\n ' s = s[:-3] s += ']' return s def tolist(self): """ Convert the matrix to a nested list. """ return [[self[i,j] for j in range(self.__cols)] for i in range(self.__rows)] def __repr__(self): if self.ctx.pretty: return self.__str__() s = 'matrix(\n' s += self._toliststr(avoid_type=True) + ')' return s def __get_element(self, key): ''' Fast extraction of the i,j element from the matrix This function is for private use only because is unsafe: 1. Does not check on the value of key it expects key to be a integer tuple (i,j) 2. Does not check bounds ''' if key in self.__data: return self.__data[key] else: return self.ctx.zero def __set_element(self, key, value): ''' Fast assignment of the i,j element in the matrix This function is unsafe: 1. Does not check on the value of key it expects key to be a integer tuple (i,j) 2. Does not check bounds 3. Does not check the value type ''' if value: # only store non-zeros self.__data[key] = value elif key in self.__data: del self.__data[key] def __getitem__(self, key): ''' Getitem function for mp matrix class with slice index enabled it allows the following assingments scalar to a slice of the matrix B = A[:,2:6] ''' # Convert vector to matrix indexing if isinstance(key, int) or isinstance(key,slice): # only sufficent for vectors if self.__rows == 1: key = (0, key) elif self.__cols == 1: key = (key, 0) else: raise IndexError('insufficient indices for matrix') if isinstance(key[0],slice) or isinstance(key[1],slice): #Rows if isinstance(key[0],slice): #Check bounds if (key[0].start is None or key[0].start >= 0) and \ (key[0].stop is None or key[0].stop <= self.__rows+1): # Generate indices rows = xrange(*key[0].indices(self.__rows)) else: raise IndexError('Row index out of bounds') else: # Single row rows = [key[0]] # Columns if isinstance(key[1],slice): # Check bounds if (key[1].start is None or key[1].start >= 0) and \ (key[1].stop is None or key[1].stop <= self.__cols+1): # Generate indices columns = xrange(*key[1].indices(self.__cols)) else: raise IndexError('Column index out of bounds') else: # Single column columns = [key[1]] # Create matrix slice m = self.ctx.matrix(len(rows),len(columns)) # Assign elements to the output matrix for i,x in enumerate(rows): for j,y in enumerate(columns): m.__set_element((i,j),self.__get_element((x,y))) return m else: # single element extraction if key[0] >= self.__rows or key[1] >= self.__cols: raise IndexError('matrix index out of range') if key in self.__data: return self.__data[key] else: return self.ctx.zero def __setitem__(self, key, value): # setitem function for mp matrix class with slice index enabled # it allows the following assingments # scalar to a slice of the matrix # A[:,2:6] = 2.5 # submatrix to matrix (the value matrix should be the same size as the slice size) # A[3,:] = B where A is n x m and B is n x 1 # Convert vector to matrix indexing if isinstance(key, int) or isinstance(key,slice): # only sufficent for vectors if self.__rows == 1: key = (0, key) elif self.__cols == 1: key = (key, 0) else: raise IndexError('insufficient indices for matrix') # Slice indexing if isinstance(key[0],slice) or isinstance(key[1],slice): # Rows if isinstance(key[0],slice): # Check bounds if (key[0].start is None or key[0].start >= 0) and \ (key[0].stop is None or key[0].stop <= self.__rows+1): # generate row indices rows = xrange(*key[0].indices(self.__rows)) else: raise IndexError('Row index out of bounds') else: # Single row rows = [key[0]] # Columns if isinstance(key[1],slice): # Check bounds if (key[1].start is None or key[1].start >= 0) and \ (key[1].stop is None or key[1].stop <= self.__cols+1): # Generate column indices columns = xrange(*key[1].indices(self.__cols)) else: raise IndexError('Column index out of bounds') else: # Single column columns = [key[1]] # Assign slice with a scalar if isinstance(value,self.ctx.matrix): # Assign elements to matrix if input and output dimensions match if len(rows) == value.rows and len(columns) == value.cols: for i,x in enumerate(rows): for j,y in enumerate(columns): self.__set_element((x,y), value.__get_element((i,j))) else: raise ValueError('Dimensions do not match') else: # Assign slice with scalars value = self.ctx.convert(value) for i in rows: for j in columns: self.__set_element((i,j), value) else: # Single element assingment # Check bounds if key[0] >= self.__rows or key[1] >= self.__cols: raise IndexError('matrix index out of range') # Convert and store value value = self.ctx.convert(value) if value: # only store non-zeros self.__data[key] = value elif key in self.__data: del self.__data[key] if self._LU: self._LU = None return def __iter__(self): for i in xrange(self.__rows): for j in xrange(self.__cols): yield self[i,j] def __mul__(self, other): if isinstance(other, self.ctx.matrix): # dot multiplication TODO: use Strassen's method? if self.__cols != other.__rows: raise ValueError('dimensions not compatible for multiplication') new = self.ctx.matrix(self.__rows, other.__cols) for i in xrange(self.__rows): for j in xrange(other.__cols): new[i, j] = self.ctx.fdot((self[i,k], other[k,j]) for k in xrange(other.__rows)) return new else: # try scalar multiplication new = self.ctx.matrix(self.__rows, self.__cols) for i in xrange(self.__rows): for j in xrange(self.__cols): new[i, j] = other * self[i, j] return new def __rmul__(self, other): # assume other is scalar and thus commutative if isinstance(other, self.ctx.matrix): raise TypeError("other should not be type of ctx.matrix") return self.__mul__(other) def __pow__(self, other): # avoid cyclic import problems #from linalg import inverse if not isinstance(other, int): raise ValueError('only integer exponents are supported') if not self.__rows == self.__cols: raise ValueError('only powers of square matrices are defined') n = other if n == 0: return self.ctx.eye(self.__rows) if n < 0: n = -n neg = True else: neg = False i = n y = 1 z = self.copy() while i != 0: if i % 2 == 1: y = y * z z = z*z i = i // 2 if neg: y = self.ctx.inverse(y) return y def __div__(self, other): # assume other is scalar and do element-wise divison assert not isinstance(other, self.ctx.matrix) new = self.ctx.matrix(self.__rows, self.__cols) for i in xrange(self.__rows): for j in xrange(self.__cols): new[i,j] = self[i,j] / other return new __truediv__ = __div__ def __add__(self, other): if isinstance(other, self.ctx.matrix): if not (self.__rows == other.__rows and self.__cols == other.__cols): raise ValueError('incompatible dimensions for addition') new = self.ctx.matrix(self.__rows, self.__cols) for i in xrange(self.__rows): for j in xrange(self.__cols): new[i,j] = self[i,j] + other[i,j] return new else: # assume other is scalar and add element-wise new = self.ctx.matrix(self.__rows, self.__cols) for i in xrange(self.__rows): for j in xrange(self.__cols): new[i,j] += self[i,j] + other return new def __radd__(self, other): return self.__add__(other) def __sub__(self, other): if isinstance(other, self.ctx.matrix) and not (self.__rows == other.__rows and self.__cols == other.__cols): raise ValueError('incompatible dimensions for subtraction') return self.__add__(other * (-1)) def __neg__(self): return (-1) * self def __rsub__(self, other): return -self + other def __eq__(self, other): return self.__rows == other.__rows and self.__cols == other.__cols \ and self.__data == other.__data def __len__(self): if self.rows == 1: return self.cols elif self.cols == 1: return self.rows else: return self.rows # do it like numpy def __getrows(self): return self.__rows def __setrows(self, value): for key in self.__data.copy(): if key[0] >= value: del self.__data[key] self.__rows = value rows = property(__getrows, __setrows, doc='number of rows') def __getcols(self): return self.__cols def __setcols(self, value): for key in self.__data.copy(): if key[1] >= value: del self.__data[key] self.__cols = value cols = property(__getcols, __setcols, doc='number of columns') def transpose(self): new = self.ctx.matrix(self.__cols, self.__rows) for i in xrange(self.__rows): for j in xrange(self.__cols): new[j,i] = self[i,j] return new T = property(transpose) def conjugate(self): return self.apply(self.ctx.conj) def transpose_conj(self): return self.conjugate().transpose() H = property(transpose_conj) def copy(self): new = self.ctx.matrix(self.__rows, self.__cols) new.__data = self.__data.copy() return new __copy__ = copy def column(self, n): m = self.ctx.matrix(self.rows, 1) for i in range(self.rows): m[i] = self[i,n] return m class MatrixMethods(object): def __init__(ctx): # XXX: subclass ctx.matrix = type('matrix', (_matrix,), {}) ctx.matrix.ctx = ctx ctx.matrix.convert = ctx.convert def eye(ctx, n, **kwargs): """ Create square identity matrix n x n. """ A = ctx.matrix(n, **kwargs) for i in xrange(n): A[i,i] = 1 return A def diag(ctx, diagonal, **kwargs): """ Create square diagonal matrix using given list. Example: >>> from mpmath import diag, mp >>> mp.pretty = False >>> diag([1, 2, 3]) matrix( [['1.0', '0.0', '0.0'], ['0.0', '2.0', '0.0'], ['0.0', '0.0', '3.0']]) """ A = ctx.matrix(len(diagonal), **kwargs) for i in xrange(len(diagonal)): A[i,i] = diagonal[i] return A def zeros(ctx, *args, **kwargs): """ Create matrix m x n filled with zeros. One given dimension will create square matrix n x n. Example: >>> from mpmath import zeros, mp >>> mp.pretty = False >>> zeros(2) matrix( [['0.0', '0.0'], ['0.0', '0.0']]) """ if len(args) == 1: m = n = args[0] elif len(args) == 2: m = args[0] n = args[1] else: raise TypeError('zeros expected at most 2 arguments, got %i' % len(args)) A = ctx.matrix(m, n, **kwargs) for i in xrange(m): for j in xrange(n): A[i,j] = 0 return A def ones(ctx, *args, **kwargs): """ Create matrix m x n filled with ones. One given dimension will create square matrix n x n. Example: >>> from mpmath import ones, mp >>> mp.pretty = False >>> ones(2) matrix( [['1.0', '1.0'], ['1.0', '1.0']]) """ if len(args) == 1: m = n = args[0] elif len(args) == 2: m = args[0] n = args[1] else: raise TypeError('ones expected at most 2 arguments, got %i' % len(args)) A = ctx.matrix(m, n, **kwargs) for i in xrange(m): for j in xrange(n): A[i,j] = 1 return A def hilbert(ctx, m, n=None): """ Create (pseudo) hilbert matrix m x n. One given dimension will create hilbert matrix n x n. The matrix is very ill-conditioned and symmetric, positive definite if square. """ if n is None: n = m A = ctx.matrix(m, n) for i in xrange(m): for j in xrange(n): A[i,j] = ctx.one / (i + j + 1) return A def randmatrix(ctx, m, n=None, min=0, max=1, **kwargs): """ Create a random m x n matrix. All values are >= min and >> from mpmath import randmatrix >>> randmatrix(2) # doctest:+SKIP matrix( [['0.53491598236191806', '0.57195669543302752'], ['0.85589992269513615', '0.82444367501382143']]) """ if not n: n = m A = ctx.matrix(m, n, **kwargs) for i in xrange(m): for j in xrange(n): A[i,j] = ctx.rand() * (max - min) + min return A def swap_row(ctx, A, i, j): """ Swap row i with row j. """ if i == j: return if isinstance(A, ctx.matrix): for k in xrange(A.cols): A[i,k], A[j,k] = A[j,k], A[i,k] elif isinstance(A, list): A[i], A[j] = A[j], A[i] else: raise TypeError('could not interpret type') def extend(ctx, A, b): """ Extend matrix A with column b and return result. """ if not isinstance(A, ctx.matrix): raise TypeError("A should be a type of ctx.matrix") if A.rows != len(b): raise ValueError("Value should be equal to len(b)") A = A.copy() A.cols += 1 for i in xrange(A.rows): A[i, A.cols-1] = b[i] return A def norm(ctx, x, p=2): r""" Gives the entrywise `p`-norm of an iterable *x*, i.e. the vector norm `\left(\sum_k |x_k|^p\right)^{1/p}`, for any given `1 \le p \le \infty`. Special cases: If *x* is not iterable, this just returns ``absmax(x)``. ``p=1`` gives the sum of absolute values. ``p=2`` is the standard Euclidean vector norm. ``p=inf`` gives the magnitude of the largest element. For *x* a matrix, ``p=2`` is the Frobenius norm. For operator matrix norms, use :func:`~mpmath.mnorm` instead. You can use the string 'inf' as well as float('inf') or mpf('inf') to specify the infinity norm. **Examples** >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> x = matrix([-10, 2, 100]) >>> norm(x, 1) mpf('112.0') >>> norm(x, 2) mpf('100.5186549850325') >>> norm(x, inf) mpf('100.0') """ try: iter(x) except TypeError: return ctx.absmax(x) if type(p) is not int: p = ctx.convert(p) if p == ctx.inf: return max(ctx.absmax(i) for i in x) elif p == 1: return ctx.fsum(x, absolute=1) elif p == 2: return ctx.sqrt(ctx.fsum(x, absolute=1, squared=1)) elif p > 1: return ctx.nthroot(ctx.fsum(abs(i)**p for i in x), p) else: raise ValueError('p has to be >= 1') def mnorm(ctx, A, p=1): r""" Gives the matrix (operator) `p`-norm of A. Currently ``p=1`` and ``p=inf`` are supported: ``p=1`` gives the 1-norm (maximal column sum) ``p=inf`` gives the `\infty`-norm (maximal row sum). You can use the string 'inf' as well as float('inf') or mpf('inf') ``p=2`` (not implemented) for a square matrix is the usual spectral matrix norm, i.e. the largest singular value. ``p='f'`` (or 'F', 'fro', 'Frobenius, 'frobenius') gives the Frobenius norm, which is the elementwise 2-norm. The Frobenius norm is an approximation of the spectral norm and satisfies .. math :: \frac{1}{\sqrt{\mathrm{rank}(A)}} \|A\|_F \le \|A\|_2 \le \|A\|_F The Frobenius norm lacks some mathematical properties that might be expected of a norm. For general elementwise `p`-norms, use :func:`~mpmath.norm` instead. **Examples** >>> from mpmath import * >>> mp.dps = 15; mp.pretty = False >>> A = matrix([[1, -1000], [100, 50]]) >>> mnorm(A, 1) mpf('1050.0') >>> mnorm(A, inf) mpf('1001.0') >>> mnorm(A, 'F') mpf('1006.2310867787777') """ A = ctx.matrix(A) if type(p) is not int: if type(p) is str and 'frobenius'.startswith(p.lower()): return ctx.norm(A, 2) p = ctx.convert(p) m, n = A.rows, A.cols if p == 1: return max(ctx.fsum((A[i,j] for i in xrange(m)), absolute=1) for j in xrange(n)) elif p == ctx.inf: return max(ctx.fsum((A[i,j] for j in xrange(n)), absolute=1) for i in xrange(m)) else: raise NotImplementedError("matrix p-norm for arbitrary p") if __name__ == '__main__': import doctest doctest.testmod() mpmath-1.1.0/mpmath/rational.py000066400000000000000000000135221340375245600164640ustar00rootroot00000000000000import operator import sys from .libmp import int_types, mpf_hash, bitcount, from_man_exp, HASH_MODULUS new = object.__new__ def create_reduced(p, q, _cache={}): key = p, q if key in _cache: return _cache[key] x, y = p, q while y: x, y = y, x % y if x != 1: p //= x q //= x v = new(mpq) v._mpq_ = p, q # Speedup integers, half-integers and other small fractions if q <= 4 and abs(key[0]) < 100: _cache[key] = v return v class mpq(object): """ Exact rational type, currently only intended for internal use. """ __slots__ = ["_mpq_"] def __new__(cls, p, q=1): if type(p) is tuple: p, q = p elif hasattr(p, '_mpq_'): p, q = p._mpq_ return create_reduced(p, q) def __repr__(s): return "mpq(%s,%s)" % s._mpq_ def __str__(s): return "(%s/%s)" % s._mpq_ def __int__(s): a, b = s._mpq_ return a // b def __nonzero__(s): return bool(s._mpq_[0]) __bool__ = __nonzero__ def __hash__(s): a, b = s._mpq_ if sys.version >= "3.2": inverse = pow(b, HASH_MODULUS-2, HASH_MODULUS) if not inverse: h = sys.hash_info.inf else: h = (abs(a) * inverse) % HASH_MODULUS if a < 0: h = -h if h == -1: h = -2 return h else: if b == 1: return hash(a) # Power of two: mpf compatible hash if not (b & (b-1)): return mpf_hash(from_man_exp(a, 1-bitcount(b))) return hash((a,b)) def __eq__(s, t): ttype = type(t) if ttype is mpq: return s._mpq_ == t._mpq_ if ttype in int_types: a, b = s._mpq_ if b != 1: return False return a == t return NotImplemented def __ne__(s, t): ttype = type(t) if ttype is mpq: return s._mpq_ != t._mpq_ if ttype in int_types: a, b = s._mpq_ if b != 1: return True return a != t return NotImplemented def _cmp(s, t, op): ttype = type(t) if ttype in int_types: a, b = s._mpq_ return op(a, t*b) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return op(a*d, b*c) return NotImplementedError def __lt__(s, t): return s._cmp(t, operator.lt) def __le__(s, t): return s._cmp(t, operator.le) def __gt__(s, t): return s._cmp(t, operator.gt) def __ge__(s, t): return s._cmp(t, operator.ge) def __abs__(s): a, b = s._mpq_ if a >= 0: return s v = new(mpq) v._mpq_ = -a, b return v def __neg__(s): a, b = s._mpq_ v = new(mpq) v._mpq_ = -a, b return v def __pos__(s): return s def __add__(s, t): ttype = type(t) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return create_reduced(a*d+b*c, b*d) if ttype in int_types: a, b = s._mpq_ v = new(mpq) v._mpq_ = a+b*t, b return v return NotImplemented __radd__ = __add__ def __sub__(s, t): ttype = type(t) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return create_reduced(a*d-b*c, b*d) if ttype in int_types: a, b = s._mpq_ v = new(mpq) v._mpq_ = a-b*t, b return v return NotImplemented def __rsub__(s, t): ttype = type(t) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return create_reduced(b*c-a*d, b*d) if ttype in int_types: a, b = s._mpq_ v = new(mpq) v._mpq_ = b*t-a, b return v return NotImplemented def __mul__(s, t): ttype = type(t) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return create_reduced(a*c, b*d) if ttype in int_types: a, b = s._mpq_ return create_reduced(a*t, b) return NotImplemented __rmul__ = __mul__ def __div__(s, t): ttype = type(t) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return create_reduced(a*d, b*c) if ttype in int_types: a, b = s._mpq_ return create_reduced(a, b*t) return NotImplemented def __rdiv__(s, t): ttype = type(t) if ttype is mpq: a, b = s._mpq_ c, d = t._mpq_ return create_reduced(b*c, a*d) if ttype in int_types: a, b = s._mpq_ return create_reduced(b*t, a) return NotImplemented def __pow__(s, t): ttype = type(t) if ttype in int_types: a, b = s._mpq_ if t: if t < 0: a, b, t = b, a, -t v = new(mpq) v._mpq_ = a**t, b**t return v raise ZeroDivisionError return NotImplemented mpq_1 = mpq((1,1)) mpq_0 = mpq((0,1)) mpq_1_2 = mpq((1,2)) mpq_3_2 = mpq((3,2)) mpq_1_4 = mpq((1,4)) mpq_1_16 = mpq((1,16)) mpq_3_16 = mpq((3,16)) mpq_5_2 = mpq((5,2)) mpq_3_4 = mpq((3,4)) mpq_7_4 = mpq((7,4)) mpq_5_4 = mpq((5,4)) # Register with "numbers" ABC # We do not subclass, hence we do not use the @abstractmethod checks. While # this is less invasive it may turn out that we do not actually support # parts of the expected interfaces. See # http://docs.python.org/2/library/numbers.html for list of abstract # methods. try: import numbers numbers.Rational.register(mpq) except ImportError: pass mpmath-1.1.0/mpmath/tests/000077500000000000000000000000001340375245600154405ustar00rootroot00000000000000mpmath-1.1.0/mpmath/tests/__init__.py000066400000000000000000000000001340375245600175370ustar00rootroot00000000000000mpmath-1.1.0/mpmath/tests/extratest_gamma.py000066400000000000000000000160741340375245600212070ustar00rootroot00000000000000from mpmath import * from mpmath.libmp import ifac import sys if "-dps" in sys.argv: maxdps = int(sys.argv[sys.argv.index("-dps")+1]) else: maxdps = 1000 raise_ = "-raise" in sys.argv errcount = 0 def check(name, func, z, y): global errcount try: x = func(z) except: errcount += 1 if raise_: raise print() print(name) print("EXCEPTION") import traceback traceback.print_tb(sys.exc_info()[2]) print() return xre = x.real xim = x.imag yre = y.real yim = y.imag tol = eps*8 err = 0 if abs(xre-yre) > abs(yre)*tol: err = 1 print() print("Error! %s (re = %s, wanted %s, err=%s)" % (name, nstr(xre,10), nstr(yre,10), nstr(abs(xre-yre)))) errcount += 1 if raise_: raise SystemExit if abs(xim-yim) > abs(yim)*tol: err = 1 print() print("Error! %s (im = %s, wanted %s, err=%s)" % (name, nstr(xim,10), nstr(yim,10), nstr(abs(xim-yim)))) errcount += 1 if raise_: raise SystemExit if not err: sys.stdout.write("%s ok; " % name) def testcase(case): z, result = case print("Testing z =", z) mp.dps = 1010 z = eval(z) mp.dps = maxdps + 50 if result is None: gamma_val = gamma(z) loggamma_val = loggamma(z) factorial_val = factorial(z) rgamma_val = rgamma(z) else: loggamma_val = eval(result) gamma_val = exp(loggamma_val) factorial_val = z * gamma_val rgamma_val = 1/gamma_val for dps in [5, 10, 15, 25, 40, 60, 90, 120, 250, 600, 1000, 1800, 3600]: if dps > maxdps: break mp.dps = dps print("dps = %s" % dps) check("gamma", gamma, z, gamma_val) check("rgamma", rgamma, z, rgamma_val) check("loggamma", loggamma, z, loggamma_val) check("factorial", factorial, z, factorial_val) print() mp.dps = 15 testcases = [] # Basic values for n in list(range(1,200)) + list(range(201,2000,17)): testcases.append(["%s" % n, None]) for n in range(-200,200): testcases.append(["%s+0.5" % n, None]) testcases.append(["%s+0.37" % n, None]) testcases += [\ ["(0.1+1j)", None], ["(-0.1+1j)", None], ["(0.1-1j)", None], ["(-0.1-1j)", None], ["10j", None], ["-10j", None], ["100j", None], ["10000j", None], ["-10000000j", None], ["(10**100)*j", None], ["125+(10**100)*j", None], ["-125+(10**100)*j", None], ["(10**10)*(1+j)", None], ["(10**10)*(-1+j)", None], ["(10**100)*(1+j)", None], ["(10**100)*(-1+j)", None], ["(1.5-1j)", None], ["(6+4j)", None], ["(4+1j)", None], ["(3.5+2j)", None], ["(1.5-1j)", None], ["(-6-4j)", None], ["(-2-3j)", None], ["(-2.5-2j)", None], ["(4+1j)", None], ["(3+3j)", None], ["(2-2j)", None], ["1", "0"], ["2", "0"], ["3", "log(2)"], ["4", "log(6)"], ["5", "log(24)"], ["0.5", "log(pi)/2"], ["1.5", "log(sqrt(pi)/2)"], ["2.5", "log(3*sqrt(pi)/4)"], ["mpf('0.37')", None], ["0.25", "log(sqrt(2*sqrt(2*pi**3)/agm(1,sqrt(2))))"], ["-0.4", None], ["mpf('-1.9')", None], ["mpf('12.8')", None], ["mpf('33.7')", None], ["mpf('95.2')", None], ["mpf('160.3')", None], ["mpf('2057.8')", None], ["25", "log(ifac(24))"], ["80", "log(ifac(79))"], ["500", "log(ifac(500-1))"], ["8000", "log(ifac(8000-1))"], ["8000.5", None], ["mpf('8000.1')", None], ["mpf('1.37e10')", None], ["mpf('1.37e10')*(1+j)", None], ["mpf('1.37e10')*(-1+j)", None], ["mpf('1.37e10')*(-1-j)", None], ["mpf('1.37e10')*(-1+j)", None], ["mpf('1.37e100')", None], ["mpf('1.37e100')*(1+j)", None], ["mpf('1.37e100')*(-1+j)", None], ["mpf('1.37e100')*(-1-j)", None], ["mpf('1.37e100')*(-1+j)", None], ["3+4j", "mpc('" "-1.7566267846037841105306041816232757851567066070613445016197619371316057169" "4723618263960834804618463052988607348289672535780644470689771115236512106002" "5970873471563240537307638968509556191696167970488390423963867031934333890838" "8009531786948197210025029725361069435208930363494971027388382086721660805397" "9163230643216054580167976201709951509519218635460317367338612500626714783631" "7498317478048447525674016344322545858832610325861086336204591943822302971823" "5161814175530618223688296232894588415495615809337292518431903058265147109853" "1710568942184987827643886816200452860853873815413367529829631430146227470517" "6579967222200868632179482214312673161276976117132204633283806161971389519137" "1243359764435612951384238091232760634271570950240717650166551484551654327989" "9360285030081716934130446150245110557038117075172576825490035434069388648124" "6678152254554001586736120762641422590778766100376515737713938521275749049949" "1284143906816424244705094759339932733567910991920631339597278805393743140853" "391550313363278558195609260225928','" "4.74266443803465792819488940755002274088830335171164611359052405215840070271" "5906813009373171139767051863542508136875688550817670379002790304870822775498" "2809996675877564504192565392367259119610438951593128982646945990372179860613" "4294436498090428077839141927485901735557543641049637962003652638924845391650" "9546290137755550107224907606529385248390667634297183361902055842228798984200" "9591180450211798341715874477629099687609819466457990642030707080894518168924" "6805549314043258530272479246115112769957368212585759640878745385160943755234" "9398036774908108204370323896757543121853650025529763655312360354244898913463" "7115955702828838923393113618205074162812089732064414530813087483533203244056" "0546577484241423134079056537777170351934430586103623577814746004431994179990" "5318522939077992613855205801498201930221975721246498720895122345420698451980" "0051215797310305885845964334761831751370672996984756815410977750799748813563" "8784405288158432214886648743541773208808731479748217023665577802702269468013" "673719173759245720489020315779001')"], ] for z in [4, 14, 34, 64]: testcases.append(["(2+j)*%s/3" % z, None]) testcases.append(["(-2+j)*%s/3" % z, None]) testcases.append(["(1+2*j)*%s/3" % z, None]) testcases.append(["(2-j)*%s/3" % z, None]) testcases.append(["(20+j)*%s/3" % z, None]) testcases.append(["(-20+j)*%s/3" % z, None]) testcases.append(["(1+20*j)*%s/3" % z, None]) testcases.append(["(20-j)*%s/3" % z, None]) testcases.append(["(200+j)*%s/3" % z, None]) testcases.append(["(-200+j)*%s/3" % z, None]) testcases.append(["(1+200*j)*%s/3" % z, None]) testcases.append(["(200-j)*%s/3" % z, None]) # Poles for n in [0,1,2,3,4,25,-1,-2,-3,-4,-20,-21,-50,-51,-200,-201,-20000,-20001]: for t in ['1e-5', '1e-20', '1e-100', '1e-10000']: testcases.append(["fadd(%s,'%s',exact=True)" % (n, t), None]) testcases.append(["fsub(%s,'%s',exact=True)" % (n, t), None]) testcases.append(["fadd(%s,'%sj',exact=True)" % (n, t), None]) testcases.append(["fsub(%s,'%sj',exact=True)" % (n, t), None]) if __name__ == "__main__": from timeit import default_timer as clock tot_time = 0.0 for case in testcases: t1 = clock() testcase(case) t2 = clock() print("Test time:", t2-t1) print() tot_time += (t2-t1) print("Total time:", tot_time) print("Errors:", errcount) mpmath-1.1.0/mpmath/tests/extratest_zeta.py000066400000000000000000000017531340375245600210660ustar00rootroot00000000000000from mpmath import zetazero from timeit import default_timer as clock def test_zetazero(): cases = [\ (399999999, 156762524.6750591511), (241389216, 97490234.2276711795), (526196239, 202950727.691229534), (542964976, 209039046.578535272), (1048449112, 388858885.231056486), (1048449113, 388858885.384337406), (1048449114, 388858886.002285122), (1048449115, 388858886.00239369), (1048449116, 388858886.690745053) ] for n, v in cases: print(n, v) t1 = clock() ok = zetazero(n).ae(complex(0.5,v)) t2 = clock() print("ok =", ok, ("(time = %s)" % round(t2-t1,3))) print("Now computing two huge zeros (this may take hours)") print("Computing zetazero(8637740722917)") ok = zetazero(8637740722917).ae(complex(0.5,2124447368584.39296466152)) print("ok =", ok) ok = zetazero(8637740722918).ae(complex(0.5,2124447368584.39298170604)) print("ok =", ok) if __name__ == "__main__": test_zetazero() mpmath-1.1.0/mpmath/tests/runtests.py000066400000000000000000000113221340375245600177000ustar00rootroot00000000000000#!/usr/bin/env python """ python runtests.py -py Use py.test to run tests (more useful for debugging) python runtests.py -coverage Generate test coverage report. Statistics are written to /tmp python runtests.py -profile Generate profile stats (this is much slower) python runtests.py -nogmpy Run tests without using GMPY even if it exists python runtests.py -strict Enforce extra tests in normalize() python runtests.py -local Insert '../..' at the beginning of sys.path to use local mpmath Additional arguments are used to filter the tests to run. Only files that have one of the arguments in their name are executed. """ import sys, os, traceback profile = False if "-profile" in sys.argv: sys.argv.remove('-profile') profile = True coverage = False if "-coverage" in sys.argv: sys.argv.remove('-coverage') coverage = True if "-nogmpy" in sys.argv: sys.argv.remove('-nogmpy') os.environ['MPMATH_NOGMPY'] = 'Y' if "-strict" in sys.argv: sys.argv.remove('-strict') os.environ['MPMATH_STRICT'] = 'Y' if "-local" in sys.argv: sys.argv.remove('-local') importdir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..')) else: importdir = '' # TODO: add a flag for this testdir = '' def testit(importdir='', testdir=''): """Run all tests in testdir while importing from importdir.""" if importdir: sys.path.insert(1, importdir) if testdir: sys.path.insert(1, testdir) import os.path import mpmath print("mpmath imported from %s" % os.path.dirname(mpmath.__file__)) print("mpmath backend: %s" % mpmath.libmp.backend.BACKEND) print("mpmath mp class: %s" % repr(mpmath.mp)) print("mpmath version: %s" % mpmath.__version__) print("Python version: %s" % sys.version) print("") if "-py" in sys.argv: sys.argv.remove('-py') import py py.test.cmdline.main() else: import glob from timeit import default_timer as clock modules = [] args = sys.argv[1:] # search for tests in directory of this file if not otherwise specified if not testdir: pattern = os.path.dirname(sys.argv[0]) else: pattern = testdir if pattern: pattern += '/' pattern += 'test*.py' # look for tests (respecting specified filter) for f in glob.glob(pattern): name = os.path.splitext(os.path.basename(f))[0] # If run as a script, only run tests given as args, if any are given if args and __name__ == "__main__": ok = False for arg in args: if arg in name: ok = True break if not ok: continue module = __import__(name) priority = module.__dict__.get('priority', 100) if priority == 666: modules = [[priority, name, module]] break modules.append([priority, name, module]) # execute tests modules.sort() tstart = clock() for priority, name, module in modules: print(name) for f in sorted(module.__dict__.keys()): if f.startswith('test_'): if coverage and ('numpy' in f): continue sys.stdout.write(" " + f[5:].ljust(25) + " ") t1 = clock() try: module.__dict__[f]() except: etype, evalue, trb = sys.exc_info() if etype in (KeyboardInterrupt, SystemExit): raise print("") print("TEST FAILED!") print("") traceback.print_exc() t2 = clock() print("ok " + " " + ("%.7f" % (t2-t1)) + " s") tend = clock() print("") print("finished tests in " + ("%.2f" % (tend-tstart)) + " seconds") # clean sys.path if importdir: sys.path.remove(importdir) if testdir: sys.path.remove(testdir) if __name__ == '__main__': if profile: import cProfile cProfile.run("testit('%s', '%s')" % (importdir, testdir), sort=1) elif coverage: import trace tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], trace=0, count=1) tracer.run('testit(importdir, testdir)') r = tracer.results() r.write_results(show_missing=True, summary=True, coverdir="/tmp") else: testit(importdir, testdir) mpmath-1.1.0/mpmath/tests/test_basic_ops.py000066400000000000000000000355371340375245600210300ustar00rootroot00000000000000import mpmath from mpmath import * from mpmath.libmp import * import random import sys try: long = long except NameError: long = int def test_type_compare(): assert mpf(2) == mpc(2,0) assert mpf(0) == mpc(0) assert mpf(2) != mpc(2, 0.00001) assert mpf(2) == 2.0 assert mpf(2) != 3.0 assert mpf(2) == 2 assert mpf(2) != '2.0' assert mpc(2) != '2.0' def test_add(): assert mpf(2.5) + mpf(3) == 5.5 assert mpf(2.5) + 3 == 5.5 assert mpf(2.5) + 3.0 == 5.5 assert 3 + mpf(2.5) == 5.5 assert 3.0 + mpf(2.5) == 5.5 assert (3+0j) + mpf(2.5) == 5.5 assert mpc(2.5) + mpf(3) == 5.5 assert mpc(2.5) + 3 == 5.5 assert mpc(2.5) + 3.0 == 5.5 assert mpc(2.5) + (3+0j) == 5.5 assert 3 + mpc(2.5) == 5.5 assert 3.0 + mpc(2.5) == 5.5 assert (3+0j) + mpc(2.5) == 5.5 def test_sub(): assert mpf(2.5) - mpf(3) == -0.5 assert mpf(2.5) - 3 == -0.5 assert mpf(2.5) - 3.0 == -0.5 assert 3 - mpf(2.5) == 0.5 assert 3.0 - mpf(2.5) == 0.5 assert (3+0j) - mpf(2.5) == 0.5 assert mpc(2.5) - mpf(3) == -0.5 assert mpc(2.5) - 3 == -0.5 assert mpc(2.5) - 3.0 == -0.5 assert mpc(2.5) - (3+0j) == -0.5 assert 3 - mpc(2.5) == 0.5 assert 3.0 - mpc(2.5) == 0.5 assert (3+0j) - mpc(2.5) == 0.5 def test_mul(): assert mpf(2.5) * mpf(3) == 7.5 assert mpf(2.5) * 3 == 7.5 assert mpf(2.5) * 3.0 == 7.5 assert 3 * mpf(2.5) == 7.5 assert 3.0 * mpf(2.5) == 7.5 assert (3+0j) * mpf(2.5) == 7.5 assert mpc(2.5) * mpf(3) == 7.5 assert mpc(2.5) * 3 == 7.5 assert mpc(2.5) * 3.0 == 7.5 assert mpc(2.5) * (3+0j) == 7.5 assert 3 * mpc(2.5) == 7.5 assert 3.0 * mpc(2.5) == 7.5 assert (3+0j) * mpc(2.5) == 7.5 def test_div(): assert mpf(6) / mpf(3) == 2.0 assert mpf(6) / 3 == 2.0 assert mpf(6) / 3.0 == 2.0 assert 6 / mpf(3) == 2.0 assert 6.0 / mpf(3) == 2.0 assert (6+0j) / mpf(3.0) == 2.0 assert mpc(6) / mpf(3) == 2.0 assert mpc(6) / 3 == 2.0 assert mpc(6) / 3.0 == 2.0 assert mpc(6) / (3+0j) == 2.0 assert 6 / mpc(3) == 2.0 assert 6.0 / mpc(3) == 2.0 assert (6+0j) / mpc(3) == 2.0 def test_pow(): assert mpf(6) ** mpf(3) == 216.0 assert mpf(6) ** 3 == 216.0 assert mpf(6) ** 3.0 == 216.0 assert 6 ** mpf(3) == 216.0 assert 6.0 ** mpf(3) == 216.0 assert (6+0j) ** mpf(3.0) == 216.0 assert mpc(6) ** mpf(3) == 216.0 assert mpc(6) ** 3 == 216.0 assert mpc(6) ** 3.0 == 216.0 assert mpc(6) ** (3+0j) == 216.0 assert 6 ** mpc(3) == 216.0 assert 6.0 ** mpc(3) == 216.0 assert (6+0j) ** mpc(3) == 216.0 def test_mixed_misc(): assert 1 + mpf(3) == mpf(3) + 1 == 4 assert 1 - mpf(3) == -(mpf(3) - 1) == -2 assert 3 * mpf(2) == mpf(2) * 3 == 6 assert 6 / mpf(2) == mpf(6) / 2 == 3 assert 1.0 + mpf(3) == mpf(3) + 1.0 == 4 assert 1.0 - mpf(3) == -(mpf(3) - 1.0) == -2 assert 3.0 * mpf(2) == mpf(2) * 3.0 == 6 assert 6.0 / mpf(2) == mpf(6) / 2.0 == 3 def test_add_misc(): mp.dps = 15 assert mpf(4) + mpf(-70) == -66 assert mpf(1) + mpf(1.1)/80 == 1 + 1.1/80 assert mpf((1, 10000000000)) + mpf(3) == mpf((1, 10000000000)) assert mpf(3) + mpf((1, 10000000000)) == mpf((1, 10000000000)) assert mpf((1, -10000000000)) + mpf(3) == mpf(3) assert mpf(3) + mpf((1, -10000000000)) == mpf(3) assert mpf(1) + 1e-15 != 1 assert mpf(1) + 1e-20 == 1 assert mpf(1.07e-22) + 0 == mpf(1.07e-22) assert mpf(0) + mpf(1.07e-22) == mpf(1.07e-22) def test_complex_misc(): # many more tests needed assert 1 + mpc(2) == 3 assert not mpc(2).ae(2 + 1e-13) assert mpc(2+1e-15j).ae(2) def test_complex_zeros(): for a in [0,2]: for b in [0,3]: for c in [0,4]: for d in [0,5]: assert mpc(a,b)*mpc(c,d) == complex(a,b)*complex(c,d) def test_hash(): for i in range(-256, 256): assert hash(mpf(i)) == hash(i) assert hash(mpf(0.5)) == hash(0.5) assert hash(mpc(2,3)) == hash(2+3j) # Check that this doesn't fail assert hash(inf) # Check that overflow doesn't assign equal hashes to large numbers assert hash(mpf('1e1000')) != hash('1e10000') assert hash(mpc(100,'1e1000')) != hash(mpc(200,'1e1000')) from mpmath.rational import mpq assert hash(mp.mpq(1,3)) assert hash(mp.mpq(0,1)) == 0 assert hash(mp.mpq(-1,1)) == hash(-1) assert hash(mp.mpq(1,1)) == hash(1) assert hash(mp.mpq(5,1)) == hash(5) assert hash(mp.mpq(1,2)) == hash(0.5) if sys.version >= "3.2": assert hash(mpf(1)*2**2000) == hash(2**2000) assert hash(mpf(1)/2**2000) == hash(mpq(1,2**2000)) # Advanced rounding test def test_add_rounding(): mp.dps = 15 a = from_float(1e-50) assert mpf_sub(mpf_add(fone, a, 53, round_up), fone, 53, round_up) == from_float(2.2204460492503131e-16) assert mpf_sub(fone, a, 53, round_up) == fone assert mpf_sub(fone, mpf_sub(fone, a, 53, round_down), 53, round_down) == from_float(1.1102230246251565e-16) assert mpf_add(fone, a, 53, round_down) == fone def test_almost_equal(): assert mpf(1.2).ae(mpf(1.20000001), 1e-7) assert not mpf(1.2).ae(mpf(1.20000001), 1e-9) assert not mpf(-0.7818314824680298).ae(mpf(-0.774695868667929)) def test_arithmetic_functions(): import operator ops = [(operator.add, fadd), (operator.sub, fsub), (operator.mul, fmul), (operator.truediv, fdiv)] a = mpf(0.27) b = mpf(1.13) c = mpc(0.51+2.16j) d = mpc(1.08-0.99j) for x in [a,b,c,d]: for y in [a,b,c,d]: for op, fop in ops: if fop is not fdiv: mp.prec = 200 z0 = op(x,y) mp.prec = 60 z1 = op(x,y) mp.prec = 53 z2 = op(x,y) assert fop(x, y, prec=60) == z1 assert fop(x, y) == z2 if fop is not fdiv: assert fop(x, y, prec=inf) == z0 assert fop(x, y, dps=inf) == z0 assert fop(x, y, exact=True) == z0 assert fneg(fneg(z1, exact=True), prec=inf) == z1 assert fneg(z1) == -(+z1) mp.dps = 15 def test_exact_integer_arithmetic(): # XXX: re-fix this so that all operations are tested with all rounding modes random.seed(0) for prec in [6, 10, 25, 40, 100, 250, 725]: for rounding in ['d', 'u', 'f', 'c', 'n']: mp.dps = prec M = 10**(prec-2) M2 = 10**(prec//2-2) for i in range(10): a = random.randint(-M, M) b = random.randint(-M, M) assert mpf(a, rounding=rounding) == a assert int(mpf(a, rounding=rounding)) == a assert int(mpf(str(a), rounding=rounding)) == a assert mpf(a) + mpf(b) == a + b assert mpf(a) - mpf(b) == a - b assert -mpf(a) == -a a = random.randint(-M2, M2) b = random.randint(-M2, M2) assert mpf(a) * mpf(b) == a*b assert mpf_mul(from_int(a), from_int(b), mp.prec, rounding) == from_int(a*b) mp.dps = 15 def test_odd_int_bug(): assert to_int(from_int(3), round_nearest) == 3 def test_str_1000_digits(): mp.dps = 1001 # last digit may be wrong assert str(mpf(2)**0.5)[-10:-1] == '9518488472'[:9] assert str(pi)[-10:-1] == '2164201989'[:9] mp.dps = 15 def test_str_10000_digits(): mp.dps = 10001 # last digit may be wrong assert str(mpf(2)**0.5)[-10:-1] == '5873258351'[:9] assert str(pi)[-10:-1] == '5256375678'[:9] mp.dps = 15 def test_monitor(): f = lambda x: x**2 a = [] b = [] g = monitor(f, a.append, b.append) assert g(3) == 9 assert g(4) == 16 assert a[0] == ((3,), {}) assert b[0] == 9 def test_nint_distance(): assert nint_distance(mpf(-3)) == (-3, -inf) assert nint_distance(mpc(-3)) == (-3, -inf) assert nint_distance(mpf(-3.1)) == (-3, -3) assert nint_distance(mpf(-3.01)) == (-3, -6) assert nint_distance(mpf(-3.001)) == (-3, -9) assert nint_distance(mpf(-3.0001)) == (-3, -13) assert nint_distance(mpf(-2.9)) == (-3, -3) assert nint_distance(mpf(-2.99)) == (-3, -6) assert nint_distance(mpf(-2.999)) == (-3, -9) assert nint_distance(mpf(-2.9999)) == (-3, -13) assert nint_distance(mpc(-3+0.1j)) == (-3, -3) assert nint_distance(mpc(-3+0.01j)) == (-3, -6) assert nint_distance(mpc(-3.1+0.1j)) == (-3, -3) assert nint_distance(mpc(-3.01+0.01j)) == (-3, -6) assert nint_distance(mpc(-3.001+0.001j)) == (-3, -9) assert nint_distance(mpf(0)) == (0, -inf) assert nint_distance(mpf(0.01)) == (0, -6) assert nint_distance(mpf('1e-100')) == (0, -332) def test_floor_ceil_nint_frac(): mp.dps = 15 for n in range(-10,10): assert floor(n) == n assert floor(n+0.5) == n assert ceil(n) == n assert ceil(n+0.5) == n+1 assert nint(n) == n # nint rounds to even if n % 2 == 1: assert nint(n+0.5) == n+1 else: assert nint(n+0.5) == n assert floor(inf) == inf assert floor(ninf) == ninf assert isnan(floor(nan)) assert ceil(inf) == inf assert ceil(ninf) == ninf assert isnan(ceil(nan)) assert nint(inf) == inf assert nint(ninf) == ninf assert isnan(nint(nan)) assert floor(0.1) == 0 assert floor(0.9) == 0 assert floor(-0.1) == -1 assert floor(-0.9) == -1 assert floor(10000000000.1) == 10000000000 assert floor(10000000000.9) == 10000000000 assert floor(-10000000000.1) == -10000000000-1 assert floor(-10000000000.9) == -10000000000-1 assert floor(1e-100) == 0 assert floor(-1e-100) == -1 assert floor(1e100) == 1e100 assert floor(-1e100) == -1e100 assert ceil(0.1) == 1 assert ceil(0.9) == 1 assert ceil(-0.1) == 0 assert ceil(-0.9) == 0 assert ceil(10000000000.1) == 10000000000+1 assert ceil(10000000000.9) == 10000000000+1 assert ceil(-10000000000.1) == -10000000000 assert ceil(-10000000000.9) == -10000000000 assert ceil(1e-100) == 1 assert ceil(-1e-100) == 0 assert ceil(1e100) == 1e100 assert ceil(-1e100) == -1e100 assert nint(0.1) == 0 assert nint(0.9) == 1 assert nint(-0.1) == 0 assert nint(-0.9) == -1 assert nint(10000000000.1) == 10000000000 assert nint(10000000000.9) == 10000000000+1 assert nint(-10000000000.1) == -10000000000 assert nint(-10000000000.9) == -10000000000-1 assert nint(1e-100) == 0 assert nint(-1e-100) == 0 assert nint(1e100) == 1e100 assert nint(-1e100) == -1e100 assert floor(3.2+4.6j) == 3+4j assert ceil(3.2+4.6j) == 4+5j assert nint(3.2+4.6j) == 3+5j for n in range(-10,10): assert frac(n) == 0 assert frac(0.25) == 0.25 assert frac(1.25) == 0.25 assert frac(2.25) == 0.25 assert frac(-0.25) == 0.75 assert frac(-1.25) == 0.75 assert frac(-2.25) == 0.75 assert frac('1e100000000000000') == 0 u = mpf('1e-100000000000000') assert frac(u) == u assert frac(-u) == 1 # rounding! u = mpf('1e-400') assert frac(-u, prec=0) == fsub(1, u, exact=True) assert frac(3.25+4.75j) == 0.25+0.75j def test_isnan_etc(): from mpmath.rational import mpq assert isnan(nan) == True assert isnan(3) == False assert isnan(mpf(3)) == False assert isnan(inf) == False assert isnan(mpc(2,nan)) == True assert isnan(mpc(2,nan)) == True assert isnan(mpc(nan,nan)) == True assert isnan(mpc(2,2)) == False assert isnan(mpc(nan,inf)) == True assert isnan(mpc(inf,inf)) == False assert isnan(mpq((3,2))) == False assert isnan(mpq((0,1))) == False assert isinf(inf) == True assert isinf(-inf) == True assert isinf(3) == False assert isinf(nan) == False assert isinf(3+4j) == False assert isinf(mpc(inf)) == True assert isinf(mpc(3,inf)) == True assert isinf(mpc(inf,3)) == True assert isinf(mpc(inf,inf)) == True assert isinf(mpc(nan,inf)) == True assert isinf(mpc(inf,nan)) == True assert isinf(mpc(nan,nan)) == False assert isinf(mpq((3,2))) == False assert isinf(mpq((0,1))) == False assert isnormal(3) == True assert isnormal(3.5) == True assert isnormal(mpf(3.5)) == True assert isnormal(0) == False assert isnormal(mpf(0)) == False assert isnormal(0.0) == False assert isnormal(inf) == False assert isnormal(-inf) == False assert isnormal(nan) == False assert isnormal(float(inf)) == False assert isnormal(mpc(0,0)) == False assert isnormal(mpc(3,0)) == True assert isnormal(mpc(0,3)) == True assert isnormal(mpc(3,3)) == True assert isnormal(mpc(0,nan)) == False assert isnormal(mpc(0,inf)) == False assert isnormal(mpc(3,nan)) == False assert isnormal(mpc(3,inf)) == False assert isnormal(mpc(3,-inf)) == False assert isnormal(mpc(nan,0)) == False assert isnormal(mpc(inf,0)) == False assert isnormal(mpc(nan,3)) == False assert isnormal(mpc(inf,3)) == False assert isnormal(mpc(inf,nan)) == False assert isnormal(mpc(nan,inf)) == False assert isnormal(mpc(nan,nan)) == False assert isnormal(mpc(inf,inf)) == False assert isnormal(mpq((3,2))) == True assert isnormal(mpq((0,1))) == False assert isint(3) == True assert isint(0) == True assert isint(long(3)) == True assert isint(long(0)) == True assert isint(mpf(3)) == True assert isint(mpf(0)) == True assert isint(mpf(-3)) == True assert isint(mpf(3.2)) == False assert isint(3.2) == False assert isint(nan) == False assert isint(inf) == False assert isint(-inf) == False assert isint(mpc(0)) == True assert isint(mpc(3)) == True assert isint(mpc(3.2)) == False assert isint(mpc(3,inf)) == False assert isint(mpc(inf)) == False assert isint(mpc(3,2)) == False assert isint(mpc(0,2)) == False assert isint(mpc(3,2),gaussian=True) == True assert isint(mpc(3,0),gaussian=True) == True assert isint(mpc(0,3),gaussian=True) == True assert isint(3+4j) == False assert isint(3+4j, gaussian=True) == True assert isint(3+0j) == True assert isint(mpq((3,2))) == False assert isint(mpq((3,9))) == False assert isint(mpq((9,3))) == True assert isint(mpq((0,4))) == True assert isint(mpq((1,1))) == True assert isint(mpq((-1,1))) == True assert mp.isnpint(0) == True assert mp.isnpint(1) == False assert mp.isnpint(-1) == True assert mp.isnpint(-1.1) == False assert mp.isnpint(-1.0) == True assert mp.isnpint(mp.mpq(1,2)) == False assert mp.isnpint(mp.mpq(-1,2)) == False assert mp.isnpint(mp.mpq(-3,1)) == True assert mp.isnpint(mp.mpq(0,1)) == True assert mp.isnpint(mp.mpq(1,1)) == False assert mp.isnpint(0+0j) == True assert mp.isnpint(-1+0j) == True assert mp.isnpint(-1.1+0j) == False assert mp.isnpint(-1+0.1j) == False assert mp.isnpint(0+0.1j) == False mpmath-1.1.0/mpmath/tests/test_bitwise.py000066400000000000000000000170061340375245600205230ustar00rootroot00000000000000""" Test bit-level integer and mpf operations """ from mpmath import * from mpmath.libmp import * def test_bitcount(): assert bitcount(0) == 0 assert bitcount(1) == 1 assert bitcount(7) == 3 assert bitcount(8) == 4 assert bitcount(2**100) == 101 assert bitcount(2**100-1) == 100 def test_trailing(): assert trailing(0) == 0 assert trailing(1) == 0 assert trailing(2) == 1 assert trailing(7) == 0 assert trailing(8) == 3 assert trailing(2**100) == 100 assert trailing(2**100-1) == 0 def test_round_down(): assert from_man_exp(0, -4, 4, round_down)[:3] == (0, 0, 0) assert from_man_exp(0xf0, -4, 4, round_down)[:3] == (0, 15, 0) assert from_man_exp(0xf1, -4, 4, round_down)[:3] == (0, 15, 0) assert from_man_exp(0xff, -4, 4, round_down)[:3] == (0, 15, 0) assert from_man_exp(-0xf0, -4, 4, round_down)[:3] == (1, 15, 0) assert from_man_exp(-0xf1, -4, 4, round_down)[:3] == (1, 15, 0) assert from_man_exp(-0xff, -4, 4, round_down)[:3] == (1, 15, 0) def test_round_up(): assert from_man_exp(0, -4, 4, round_up)[:3] == (0, 0, 0) assert from_man_exp(0xf0, -4, 4, round_up)[:3] == (0, 15, 0) assert from_man_exp(0xf1, -4, 4, round_up)[:3] == (0, 1, 4) assert from_man_exp(0xff, -4, 4, round_up)[:3] == (0, 1, 4) assert from_man_exp(-0xf0, -4, 4, round_up)[:3] == (1, 15, 0) assert from_man_exp(-0xf1, -4, 4, round_up)[:3] == (1, 1, 4) assert from_man_exp(-0xff, -4, 4, round_up)[:3] == (1, 1, 4) def test_round_floor(): assert from_man_exp(0, -4, 4, round_floor)[:3] == (0, 0, 0) assert from_man_exp(0xf0, -4, 4, round_floor)[:3] == (0, 15, 0) assert from_man_exp(0xf1, -4, 4, round_floor)[:3] == (0, 15, 0) assert from_man_exp(0xff, -4, 4, round_floor)[:3] == (0, 15, 0) assert from_man_exp(-0xf0, -4, 4, round_floor)[:3] == (1, 15, 0) assert from_man_exp(-0xf1, -4, 4, round_floor)[:3] == (1, 1, 4) assert from_man_exp(-0xff, -4, 4, round_floor)[:3] == (1, 1, 4) def test_round_ceiling(): assert from_man_exp(0, -4, 4, round_ceiling)[:3] == (0, 0, 0) assert from_man_exp(0xf0, -4, 4, round_ceiling)[:3] == (0, 15, 0) assert from_man_exp(0xf1, -4, 4, round_ceiling)[:3] == (0, 1, 4) assert from_man_exp(0xff, -4, 4, round_ceiling)[:3] == (0, 1, 4) assert from_man_exp(-0xf0, -4, 4, round_ceiling)[:3] == (1, 15, 0) assert from_man_exp(-0xf1, -4, 4, round_ceiling)[:3] == (1, 15, 0) assert from_man_exp(-0xff, -4, 4, round_ceiling)[:3] == (1, 15, 0) def test_round_nearest(): assert from_man_exp(0, -4, 4, round_nearest)[:3] == (0, 0, 0) assert from_man_exp(0xf0, -4, 4, round_nearest)[:3] == (0, 15, 0) assert from_man_exp(0xf7, -4, 4, round_nearest)[:3] == (0, 15, 0) assert from_man_exp(0xf8, -4, 4, round_nearest)[:3] == (0, 1, 4) # 1111.1000 -> 10000.0 assert from_man_exp(0xf9, -4, 4, round_nearest)[:3] == (0, 1, 4) # 1111.1001 -> 10000.0 assert from_man_exp(0xe8, -4, 4, round_nearest)[:3] == (0, 7, 1) # 1110.1000 -> 1110.0 assert from_man_exp(0xe9, -4, 4, round_nearest)[:3] == (0, 15, 0) # 1110.1001 -> 1111.0 assert from_man_exp(-0xf0, -4, 4, round_nearest)[:3] == (1, 15, 0) assert from_man_exp(-0xf7, -4, 4, round_nearest)[:3] == (1, 15, 0) assert from_man_exp(-0xf8, -4, 4, round_nearest)[:3] == (1, 1, 4) assert from_man_exp(-0xf9, -4, 4, round_nearest)[:3] == (1, 1, 4) assert from_man_exp(-0xe8, -4, 4, round_nearest)[:3] == (1, 7, 1) assert from_man_exp(-0xe9, -4, 4, round_nearest)[:3] == (1, 15, 0) def test_rounding_bugs(): # 1 less than power-of-two cases assert from_man_exp(72057594037927935, -56, 53, round_up) == (0, 1, 0, 1) assert from_man_exp(73786976294838205979, -65, 53, round_nearest) == (0, 1, 1, 1) assert from_man_exp(31, 0, 4, round_up) == (0, 1, 5, 1) assert from_man_exp(-31, 0, 4, round_floor) == (1, 1, 5, 1) assert from_man_exp(255, 0, 7, round_up) == (0, 1, 8, 1) assert from_man_exp(-255, 0, 7, round_floor) == (1, 1, 8, 1) def test_rounding_issue_200(): a = from_man_exp(9867,-100) b = from_man_exp(9867,-200) c = from_man_exp(-1,0) z = (1, 1023, -10, 10) assert mpf_add(a, c, 10, 'd') == z assert mpf_add(b, c, 10, 'd') == z assert mpf_add(c, a, 10, 'd') == z assert mpf_add(c, b, 10, 'd') == z def test_perturb(): a = fone b = from_float(0.99999999999999989) c = from_float(1.0000000000000002) assert mpf_perturb(a, 0, 53, round_nearest) == a assert mpf_perturb(a, 1, 53, round_nearest) == a assert mpf_perturb(a, 0, 53, round_up) == c assert mpf_perturb(a, 0, 53, round_ceiling) == c assert mpf_perturb(a, 0, 53, round_down) == a assert mpf_perturb(a, 0, 53, round_floor) == a assert mpf_perturb(a, 1, 53, round_up) == a assert mpf_perturb(a, 1, 53, round_ceiling) == a assert mpf_perturb(a, 1, 53, round_down) == b assert mpf_perturb(a, 1, 53, round_floor) == b a = mpf_neg(a) b = mpf_neg(b) c = mpf_neg(c) assert mpf_perturb(a, 0, 53, round_nearest) == a assert mpf_perturb(a, 1, 53, round_nearest) == a assert mpf_perturb(a, 0, 53, round_up) == a assert mpf_perturb(a, 0, 53, round_floor) == a assert mpf_perturb(a, 0, 53, round_down) == b assert mpf_perturb(a, 0, 53, round_ceiling) == b assert mpf_perturb(a, 1, 53, round_up) == c assert mpf_perturb(a, 1, 53, round_floor) == c assert mpf_perturb(a, 1, 53, round_down) == a assert mpf_perturb(a, 1, 53, round_ceiling) == a def test_add_exact(): ff = from_float assert mpf_add(ff(3.0), ff(2.5)) == ff(5.5) assert mpf_add(ff(3.0), ff(-2.5)) == ff(0.5) assert mpf_add(ff(-3.0), ff(2.5)) == ff(-0.5) assert mpf_add(ff(-3.0), ff(-2.5)) == ff(-5.5) assert mpf_sub(mpf_add(fone, ff(1e-100)), fone) == ff(1e-100) assert mpf_sub(mpf_add(ff(1e-100), fone), fone) == ff(1e-100) assert mpf_sub(mpf_add(fone, ff(-1e-100)), fone) == ff(-1e-100) assert mpf_sub(mpf_add(ff(-1e-100), fone), fone) == ff(-1e-100) assert mpf_add(fone, fzero) == fone assert mpf_add(fzero, fone) == fone assert mpf_add(fzero, fzero) == fzero def test_long_exponent_shifts(): mp.dps = 15 # Check for possible bugs due to exponent arithmetic overflow # in a C implementation x = mpf(1) for p in [32, 64]: a = ldexp(1,2**(p-1)) b = ldexp(1,2**p) c = ldexp(1,2**(p+1)) d = ldexp(1,-2**(p-1)) e = ldexp(1,-2**p) f = ldexp(1,-2**(p+1)) assert (x+a) == a assert (x+b) == b assert (x+c) == c assert (x+d) == x assert (x+e) == x assert (x+f) == x assert (a+x) == a assert (b+x) == b assert (c+x) == c assert (d+x) == x assert (e+x) == x assert (f+x) == x assert (x-a) == -a assert (x-b) == -b assert (x-c) == -c assert (x-d) == x assert (x-e) == x assert (x-f) == x assert (a-x) == a assert (b-x) == b assert (c-x) == c assert (d-x) == -x assert (e-x) == -x assert (f-x) == -x def test_float_rounding(): mp.prec = 64 for x in [mpf(1), mpf(1)+eps, mpf(1)-eps, -mpf(1)+eps, -mpf(1)-eps]: fa = float(x) fb = float(fadd(x,0,prec=53,rounding='n')) assert fa == fb z = mpc(x,x) ca = complex(z) cb = complex(fadd(z,0,prec=53,rounding='n')) assert ca == cb for rnd in ['n', 'd', 'u', 'f', 'c']: fa = to_float(x._mpf_, rnd=rnd) fb = to_float(fadd(x,0,prec=53,rounding=rnd)._mpf_, rnd=rnd) assert fa == fb mp.prec = 53 mpmath-1.1.0/mpmath/tests/test_calculus.py000066400000000000000000000214131340375245600206650ustar00rootroot00000000000000import pytest from mpmath import * def test_approximation(): mp.dps = 15 f = lambda x: cos(2-2*x)/x p, err = chebyfit(f, [2, 4], 8, error=True) assert err < 1e-5 for i in range(10): x = 2 + i/5. assert abs(polyval(p, x) - f(x)) < err def test_limits(): mp.dps = 15 assert limit(lambda x: (x-sin(x))/x**3, 0).ae(mpf(1)/6) assert limit(lambda n: (1+1/n)**n, inf).ae(e) def test_polyval(): assert polyval([], 3) == 0 assert polyval([0], 3) == 0 assert polyval([5], 3) == 5 # 4x^3 - 2x + 5 p = [4, 0, -2, 5] assert polyval(p,4) == 253 assert polyval(p,4,derivative=True) == (253, 190) def test_polyroots(): p = polyroots([1,-4]) assert p[0].ae(4) p, q = polyroots([1,2,3]) assert p.ae(-1 - sqrt(2)*j) assert q.ae(-1 + sqrt(2)*j) #this is not a real test, it only tests a specific case assert polyroots([1]) == [] pytest.raises(ValueError, lambda: polyroots([0])) def test_polyroots_legendre(): n = 64 coeffs = [11975573020964041433067793888190275875, 0, -190100434726484311252477736051902332000, 0, 1437919688271127330313741595496589239248, 0, -6897338342113537600691931230430793911840, 0, 23556405536185284408974715545252277554280, 0, -60969520211303089058522793175947071316960, 0, 124284021969194758465450309166353645376880, 0, -204721258548015217049921875719981284186016, 0, 277415422258095841688223780704620656114900, 0, -313237834141273382807123548182995095192800, 0, 297432255354328395601259515935229287637200, 0, -239057700565161140389797367947941296605600, 0, 163356095386193445933028201431093219347160, 0, -95158890516229191805647495979277603503200, 0, 47310254620162038075933656063247634556400, 0, -20071017111583894941305187420771723751200, 0, 7255051932731034189479516844750603752850, 0, -2228176940331017311443863996901733412640, 0, 579006552594977616773047095969088431600, 0, -126584428502545713788439446082310831200, 0, 23112325428835593809686977515028663000, 0, -3491517141958743235617737161547844000, 0, 431305058712550634988073414073557200, 0, -42927166660756742088912492757452000, 0, 3378527005707706553294038781836500, 0, -205277590220215081719131470288800, 0, 9330799555464321896324157740400, 0, -304114948474392713657972548576, 0, 6695289961520387531608984680, 0, -91048139350447232095702560, 0, 659769125727878493447120, 0, -1905929106580294155360, 0, 916312070471295267] with mp.workdps(3): with pytest.raises(mp.NoConvergence): polyroots(coeffs, maxsteps=5, cleanup=True, error=False, extraprec=n*10) roots = polyroots(coeffs, maxsteps=50, cleanup=True, error=False, extraprec=n*10) roots = [str(r) for r in roots] assert roots == \ ['-0.999', '-0.996', '-0.991', '-0.983', '-0.973', '-0.961', '-0.946', '-0.93', '-0.911', '-0.889', '-0.866', '-0.841', '-0.813', '-0.784', '-0.753', '-0.72', '-0.685', '-0.649', '-0.611', '-0.572', '-0.531', '-0.489', '-0.446', '-0.402', '-0.357', '-0.311', '-0.265', '-0.217', '-0.17', '-0.121', '-0.073', '-0.0243', '0.0243', '0.073', '0.121', '0.17', '0.217', '0.265', '0.311', '0.357', '0.402', '0.446', '0.489', '0.531', '0.572', '0.611', '0.649', '0.685', '0.72', '0.753', '0.784', '0.813', '0.841', '0.866', '0.889', '0.911', '0.93', '0.946', '0.961', '0.973', '0.983', '0.991', '0.996', '0.999'] def test_polyroots_legendre_init(): extra_prec = 100 coeffs = [11975573020964041433067793888190275875, 0, -190100434726484311252477736051902332000, 0, 1437919688271127330313741595496589239248, 0, -6897338342113537600691931230430793911840, 0, 23556405536185284408974715545252277554280, 0, -60969520211303089058522793175947071316960, 0, 124284021969194758465450309166353645376880, 0, -204721258548015217049921875719981284186016, 0, 277415422258095841688223780704620656114900, 0, -313237834141273382807123548182995095192800, 0, 297432255354328395601259515935229287637200, 0, -239057700565161140389797367947941296605600, 0, 163356095386193445933028201431093219347160, 0, -95158890516229191805647495979277603503200, 0, 47310254620162038075933656063247634556400, 0, -20071017111583894941305187420771723751200, 0, 7255051932731034189479516844750603752850, 0, -2228176940331017311443863996901733412640, 0, 579006552594977616773047095969088431600, 0, -126584428502545713788439446082310831200, 0, 23112325428835593809686977515028663000, 0, -3491517141958743235617737161547844000, 0, 431305058712550634988073414073557200, 0, -42927166660756742088912492757452000, 0, 3378527005707706553294038781836500, 0, -205277590220215081719131470288800, 0, 9330799555464321896324157740400, 0, -304114948474392713657972548576, 0, 6695289961520387531608984680, 0, -91048139350447232095702560, 0, 659769125727878493447120, 0, -1905929106580294155360, 0, 916312070471295267] roots_init = matrix(['-0.999', '-0.996', '-0.991', '-0.983', '-0.973', '-0.961', '-0.946', '-0.93', '-0.911', '-0.889', '-0.866', '-0.841', '-0.813', '-0.784', '-0.753', '-0.72', '-0.685', '-0.649', '-0.611', '-0.572', '-0.531', '-0.489', '-0.446', '-0.402', '-0.357', '-0.311', '-0.265', '-0.217', '-0.17', '-0.121', '-0.073', '-0.0243', '0.0243', '0.073', '0.121', '0.17', '0.217', '0.265', ' 0.311', '0.357', '0.402', '0.446', '0.489', '0.531', '0.572', '0.611', '0.649', '0.685', '0.72', '0.753', '0.784', '0.813', '0.841', '0.866', '0.889', '0.911', '0.93', '0.946', '0.961', '0.973', '0.983', '0.991', '0.996', '0.999', '1.0']) with mp.workdps(2*mp.dps): roots_exact = polyroots(coeffs, maxsteps=50, cleanup=True, error=False, extraprec=2*extra_prec) with pytest.raises(mp.NoConvergence): polyroots(coeffs, maxsteps=5, cleanup=True, error=False, extraprec=extra_prec) roots,err = polyroots(coeffs, maxsteps=5, cleanup=True, error=True, extraprec=extra_prec,roots_init=roots_init) assert max(matrix(roots_exact)-matrix(roots).apply(abs)) < err roots1,err1 = polyroots(coeffs, maxsteps=25, cleanup=True, error=True, extraprec=extra_prec,roots_init=roots_init[:60]) assert max(matrix(roots_exact)-matrix(roots1).apply(abs)) < err1 def test_pade(): one = mpf(1) mp.dps = 20 N = 10 a = [one] k = 1 for i in range(1, N+1): k *= i a.append(one/k) p, q = pade(a, N//2, N//2) for x in arange(0, 1, 0.1): r = polyval(p[::-1], x)/polyval(q[::-1], x) assert(r.ae(exp(x), 1.0e-10)) mp.dps = 15 def test_fourier(): mp.dps = 15 c, s = fourier(lambda x: x+1, [-1, 2], 2) #plot([lambda x: x+1, lambda x: fourierval((c, s), [-1, 2], x)], [-1, 2]) assert c[0].ae(1.5) assert c[1].ae(-3*sqrt(3)/(2*pi)) assert c[2].ae(3*sqrt(3)/(4*pi)) assert s[0] == 0 assert s[1].ae(3/(2*pi)) assert s[2].ae(3/(4*pi)) assert fourierval((c, s), [-1, 2], 1).ae(1.9134966715663442) def test_differint(): mp.dps = 15 assert differint(lambda t: t, 2, -0.5).ae(8*sqrt(2/pi)/3) def test_invlap(): mp.dps = 15 t = 0.01 fp = lambda p: 1/(p+1)**2 ft = lambda t: t*exp(-t) ftt = ft(t) assert invertlaplace(fp,t,method='talbot').ae(ftt) assert invertlaplace(fp,t,method='stehfest').ae(ftt) assert invertlaplace(fp,t,method='dehoog').ae(ftt) t = 1.0 ftt = ft(t) assert invertlaplace(fp,t,method='talbot').ae(ftt) assert invertlaplace(fp,t,method='stehfest').ae(ftt) assert invertlaplace(fp,t,method='dehoog').ae(ftt) t = 0.01 fp = lambda p: log(p)/p ft = lambda t: -euler-log(t) ftt = ft(t) assert invertlaplace(fp,t,method='talbot').ae(ftt) assert invertlaplace(fp,t,method='stehfest').ae(ftt) assert invertlaplace(fp,t,method='dehoog').ae(ftt) t = 1.0 ftt = ft(t) assert invertlaplace(fp,t,method='talbot').ae(ftt) assert invertlaplace(fp,t,method='stehfest').ae(ftt) assert invertlaplace(fp,t,method='dehoog').ae(ftt) mpmath-1.1.0/mpmath/tests/test_compatibility.py000066400000000000000000000044021340375245600217220ustar00rootroot00000000000000from mpmath import * from random import seed, randint, random import math # Test compatibility with Python floats, which are # IEEE doubles (53-bit) N = 5000 seed(1) # Choosing exponents between roughly -140, 140 ensures that # the Python floats don't overflow or underflow xs = [(random()-1) * 10**randint(-140, 140) for x in range(N)] ys = [(random()-1) * 10**randint(-140, 140) for x in range(N)] # include some equal values ys[int(N*0.8):] = xs[int(N*0.8):] # Detect whether Python is compiled to use 80-bit floating-point # instructions, in which case the double compatibility test breaks uses_x87 = -4.1974624032366689e+117 / -8.4657370748010221e-47 \ == 4.9581771393902231e+163 def test_double_compatibility(): mp.prec = 53 for x, y in zip(xs, ys): mpx = mpf(x) mpy = mpf(y) assert mpf(x) == x assert (mpx < mpy) == (x < y) assert (mpx > mpy) == (x > y) assert (mpx == mpy) == (x == y) assert (mpx != mpy) == (x != y) assert (mpx <= mpy) == (x <= y) assert (mpx >= mpy) == (x >= y) assert mpx == mpx if uses_x87: mp.prec = 64 a = mpx + mpy b = mpx * mpy c = mpx / mpy d = mpx % mpy mp.prec = 53 assert +a == x + y assert +b == x * y assert +c == x / y assert +d == x % y else: assert mpx + mpy == x + y assert mpx * mpy == x * y assert mpx / mpy == x / y assert mpx % mpy == x % y assert abs(mpx) == abs(x) assert mpf(repr(x)) == x assert ceil(mpx) == math.ceil(x) assert floor(mpx) == math.floor(x) def test_sqrt(): # this fails quite often. it appers to be float # that rounds the wrong way, not mpf fail = 0 mp.prec = 53 for x in xs: x = abs(x) mp.prec = 100 mp_high = mpf(x)**0.5 mp.prec = 53 mp_low = mpf(x)**0.5 fp = x**0.5 assert abs(mp_low-mp_high) <= abs(fp-mp_high) fail += mp_low != fp assert fail < N/10 def test_bugs(): # particular bugs assert mpf(4.4408920985006262E-16) < mpf(1.7763568394002505E-15) assert mpf(-4.4408920985006262E-16) > mpf(-1.7763568394002505E-15) mpmath-1.1.0/mpmath/tests/test_convert.py000066400000000000000000000204761340375245600205420ustar00rootroot00000000000000import random from mpmath import * from mpmath.libmp import * def test_basic_string(): """ Test basic string conversion """ mp.dps = 15 assert mpf('3') == mpf('3.0') == mpf('0003.') == mpf('0.03e2') == mpf(3.0) assert mpf('30') == mpf('30.0') == mpf('00030.') == mpf(30.0) for i in range(10): for j in range(10): assert mpf('%ie%i' % (i,j)) == i * 10**j assert str(mpf('25000.0')) == '25000.0' assert str(mpf('2500.0')) == '2500.0' assert str(mpf('250.0')) == '250.0' assert str(mpf('25.0')) == '25.0' assert str(mpf('2.5')) == '2.5' assert str(mpf('0.25')) == '0.25' assert str(mpf('0.025')) == '0.025' assert str(mpf('0.0025')) == '0.0025' assert str(mpf('0.00025')) == '0.00025' assert str(mpf('0.000025')) == '2.5e-5' assert str(mpf(0)) == '0.0' assert str(mpf('2.5e1000000000000000000000')) == '2.5e+1000000000000000000000' assert str(mpf('2.6e-1000000000000000000000')) == '2.6e-1000000000000000000000' assert str(mpf(1.23402834e-15)) == '1.23402834e-15' assert str(mpf(-1.23402834e-15)) == '-1.23402834e-15' assert str(mpf(-1.2344e-15)) == '-1.2344e-15' assert repr(mpf(-1.2344e-15)) == "mpf('-1.2343999999999999e-15')" assert str(mpf("2163048125L")) == '2163048125.0' assert str(mpf("-2163048125l")) == '-2163048125.0' assert str(mpf("-2163048125L/1088391168")) == '-1.98738118113799' assert str(mpf("2163048125/1088391168l")) == '1.98738118113799' def test_pretty(): mp.pretty = True assert repr(mpf(2.5)) == '2.5' assert repr(mpc(2.5,3.5)) == '(2.5 + 3.5j)' mp.pretty = False iv.pretty = True assert repr(mpi(2.5,3.5)) == '[2.5, 3.5]' iv.pretty = False def test_str_whitespace(): assert mpf('1.26 ') == 1.26 def test_unicode(): mp.dps = 15 try: unicode = unicode except NameError: unicode = str assert mpf(unicode('2.76')) == 2.76 assert mpf(unicode('inf')) == inf def test_str_format(): assert to_str(from_float(0.1),15,strip_zeros=False) == '0.100000000000000' assert to_str(from_float(0.0),15,show_zero_exponent=True) == '0.0e+0' assert to_str(from_float(0.0),0,show_zero_exponent=True) == '.0e+0' assert to_str(from_float(0.0),0,show_zero_exponent=False) == '.0' assert to_str(from_float(0.0),1,show_zero_exponent=True) == '0.0e+0' assert to_str(from_float(0.0),1,show_zero_exponent=False) == '0.0' assert to_str(from_float(1.23),3,show_zero_exponent=True) == '1.23e+0' assert to_str(from_float(1.23456789000000e-2),15,strip_zeros=False,min_fixed=0,max_fixed=0) == '1.23456789000000e-2' assert to_str(from_float(1.23456789000000e+2),15,strip_zeros=False,min_fixed=0,max_fixed=0) == '1.23456789000000e+2' assert to_str(from_float(2.1287e14), 15, max_fixed=1000) == '212870000000000.0' assert to_str(from_float(2.1287e15), 15, max_fixed=1000) == '2128700000000000.0' assert to_str(from_float(2.1287e16), 15, max_fixed=1000) == '21287000000000000.0' assert to_str(from_float(2.1287e30), 15, max_fixed=1000) == '2128700000000000000000000000000.0' def test_tight_string_conversion(): mp.dps = 15 # In an old version, '0.5' wasn't recognized as representing # an exact binary number and was erroneously rounded up or down assert from_str('0.5', 10, round_floor) == fhalf assert from_str('0.5', 10, round_ceiling) == fhalf def test_eval_repr_invariant(): """Test that eval(repr(x)) == x""" random.seed(123) for dps in [10, 15, 20, 50, 100]: mp.dps = dps for i in range(1000): a = mpf(random.random())**0.5 * 10**random.randint(-100, 100) assert eval(repr(a)) == a mp.dps = 15 def test_str_bugs(): mp.dps = 15 # Decimal rounding used to give the wrong exponent in some cases assert str(mpf('1e600')) == '1.0e+600' assert str(mpf('1e10000')) == '1.0e+10000' def test_str_prec0(): assert to_str(from_float(1.234), 0) == '.0e+0' assert to_str(from_float(1e-15), 0) == '.0e-15' assert to_str(from_float(1e+15), 0) == '.0e+15' assert to_str(from_float(-1e-15), 0) == '-.0e-15' assert to_str(from_float(-1e+15), 0) == '-.0e+15' def test_convert_rational(): mp.dps = 15 assert from_rational(30, 5, 53, round_nearest) == (0, 3, 1, 2) assert from_rational(-7, 4, 53, round_nearest) == (1, 7, -2, 3) assert to_rational((0, 1, -1, 1)) == (1, 2) def test_custom_class(): class mympf: @property def _mpf_(self): return mpf(3.5)._mpf_ class mympc: @property def _mpc_(self): return mpf(3.5)._mpf_, mpf(2.5)._mpf_ assert mpf(2) + mympf() == 5.5 assert mympf() + mpf(2) == 5.5 assert mpf(mympf()) == 3.5 assert mympc() + mpc(2) == mpc(5.5, 2.5) assert mpc(2) + mympc() == mpc(5.5, 2.5) assert mpc(mympc()) == (3.5+2.5j) def test_conversion_methods(): class SomethingRandom: pass class SomethingReal: def _mpmath_(self, prec, rounding): return mp.make_mpf(from_str('1.3', prec, rounding)) class SomethingComplex: def _mpmath_(self, prec, rounding): return mp.make_mpc((from_str('1.3', prec, rounding), \ from_str('1.7', prec, rounding))) x = mpf(3) z = mpc(3) a = SomethingRandom() y = SomethingReal() w = SomethingComplex() for d in [15, 45]: mp.dps = d assert (x+y).ae(mpf('4.3')) assert (y+x).ae(mpf('4.3')) assert (x+w).ae(mpc('4.3', '1.7')) assert (w+x).ae(mpc('4.3', '1.7')) assert (z+y).ae(mpc('4.3')) assert (y+z).ae(mpc('4.3')) assert (z+w).ae(mpc('4.3', '1.7')) assert (w+z).ae(mpc('4.3', '1.7')) x-y; y-x; x-w; w-x; z-y; y-z; z-w; w-z x*y; y*x; x*w; w*x; z*y; y*z; z*w; w*z x/y; y/x; x/w; w/x; z/y; y/z; z/w; w/z x**y; y**x; x**w; w**x; z**y; y**z; z**w; w**z x==y; y==x; x==w; w==x; z==y; y==z; z==w; w==z mp.dps = 15 assert x.__add__(a) is NotImplemented assert x.__radd__(a) is NotImplemented assert x.__lt__(a) is NotImplemented assert x.__gt__(a) is NotImplemented assert x.__le__(a) is NotImplemented assert x.__ge__(a) is NotImplemented assert x.__eq__(a) is NotImplemented assert x.__ne__(a) is NotImplemented # implementation detail if hasattr(x, "__cmp__"): assert x.__cmp__(a) is NotImplemented assert x.__sub__(a) is NotImplemented assert x.__rsub__(a) is NotImplemented assert x.__mul__(a) is NotImplemented assert x.__rmul__(a) is NotImplemented assert x.__div__(a) is NotImplemented assert x.__rdiv__(a) is NotImplemented assert x.__mod__(a) is NotImplemented assert x.__rmod__(a) is NotImplemented assert x.__pow__(a) is NotImplemented assert x.__rpow__(a) is NotImplemented assert z.__add__(a) is NotImplemented assert z.__radd__(a) is NotImplemented assert z.__eq__(a) is NotImplemented assert z.__ne__(a) is NotImplemented assert z.__sub__(a) is NotImplemented assert z.__rsub__(a) is NotImplemented assert z.__mul__(a) is NotImplemented assert z.__rmul__(a) is NotImplemented assert z.__div__(a) is NotImplemented assert z.__rdiv__(a) is NotImplemented assert z.__pow__(a) is NotImplemented assert z.__rpow__(a) is NotImplemented def test_mpmathify(): assert mpmathify('1/2') == 0.5 assert mpmathify('(1.0+1.0j)') == mpc(1, 1) assert mpmathify('(1.2e-10 - 3.4e5j)') == mpc('1.2e-10', '-3.4e5') assert mpmathify('1j') == mpc(1j) def test_compatibility(): try: import numpy as np from fractions import Fraction from decimal import Decimal import decimal except ImportError: return # numpy types for nptype in np.core.numerictypes.typeDict.values(): if issubclass(nptype, np.complexfloating): x = nptype(complex(0.5, -0.5)) elif issubclass(nptype, np.floating): x = nptype(0.5) elif issubclass(nptype, np.integer): x = nptype(2) # Handle the weird types try: diff = np.abs(type(np.sqrt(x))(sqrt(x)) - np.sqrt(x)) except: continue assert diff < 2.0**-53 #Fraction and Decimal oldprec = mp.prec mp.prec = 1000 decimal.getcontext().prec = mp.dps assert sqrt(Fraction(2, 3)).ae(sqrt(mpf('2/3'))) assert sqrt(Decimal(2)/Decimal(3)).ae(sqrt(mpf('2/3'))) mp.prec = oldprec mpmath-1.1.0/mpmath/tests/test_diff.py000066400000000000000000000046421340375245600177670ustar00rootroot00000000000000from mpmath import * def test_diff(): mp.dps = 15 assert diff(log, 2.0, n=0).ae(log(2)) assert diff(cos, 1.0).ae(-sin(1)) assert diff(abs, 0.0) == 0 assert diff(abs, 0.0, direction=1) == 1 assert diff(abs, 0.0, direction=-1) == -1 assert diff(exp, 1.0).ae(e) assert diff(exp, 1.0, n=5).ae(e) assert diff(exp, 2.0, n=5, direction=3*j).ae(e**2) assert diff(lambda x: x**2, 3.0, method='quad').ae(6) assert diff(lambda x: 3+x**5, 3.0, n=2, method='quad').ae(540) assert diff(lambda x: 3+x**5, 3.0, n=2, method='step').ae(540) assert diffun(sin)(2).ae(cos(2)) assert diffun(sin, n=2)(2).ae(-sin(2)) def test_diffs(): mp.dps = 15 assert [chop(d) for d in diffs(sin, 0, 1)] == [0, 1] assert [chop(d) for d in diffs(sin, 0, 1, method='quad')] == [0, 1] assert [chop(d) for d in diffs(sin, 0, 2)] == [0, 1, 0] assert [chop(d) for d in diffs(sin, 0, 2, method='quad')] == [0, 1, 0] def test_taylor(): mp.dps = 15 # Easy to test since the coefficients are exact in floating-point assert taylor(sqrt, 1, 4) == [1, 0.5, -0.125, 0.0625, -0.0390625] def test_diff_partial(): mp.dps = 15 x,y,z = xyz = 2,3,7 f = lambda x,y,z: 3*x**2 * (y+2)**3 * z**5 assert diff(f, xyz, (0,0,0)).ae(25210500) assert diff(f, xyz, (0,0,1)).ae(18007500) assert diff(f, xyz, (0,0,2)).ae(10290000) assert diff(f, xyz, (0,1,0)).ae(15126300) assert diff(f, xyz, (0,1,1)).ae(10804500) assert diff(f, xyz, (0,1,2)).ae(6174000) assert diff(f, xyz, (0,2,0)).ae(6050520) assert diff(f, xyz, (0,2,1)).ae(4321800) assert diff(f, xyz, (0,2,2)).ae(2469600) assert diff(f, xyz, (1,0,0)).ae(25210500) assert diff(f, xyz, (1,0,1)).ae(18007500) assert diff(f, xyz, (1,0,2)).ae(10290000) assert diff(f, xyz, (1,1,0)).ae(15126300) assert diff(f, xyz, (1,1,1)).ae(10804500) assert diff(f, xyz, (1,1,2)).ae(6174000) assert diff(f, xyz, (1,2,0)).ae(6050520) assert diff(f, xyz, (1,2,1)).ae(4321800) assert diff(f, xyz, (1,2,2)).ae(2469600) assert diff(f, xyz, (2,0,0)).ae(12605250) assert diff(f, xyz, (2,0,1)).ae(9003750) assert diff(f, xyz, (2,0,2)).ae(5145000) assert diff(f, xyz, (2,1,0)).ae(7563150) assert diff(f, xyz, (2,1,1)).ae(5402250) assert diff(f, xyz, (2,1,2)).ae(3087000) assert diff(f, xyz, (2,2,0)).ae(3025260) assert diff(f, xyz, (2,2,1)).ae(2160900) assert diff(f, xyz, (2,2,2)).ae(1234800) mpmath-1.1.0/mpmath/tests/test_division.py000066400000000000000000000123341340375245600207000ustar00rootroot00000000000000from mpmath.libmp import * from mpmath import mpf, mp from random import randint, choice, seed all_modes = [round_floor, round_ceiling, round_down, round_up, round_nearest] fb = from_bstr fi = from_int ff = from_float def test_div_1_3(): a = fi(1) b = fi(3) c = fi(-1) # floor rounds down, ceiling rounds up assert mpf_div(a, b, 7, round_floor) == fb('0.01010101') assert mpf_div(a, b, 7, round_ceiling) == fb('0.01010110') assert mpf_div(a, b, 7, round_down) == fb('0.01010101') assert mpf_div(a, b, 7, round_up) == fb('0.01010110') assert mpf_div(a, b, 7, round_nearest) == fb('0.01010101') # floor rounds up, ceiling rounds down assert mpf_div(c, b, 7, round_floor) == fb('-0.01010110') assert mpf_div(c, b, 7, round_ceiling) == fb('-0.01010101') assert mpf_div(c, b, 7, round_down) == fb('-0.01010101') assert mpf_div(c, b, 7, round_up) == fb('-0.01010110') assert mpf_div(c, b, 7, round_nearest) == fb('-0.01010101') def test_mpf_divi_1_3(): a = 1 b = fi(3) c = -1 assert mpf_rdiv_int(a, b, 7, round_floor) == fb('0.01010101') assert mpf_rdiv_int(a, b, 7, round_ceiling) == fb('0.01010110') assert mpf_rdiv_int(a, b, 7, round_down) == fb('0.01010101') assert mpf_rdiv_int(a, b, 7, round_up) == fb('0.01010110') assert mpf_rdiv_int(a, b, 7, round_nearest) == fb('0.01010101') assert mpf_rdiv_int(c, b, 7, round_floor) == fb('-0.01010110') assert mpf_rdiv_int(c, b, 7, round_ceiling) == fb('-0.01010101') assert mpf_rdiv_int(c, b, 7, round_down) == fb('-0.01010101') assert mpf_rdiv_int(c, b, 7, round_up) == fb('-0.01010110') assert mpf_rdiv_int(c, b, 7, round_nearest) == fb('-0.01010101') def test_div_300(): q = fi(1000000) a = fi(300499999) # a/q is a little less than a half-integer b = fi(300500000) # b/q exactly a half-integer c = fi(300500001) # c/q is a little more than a half-integer # Check nearest integer rounding (prec=9 as 2**8 < 300 < 2**9) assert mpf_div(a, q, 9, round_down) == fi(300) assert mpf_div(b, q, 9, round_down) == fi(300) assert mpf_div(c, q, 9, round_down) == fi(300) assert mpf_div(a, q, 9, round_up) == fi(301) assert mpf_div(b, q, 9, round_up) == fi(301) assert mpf_div(c, q, 9, round_up) == fi(301) # Nearest even integer is down assert mpf_div(a, q, 9, round_nearest) == fi(300) assert mpf_div(b, q, 9, round_nearest) == fi(300) assert mpf_div(c, q, 9, round_nearest) == fi(301) # Nearest even integer is up a = fi(301499999) b = fi(301500000) c = fi(301500001) assert mpf_div(a, q, 9, round_nearest) == fi(301) assert mpf_div(b, q, 9, round_nearest) == fi(302) assert mpf_div(c, q, 9, round_nearest) == fi(302) def test_tight_integer_division(): # Test that integer division at tightest possible precision is exact N = 100 seed(1) for i in range(N): a = choice([1, -1]) * randint(1, 1< 1: print("original matrix (hessenberg):\n", A) n = A.rows Q, H = mp.hessenberg(A) if verbose > 1: print("Q:\n",Q) print("H:\n",H) B = Q * H * Q.transpose_conj() eps = mp.exp(0.8 * mp.log(mp.eps)) err0 = 0 for x in xrange(n): for y in xrange(n): err0 += abs(A[y,x] - B[y,x]) err0 /= n * n err1 = 0 for x in xrange(n): for y in xrange(x + 2, n): err1 += abs(H[y,x]) if verbose > 0: print("difference (H):", err0, err1) if verbose > 1: print("B:\n", B) assert err0 < eps assert err1 == 0 def run_schur(A, verbose = 0): if verbose > 1: print("original matrix (schur):\n", A) n = A.rows Q, R = mp.schur(A) if verbose > 1: print("Q:\n", Q) print("R:\n", R) B = Q * R * Q.transpose_conj() C = Q * Q.transpose_conj() eps = mp.exp(0.8 * mp.log(mp.eps)) err0 = 0 for x in xrange(n): for y in xrange(n): err0 += abs(A[y,x] - B[y,x]) err0 /= n * n err1 = 0 for x in xrange(n): for y in xrange(n): if x == y: C[y,x] -= 1 err1 += abs(C[y,x]) err1 /= n * n err2 = 0 for x in xrange(n): for y in xrange(x + 1, n): err2 += abs(R[y,x]) if verbose > 0: print("difference (S):", err0, err1, err2) if verbose > 1: print("B:\n", B) assert err0 < eps assert err1 < eps assert err2 == 0 def run_eig(A, verbose = 0): if verbose > 1: print("original matrix (eig):\n", A) n = A.rows E, EL, ER = mp.eig(A, left = True, right = True) if verbose > 1: print("E:\n", E) print("EL:\n", EL) print("ER:\n", ER) eps = mp.exp(0.8 * mp.log(mp.eps)) err0 = 0 for i in xrange(n): B = A * ER[:,i] - E[i] * ER[:,i] err0 = max(err0, mp.mnorm(B)) B = EL[i,:] * A - EL[i,:] * E[i] err0 = max(err0, mp.mnorm(B)) err0 /= n * n if verbose > 0: print("difference (E):", err0) assert err0 < eps ##################### def test_eig_dyn(): v = 0 for i in xrange(5): n = 1 + int(mp.rand() * 5) if mp.rand() > 0.5: # real A = 2 * mp.randmatrix(n, n) - 1 if mp.rand() > 0.5: A *= 10 for x in xrange(n): for y in xrange(n): A[x,y] = int(A[x,y]) else: A = (2 * mp.randmatrix(n, n) - 1) + 1j * (2 * mp.randmatrix(n, n) - 1) if mp.rand() > 0.5: A *= 10 for x in xrange(n): for y in xrange(n): A[x,y] = int(mp.re(A[x,y])) + 1j * int(mp.im(A[x,y])) run_hessenberg(A, verbose = v) run_schur(A, verbose = v) run_eig(A, verbose = v) def test_eig(): v = 0 AS = [] A = mp.matrix([[2, 1, 0], # jordan block of size 3 [0, 2, 1], [0, 0, 2]]) AS.append(A) AS.append(A.transpose()) A = mp.matrix([[2, 0, 0], # jordan block of size 2 [0, 2, 1], [0, 0, 2]]) AS.append(A) AS.append(A.transpose()) A = mp.matrix([[2, 0, 1], # jordan block of size 2 [0, 2, 0], [0, 0, 2]]) AS.append(A) AS.append(A.transpose()) A= mp.matrix([[0, 0, 1], # cyclic [1, 0, 0], [0, 1, 0]]) AS.append(A) AS.append(A.transpose()) for A in AS: run_hessenberg(A, verbose = v) run_schur(A, verbose = v) run_eig(A, verbose = v) mpmath-1.1.0/mpmath/tests/test_eigen_symmetric.py000066400000000000000000000211121340375245600222310ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- from mpmath import mp from mpmath import libmp xrange = libmp.backend.xrange def run_eigsy(A, verbose = False): if verbose: print("original matrix:\n", str(A)) D, Q = mp.eigsy(A) B = Q * mp.diag(D) * Q.transpose() C = A - B E = Q * Q.transpose() - mp.eye(A.rows) if verbose: print("eigenvalues:\n", D) print("eigenvectors:\n", Q) NC = mp.mnorm(C) NE = mp.mnorm(E) if verbose: print("difference:", NC, "\n", C, "\n") print("difference:", NE, "\n", E, "\n") eps = mp.exp( 0.8 * mp.log(mp.eps)) assert NC < eps assert NE < eps return NC def run_eighe(A, verbose = False): if verbose: print("original matrix:\n", str(A)) D, Q = mp.eighe(A) B = Q * mp.diag(D) * Q.transpose_conj() C = A - B E = Q * Q.transpose_conj() - mp.eye(A.rows) if verbose: print("eigenvalues:\n", D) print("eigenvectors:\n", Q) NC = mp.mnorm(C) NE = mp.mnorm(E) if verbose: print("difference:", NC, "\n", C, "\n") print("difference:", NE, "\n", E, "\n") eps = mp.exp( 0.8 * mp.log(mp.eps)) assert NC < eps assert NE < eps return NC def run_svd_r(A, full_matrices = False, verbose = True): m, n = A.rows, A.cols eps = mp.exp(0.8 * mp.log(mp.eps)) if verbose: print("original matrix:\n", str(A)) print("full", full_matrices) U, S0, V = mp.svd_r(A, full_matrices = full_matrices) S = mp.zeros(U.cols, V.rows) for j in xrange(min(m, n)): S[j,j] = S0[j] if verbose: print("U:\n", str(U)) print("S:\n", str(S0)) print("V:\n", str(V)) C = U * S * V - A err = mp.mnorm(C) if verbose: print("C\n", str(C), "\n", err) assert err < eps D = V * V.transpose() - mp.eye(V.rows) err = mp.mnorm(D) if verbose: print("D:\n", str(D), "\n", err) assert err < eps E = U.transpose() * U - mp.eye(U.cols) err = mp.mnorm(E) if verbose: print("E:\n", str(E), "\n", err) assert err < eps def run_svd_c(A, full_matrices = False, verbose = True): m, n = A.rows, A.cols eps = mp.exp(0.8 * mp.log(mp.eps)) if verbose: print("original matrix:\n", str(A)) print("full", full_matrices) U, S0, V = mp.svd_c(A, full_matrices = full_matrices) S = mp.zeros(U.cols, V.rows) for j in xrange(min(m, n)): S[j,j] = S0[j] if verbose: print("U:\n", str(U)) print("S:\n", str(S0)) print("V:\n", str(V)) C = U * S * V - A err = mp.mnorm(C) if verbose: print("C\n", str(C), "\n", err) assert err < eps D = V * V.transpose_conj() - mp.eye(V.rows) err = mp.mnorm(D) if verbose: print("D:\n", str(D), "\n", err) assert err < eps E = U.transpose_conj() * U - mp.eye(U.cols) err = mp.mnorm(E) if verbose: print("E:\n", str(E), "\n", err) assert err < eps def run_gauss(qtype, a, b): eps = 1e-5 d, e = mp.gauss_quadrature(len(a), qtype) d -= mp.matrix(a) e -= mp.matrix(b) assert mp.mnorm(d) < eps assert mp.mnorm(e) < eps def irandmatrix(n, range = 10): """ random matrix with integer entries """ A = mp.matrix(n, n) for i in xrange(n): for j in xrange(n): A[i,j]=int( (2 * mp.rand() - 1) * range) return A ####################### def test_eighe_fixed_matrix(): A = mp.matrix([[2, 3], [3, 5]]) run_eigsy(A) run_eighe(A) A = mp.matrix([[7, -11], [-11, 13]]) run_eigsy(A) run_eighe(A) A = mp.matrix([[2, 11, 7], [11, 3, 13], [7, 13, 5]]) run_eigsy(A) run_eighe(A) A = mp.matrix([[2, 0, 7], [0, 3, 1], [7, 1, 5]]) run_eigsy(A) run_eighe(A) # A = mp.matrix([[2, 3+7j], [3-7j, 5]]) run_eighe(A) A = mp.matrix([[2, -11j, 0], [+11j, 3, 29j], [0, -29j, 5]]) run_eighe(A) A = mp.matrix([[2, 11 + 17j, 7 + 19j], [11 - 17j, 3, -13 + 23j], [7 - 19j, -13 - 23j, 5]]) run_eighe(A) def test_eigsy_randmatrix(): N = 5 for a in xrange(10): A = 2 * mp.randmatrix(N, N) - 1 for i in xrange(0, N): for j in xrange(i + 1, N): A[j,i] = A[i,j] run_eigsy(A) def test_eighe_randmatrix(): N = 5 for a in xrange(10): A = (2 * mp.randmatrix(N, N) - 1) + 1j * (2 * mp.randmatrix(N, N) - 1) for i in xrange(0, N): A[i,i] = mp.re(A[i,i]) for j in xrange(i + 1, N): A[j,i] = mp.conj(A[i,j]) run_eighe(A) def test_eigsy_irandmatrix(): N = 4 R = 4 for a in xrange(10): A=irandmatrix(N, R) for i in xrange(0, N): for j in xrange(i + 1, N): A[j,i] = A[i,j] run_eigsy(A) def test_eighe_irandmatrix(): N = 4 R = 4 for a in xrange(10): A=irandmatrix(N, R) + 1j * irandmatrix(N, R) for i in xrange(0, N): A[i,i] = mp.re(A[i,i]) for j in xrange(i + 1, N): A[j,i] = mp.conj(A[i,j]) run_eighe(A) def test_svd_r_rand(): for i in xrange(5): full = mp.rand() > 0.5 m = 1 + int(mp.rand() * 10) n = 1 + int(mp.rand() * 10) A = 2 * mp.randmatrix(m, n) - 1 if mp.rand() > 0.5: A *= 10 for x in xrange(m): for y in xrange(n): A[x,y]=int(A[x,y]) run_svd_r(A, full_matrices = full, verbose = False) def test_svd_c_rand(): for i in xrange(5): full = mp.rand() > 0.5 m = 1 + int(mp.rand() * 10) n = 1 + int(mp.rand() * 10) A = (2 * mp.randmatrix(m, n) - 1) + 1j * (2 * mp.randmatrix(m, n) - 1) if mp.rand() > 0.5: A *= 10 for x in xrange(m): for y in xrange(n): A[x,y]=int(mp.re(A[x,y])) + 1j * int(mp.im(A[x,y])) run_svd_c(A, full_matrices=full, verbose=False) def test_svd_test_case(): # a test case from Golub and Reinsch # (see wilkinson/reinsch: handbook for auto. comp., vol ii-linear algebra, 134-151(1971).) eps = mp.exp(0.8 * mp.log(mp.eps)) a = [[22, 10, 2, 3, 7], [14, 7, 10, 0, 8], [-1, 13, -1, -11, 3], [-3, -2, 13, -2, 4], [ 9, 8, 1, -2, 4], [ 9, 1, -7, 5, -1], [ 2, -6, 6, 5, 1], [ 4, 5, 0, -2, 2]] a = mp.matrix(a) b = mp.matrix([mp.sqrt(1248), 20, mp.sqrt(384), 0, 0]) S = mp.svd_r(a, compute_uv = False) S -= b assert mp.mnorm(S) < eps S = mp.svd_c(a, compute_uv = False) S -= b assert mp.mnorm(S) < eps def test_gauss_quadrature_static(): a = [-0.57735027, 0.57735027] b = [ 1, 1] run_gauss("legendre", a , b) a = [ -0.906179846, -0.538469310, 0, 0.538469310, 0.906179846] b = [ 0.23692689, 0.47862867, 0.56888889, 0.47862867, 0.23692689] run_gauss("legendre", a , b) a = [ 0.06943184, 0.33000948, 0.66999052, 0.93056816] b = [ 0.17392742, 0.32607258, 0.32607258, 0.17392742] run_gauss("legendre01", a , b) a = [-0.70710678, 0.70710678] b = [ 0.88622693, 0.88622693] run_gauss("hermite", a , b) a = [ -2.02018287, -0.958572465, 0, 0.958572465, 2.02018287] b = [ 0.01995324, 0.39361932, 0.94530872, 0.39361932, 0.01995324] run_gauss("hermite", a , b) a = [ 0.41577456, 2.29428036, 6.28994508] b = [ 0.71109301, 0.27851773, 0.01038926] run_gauss("laguerre", a , b) def test_gauss_quadrature_dynamic(verbose = False): n = 5 A = mp.randmatrix(2 * n, 1) def F(x): r = 0 for i in xrange(len(A) - 1, -1, -1): r = r * x + A[i] return r def run(qtype, FW, R, alpha = 0, beta = 0): X, W = mp.gauss_quadrature(n, qtype, alpha = alpha, beta = beta) a = 0 for i in xrange(len(X)): a += W[i] * F(X[i]) b = mp.quad(lambda x: FW(x) * F(x), R) c = mp.fabs(a - b) if verbose: print(qtype, c, a, b) assert c < 1e-5 run("legendre", lambda x: 1, [-1, 1]) run("legendre01", lambda x: 1, [0, 1]) run("hermite", lambda x: mp.exp(-x*x), [-mp.inf, mp.inf]) run("laguerre", lambda x: mp.exp(-x), [0, mp.inf]) run("glaguerre", lambda x: mp.sqrt(x)*mp.exp(-x), [0, mp.inf], alpha = 1 / mp.mpf(2)) run("chebyshev1", lambda x: 1/mp.sqrt(1-x*x), [-1, 1]) run("chebyshev2", lambda x: mp.sqrt(1-x*x), [-1, 1]) run("jacobi", lambda x: (1-x)**(1/mp.mpf(3)) * (1+x)**(1/mp.mpf(5)), [-1, 1], alpha = 1 / mp.mpf(3), beta = 1 / mp.mpf(5) ) mpmath-1.1.0/mpmath/tests/test_elliptic.py000066400000000000000000000601051340375245600206600ustar00rootroot00000000000000""" Limited tests of the elliptic functions module. A full suite of extensive testing can be found in elliptic_torture_tests.py Author of the first version: M.T. Taschuk References: [1] Abramowitz & Stegun. 'Handbook of Mathematical Functions, 9th Ed.', (Dover duplicate of 1972 edition) [2] Whittaker 'A Course of Modern Analysis, 4th Ed.', 1946, Cambridge University Press """ import mpmath import random import pytest from mpmath import * def mpc_ae(a, b, eps=eps): res = True res = res and a.real.ae(b.real, eps) res = res and a.imag.ae(b.imag, eps) return res zero = mpf(0) one = mpf(1) jsn = ellipfun('sn') jcn = ellipfun('cn') jdn = ellipfun('dn') calculate_nome = lambda k: qfrom(k=k) def test_ellipfun(): mp.dps = 15 assert ellipfun('ss', 0, 0) == 1 assert ellipfun('cc', 0, 0) == 1 assert ellipfun('dd', 0, 0) == 1 assert ellipfun('nn', 0, 0) == 1 assert ellipfun('sn', 0.25, 0).ae(sin(0.25)) assert ellipfun('cn', 0.25, 0).ae(cos(0.25)) assert ellipfun('dn', 0.25, 0).ae(1) assert ellipfun('ns', 0.25, 0).ae(csc(0.25)) assert ellipfun('nc', 0.25, 0).ae(sec(0.25)) assert ellipfun('nd', 0.25, 0).ae(1) assert ellipfun('sc', 0.25, 0).ae(tan(0.25)) assert ellipfun('sd', 0.25, 0).ae(sin(0.25)) assert ellipfun('cd', 0.25, 0).ae(cos(0.25)) assert ellipfun('cs', 0.25, 0).ae(cot(0.25)) assert ellipfun('dc', 0.25, 0).ae(sec(0.25)) assert ellipfun('ds', 0.25, 0).ae(csc(0.25)) assert ellipfun('sn', 0.25, 1).ae(tanh(0.25)) assert ellipfun('cn', 0.25, 1).ae(sech(0.25)) assert ellipfun('dn', 0.25, 1).ae(sech(0.25)) assert ellipfun('ns', 0.25, 1).ae(coth(0.25)) assert ellipfun('nc', 0.25, 1).ae(cosh(0.25)) assert ellipfun('nd', 0.25, 1).ae(cosh(0.25)) assert ellipfun('sc', 0.25, 1).ae(sinh(0.25)) assert ellipfun('sd', 0.25, 1).ae(sinh(0.25)) assert ellipfun('cd', 0.25, 1).ae(1) assert ellipfun('cs', 0.25, 1).ae(csch(0.25)) assert ellipfun('dc', 0.25, 1).ae(1) assert ellipfun('ds', 0.25, 1).ae(csch(0.25)) assert ellipfun('sn', 0.25, 0.5).ae(0.24615967096986145833) assert ellipfun('cn', 0.25, 0.5).ae(0.96922928989378439337) assert ellipfun('dn', 0.25, 0.5).ae(0.98473484156599474563) assert ellipfun('ns', 0.25, 0.5).ae(4.0624038700573130369) assert ellipfun('nc', 0.25, 0.5).ae(1.0317476065024692949) assert ellipfun('nd', 0.25, 0.5).ae(1.0155017958029488665) assert ellipfun('sc', 0.25, 0.5).ae(0.25397465134058993408) assert ellipfun('sd', 0.25, 0.5).ae(0.24997558792415733063) assert ellipfun('cd', 0.25, 0.5).ae(0.98425408443195497052) assert ellipfun('cs', 0.25, 0.5).ae(3.9374008182374110826) assert ellipfun('dc', 0.25, 0.5).ae(1.0159978158253033913) assert ellipfun('ds', 0.25, 0.5).ae(4.0003906313579720593) def test_calculate_nome(): mp.dps = 100 q = calculate_nome(zero) assert(q == zero) mp.dps = 25 # used Mathematica's EllipticNomeQ[m] math1 = [(mpf(1)/10, mpf('0.006584651553858370274473060')), (mpf(2)/10, mpf('0.01394285727531826872146409')), (mpf(3)/10, mpf('0.02227743615715350822901627')), (mpf(4)/10, mpf('0.03188334731336317755064299')), (mpf(5)/10, mpf('0.04321391826377224977441774')), (mpf(6)/10, mpf('0.05702025781460967637754953')), (mpf(7)/10, mpf('0.07468994353717944761143751')), (mpf(8)/10, mpf('0.09927369733882489703607378')), (mpf(9)/10, mpf('0.1401731269542615524091055')), (mpf(9)/10, mpf('0.1401731269542615524091055'))] for i in math1: m = i[0] q = calculate_nome(sqrt(m)) assert q.ae(i[1]) mp.dps = 15 def test_jtheta(): mp.dps = 25 z = q = zero for n in range(1,5): value = jtheta(n, z, q) assert(value == (n-1)//2) for q in [one, mpf(2)]: for n in range(1,5): pytest.raises(ValueError, lambda: jtheta(n, z, q)) z = one/10 q = one/11 # Mathematical N[EllipticTheta[1, 1/10, 1/11], 25] res = mpf('0.1069552990104042681962096') result = jtheta(1, z, q) assert(result.ae(res)) # Mathematica N[EllipticTheta[2, 1/10, 1/11], 25] res = mpf('1.101385760258855791140606') result = jtheta(2, z, q) assert(result.ae(res)) # Mathematica N[EllipticTheta[3, 1/10, 1/11], 25] res = mpf('1.178319743354331061795905') result = jtheta(3, z, q) assert(result.ae(res)) # Mathematica N[EllipticTheta[4, 1/10, 1/11], 25] res = mpf('0.8219318954665153577314573') result = jtheta(4, z, q) assert(result.ae(res)) # test for sin zeros for jtheta(1, z, q) # test for cos zeros for jtheta(2, z, q) z1 = pi z2 = pi/2 for i in range(10): qstring = str(random.random()) q = mpf(qstring) result = jtheta(1, z1, q) assert(result.ae(0)) result = jtheta(2, z2, q) assert(result.ae(0)) mp.dps = 15 def test_jtheta_issue_79(): # near the circle of covergence |q| = 1 the convergence slows # down; for |q| > Q_LIM the theta functions raise ValueError mp.dps = 30 mp.dps += 30 q = mpf(6)/10 - one/10**6 - mpf(8)/10 * j mp.dps -= 30 # Mathematica run first # N[EllipticTheta[3, 1, 6/10 - 10^-6 - 8/10*I], 2000] # then it works: # N[EllipticTheta[3, 1, 6/10 - 10^-6 - 8/10*I], 30] res = mpf('32.0031009628901652627099524264') + \ mpf('16.6153027998236087899308935624') * j result = jtheta(3, 1, q) # check that for abs(q) > Q_LIM a ValueError exception is raised mp.dps += 30 q = mpf(6)/10 - one/10**7 - mpf(8)/10 * j mp.dps -= 30 pytest.raises(ValueError, lambda: jtheta(3, 1, q)) # bug reported in issue 79 mp.dps = 100 z = (1+j)/3 q = mpf(368983957219251)/10**15 + mpf(636363636363636)/10**15 * j # Mathematica N[EllipticTheta[1, z, q], 35] res = mpf('2.4439389177990737589761828991467471') + \ mpf('0.5446453005688226915290954851851490') *j mp.dps = 30 result = jtheta(1, z, q) assert(result.ae(res)) mp.dps = 80 z = 3 + 4*j q = 0.5 + 0.5*j r1 = jtheta(1, z, q) mp.dps = 15 r2 = jtheta(1, z, q) assert r1.ae(r2) mp.dps = 80 z = 3 + j q1 = exp(j*3) # longer test # for n in range(1, 6) for n in range(1, 2): mp.dps = 80 q = q1*(1 - mpf(1)/10**n) r1 = jtheta(1, z, q) mp.dps = 15 r2 = jtheta(1, z, q) assert r1.ae(r2) mp.dps = 15 # issue 79 about high derivatives assert jtheta(3, 4.5, 0.25, 9).ae(1359.04892680683) assert jtheta(3, 4.5, 0.25, 50).ae(-6.14832772630905e+33) mp.dps = 50 r = jtheta(3, 4.5, 0.25, 9) assert r.ae('1359.048926806828939547859396600218966947753213803') r = jtheta(3, 4.5, 0.25, 50) assert r.ae('-6148327726309051673317975084654262.4119215720343656') def test_jtheta_identities(): """ Tests the some of the jacobi identidies found in Abramowitz, Sec. 16.28, Pg. 576. The identities are tested to 1 part in 10^98. """ mp.dps = 110 eps1 = ldexp(eps, 30) for i in range(10): qstring = str(random.random()) q = mpf(qstring) zstring = str(10*random.random()) z = mpf(zstring) # Abramowitz 16.28.1 # v_1(z, q)**2 * v_4(0, q)**2 = v_3(z, q)**2 * v_2(0, q)**2 # - v_2(z, q)**2 * v_3(0, q)**2 term1 = (jtheta(1, z, q)**2) * (jtheta(4, zero, q)**2) term2 = (jtheta(3, z, q)**2) * (jtheta(2, zero, q)**2) term3 = (jtheta(2, z, q)**2) * (jtheta(3, zero, q)**2) equality = term1 - term2 + term3 assert(equality.ae(0, eps1)) zstring = str(100*random.random()) z = mpf(zstring) # Abramowitz 16.28.2 # v_2(z, q)**2 * v_4(0, q)**2 = v_4(z, q)**2 * v_2(0, q)**2 # - v_1(z, q)**2 * v_3(0, q)**2 term1 = (jtheta(2, z, q)**2) * (jtheta(4, zero, q)**2) term2 = (jtheta(4, z, q)**2) * (jtheta(2, zero, q)**2) term3 = (jtheta(1, z, q)**2) * (jtheta(3, zero, q)**2) equality = term1 - term2 + term3 assert(equality.ae(0, eps1)) # Abramowitz 16.28.3 # v_3(z, q)**2 * v_4(0, q)**2 = v_4(z, q)**2 * v_3(0, q)**2 # - v_1(z, q)**2 * v_2(0, q)**2 term1 = (jtheta(3, z, q)**2) * (jtheta(4, zero, q)**2) term2 = (jtheta(4, z, q)**2) * (jtheta(3, zero, q)**2) term3 = (jtheta(1, z, q)**2) * (jtheta(2, zero, q)**2) equality = term1 - term2 + term3 assert(equality.ae(0, eps1)) # Abramowitz 16.28.4 # v_4(z, q)**2 * v_4(0, q)**2 = v_3(z, q)**2 * v_3(0, q)**2 # - v_2(z, q)**2 * v_2(0, q)**2 term1 = (jtheta(4, z, q)**2) * (jtheta(4, zero, q)**2) term2 = (jtheta(3, z, q)**2) * (jtheta(3, zero, q)**2) term3 = (jtheta(2, z, q)**2) * (jtheta(2, zero, q)**2) equality = term1 - term2 + term3 assert(equality.ae(0, eps1)) # Abramowitz 16.28.5 # v_2(0, q)**4 + v_4(0, q)**4 == v_3(0, q)**4 term1 = (jtheta(2, zero, q))**4 term2 = (jtheta(4, zero, q))**4 term3 = (jtheta(3, zero, q))**4 equality = term1 + term2 - term3 assert(equality.ae(0, eps1)) mp.dps = 15 def test_jtheta_complex(): mp.dps = 30 z = mpf(1)/4 + j/8 q = mpf(1)/3 + j/7 # Mathematica N[EllipticTheta[1, 1/4 + I/8, 1/3 + I/7], 35] res = mpf('0.31618034835986160705729105731678285') + \ mpf('0.07542013825835103435142515194358975') * j r = jtheta(1, z, q) assert(mpc_ae(r, res)) # Mathematica N[EllipticTheta[2, 1/4 + I/8, 1/3 + I/7], 35] res = mpf('1.6530986428239765928634711417951828') + \ mpf('0.2015344864707197230526742145361455') * j r = jtheta(2, z, q) assert(mpc_ae(r, res)) # Mathematica N[EllipticTheta[3, 1/4 + I/8, 1/3 + I/7], 35] res = mpf('1.6520564411784228184326012700348340') + \ mpf('0.1998129119671271328684690067401823') * j r = jtheta(3, z, q) assert(mpc_ae(r, res)) # Mathematica N[EllipticTheta[4, 1/4 + I/8, 1/3 + I/7], 35] res = mpf('0.37619082382228348252047624089973824') - \ mpf('0.15623022130983652972686227200681074') * j r = jtheta(4, z, q) assert(mpc_ae(r, res)) # check some theta function identities mp.dos = 100 z = mpf(1)/4 + j/8 q = mpf(1)/3 + j/7 mp.dps += 10 a = [0,0, jtheta(2, 0, q), jtheta(3, 0, q), jtheta(4, 0, q)] t = [0, jtheta(1, z, q), jtheta(2, z, q), jtheta(3, z, q), jtheta(4, z, q)] r = [(t[2]*a[4])**2 - (t[4]*a[2])**2 + (t[1] *a[3])**2, (t[3]*a[4])**2 - (t[4]*a[3])**2 + (t[1] *a[2])**2, (t[1]*a[4])**2 - (t[3]*a[2])**2 + (t[2] *a[3])**2, (t[4]*a[4])**2 - (t[3]*a[3])**2 + (t[2] *a[2])**2, a[2]**4 + a[4]**4 - a[3]**4] mp.dps -= 10 for x in r: assert(mpc_ae(x, mpc(0))) mp.dps = 15 def test_djtheta(): mp.dps = 30 z = one/7 + j/3 q = one/8 + j/5 # Mathematica N[EllipticThetaPrime[1, 1/7 + I/3, 1/8 + I/5], 35] res = mpf('1.5555195883277196036090928995803201') - \ mpf('0.02439761276895463494054149673076275') * j result = jtheta(1, z, q, 1) assert(mpc_ae(result, res)) # Mathematica N[EllipticThetaPrime[2, 1/7 + I/3, 1/8 + I/5], 35] res = mpf('0.19825296689470982332701283509685662') - \ mpf('0.46038135182282106983251742935250009') * j result = jtheta(2, z, q, 1) assert(mpc_ae(result, res)) # Mathematica N[EllipticThetaPrime[3, 1/7 + I/3, 1/8 + I/5], 35] res = mpf('0.36492498415476212680896699407390026') - \ mpf('0.57743812698666990209897034525640369') * j result = jtheta(3, z, q, 1) assert(mpc_ae(result, res)) # Mathematica N[EllipticThetaPrime[4, 1/7 + I/3, 1/8 + I/5], 35] res = mpf('-0.38936892528126996010818803742007352') + \ mpf('0.66549886179739128256269617407313625') * j result = jtheta(4, z, q, 1) assert(mpc_ae(result, res)) for i in range(10): q = (one*random.random() + j*random.random())/2 # identity in Wittaker, Watson &21.41 a = jtheta(1, 0, q, 1) b = jtheta(2, 0, q)*jtheta(3, 0, q)*jtheta(4, 0, q) assert(a.ae(b)) # test higher derivatives mp.dps = 20 for q,z in [(one/3, one/5), (one/3 + j/8, one/5), (one/3, one/5 + j/8), (one/3 + j/7, one/5 + j/8)]: for n in [1, 2, 3, 4]: r = jtheta(n, z, q, 2) r1 = diff(lambda zz: jtheta(n, zz, q), z, n=2) assert r.ae(r1) r = jtheta(n, z, q, 3) r1 = diff(lambda zz: jtheta(n, zz, q), z, n=3) assert r.ae(r1) # identity in Wittaker, Watson &21.41 q = one/3 z = zero a = [0]*5 a[1] = jtheta(1, z, q, 3)/jtheta(1, z, q, 1) for n in [2,3,4]: a[n] = jtheta(n, z, q, 2)/jtheta(n, z, q) equality = a[2] + a[3] + a[4] - a[1] assert(equality.ae(0)) mp.dps = 15 def test_jsn(): """ Test some special cases of the sn(z, q) function. """ mp.dps = 100 # trival case result = jsn(zero, zero) assert(result == zero) # Abramowitz Table 16.5 # # sn(0, m) = 0 for i in range(10): qstring = str(random.random()) q = mpf(qstring) equality = jsn(zero, q) assert(equality.ae(0)) # Abramowitz Table 16.6.1 # # sn(z, 0) = sin(z), m == 0 # # sn(z, 1) = tanh(z), m == 1 # # It would be nice to test these, but I find that they run # in to numerical trouble. I'm currently treating as a boundary # case for sn function. mp.dps = 25 arg = one/10 #N[JacobiSN[1/10, 2^-100], 25] res = mpf('0.09983341664682815230681420') m = ldexp(one, -100) result = jsn(arg, m) assert(result.ae(res)) # N[JacobiSN[1/10, 1/10], 25] res = mpf('0.09981686718599080096451168') result = jsn(arg, arg) assert(result.ae(res)) mp.dps = 15 def test_jcn(): """ Test some special cases of the cn(z, q) function. """ mp.dps = 100 # Abramowitz Table 16.5 # cn(0, q) = 1 qstring = str(random.random()) q = mpf(qstring) cn = jcn(zero, q) assert(cn.ae(one)) # Abramowitz Table 16.6.2 # # cn(u, 0) = cos(u), m == 0 # # cn(u, 1) = sech(z), m == 1 # # It would be nice to test these, but I find that they run # in to numerical trouble. I'm currently treating as a boundary # case for cn function. mp.dps = 25 arg = one/10 m = ldexp(one, -100) #N[JacobiCN[1/10, 2^-100], 25] res = mpf('0.9950041652780257660955620') result = jcn(arg, m) assert(result.ae(res)) # N[JacobiCN[1/10, 1/10], 25] res = mpf('0.9950058256237368748520459') result = jcn(arg, arg) assert(result.ae(res)) mp.dps = 15 def test_jdn(): """ Test some special cases of the dn(z, q) function. """ mp.dps = 100 # Abramowitz Table 16.5 # dn(0, q) = 1 mstring = str(random.random()) m = mpf(mstring) dn = jdn(zero, m) assert(dn.ae(one)) mp.dps = 25 # N[JacobiDN[1/10, 1/10], 25] res = mpf('0.9995017055025556219713297') arg = one/10 result = jdn(arg, arg) assert(result.ae(res)) mp.dps = 15 def test_sn_cn_dn_identities(): """ Tests the some of the jacobi elliptic function identities found on Mathworld. Haven't found in Abramowitz. """ mp.dps = 100 N = 5 for i in range(N): qstring = str(random.random()) q = mpf(qstring) zstring = str(100*random.random()) z = mpf(zstring) # MathWorld # sn(z, q)**2 + cn(z, q)**2 == 1 term1 = jsn(z, q)**2 term2 = jcn(z, q)**2 equality = one - term1 - term2 assert(equality.ae(0)) # MathWorld # k**2 * sn(z, m)**2 + dn(z, m)**2 == 1 for i in range(N): mstring = str(random.random()) m = mpf(qstring) k = m.sqrt() zstring = str(10*random.random()) z = mpf(zstring) term1 = k**2 * jsn(z, m)**2 term2 = jdn(z, m)**2 equality = one - term1 - term2 assert(equality.ae(0)) for i in range(N): mstring = str(random.random()) m = mpf(mstring) k = m.sqrt() zstring = str(random.random()) z = mpf(zstring) # MathWorld # k**2 * cn(z, m)**2 + (1 - k**2) = dn(z, m)**2 term1 = k**2 * jcn(z, m)**2 term2 = 1 - k**2 term3 = jdn(z, m)**2 equality = term3 - term1 - term2 assert(equality.ae(0)) K = ellipk(k**2) # Abramowitz Table 16.5 # sn(K, m) = 1; K is K(k), first complete elliptic integral r = jsn(K, m) assert(r.ae(one)) # Abramowitz Table 16.5 # cn(K, q) = 0; K is K(k), first complete elliptic integral equality = jcn(K, m) assert(equality.ae(0)) # Abramowitz Table 16.6.3 # dn(z, 0) = 1, m == 0 z = m value = jdn(z, zero) assert(value.ae(one)) mp.dps = 15 def test_sn_cn_dn_complex(): mp.dps = 30 # N[JacobiSN[1/4 + I/8, 1/3 + I/7], 35] in Mathematica res = mpf('0.2495674401066275492326652143537') + \ mpf('0.12017344422863833381301051702823') * j u = mpf(1)/4 + j/8 m = mpf(1)/3 + j/7 r = jsn(u, m) assert(mpc_ae(r, res)) #N[JacobiCN[1/4 + I/8, 1/3 + I/7], 35] res = mpf('0.9762691700944007312693721148331') - \ mpf('0.0307203994181623243583169154824')*j r = jcn(u, m) #assert r.real.ae(res.real) #assert r.imag.ae(res.imag) assert(mpc_ae(r, res)) #N[JacobiDN[1/4 + I/8, 1/3 + I/7], 35] res = mpf('0.99639490163039577560547478589753039') - \ mpf('0.01346296520008176393432491077244994')*j r = jdn(u, m) assert(mpc_ae(r, res)) mp.dps = 15 def test_elliptic_integrals(): # Test cases from Carlson's paper mp.dps = 15 assert elliprd(0,2,1).ae(1.7972103521033883112) assert elliprd(2,3,4).ae(0.16510527294261053349) assert elliprd(j,-j,2).ae(0.65933854154219768919) assert elliprd(0,j,-j).ae(1.2708196271909686299 + 2.7811120159520578777j) assert elliprd(0,j-1,j).ae(-1.8577235439239060056 - 0.96193450888838559989j) assert elliprd(-2-j,-j,-1+j).ae(1.8249027393703805305 - 1.2218475784827035855j) # extra test cases assert elliprg(0,0,0) == 0 assert elliprg(0,0,16).ae(2) assert elliprg(0,16,0).ae(2) assert elliprg(16,0,0).ae(2) assert elliprg(1,4,0).ae(1.2110560275684595248036) assert elliprg(1,0,4).ae(1.2110560275684595248036) assert elliprg(0,4,1).ae(1.2110560275684595248036) # should be symmetric -- fixes a bug present in the paper x,y,z = 1,1j,-1+1j assert elliprg(x,y,z).ae(0.64139146875812627545 + 0.58085463774808290907j) assert elliprg(x,z,y).ae(0.64139146875812627545 + 0.58085463774808290907j) assert elliprg(y,x,z).ae(0.64139146875812627545 + 0.58085463774808290907j) assert elliprg(y,z,x).ae(0.64139146875812627545 + 0.58085463774808290907j) assert elliprg(z,x,y).ae(0.64139146875812627545 + 0.58085463774808290907j) assert elliprg(z,y,x).ae(0.64139146875812627545 + 0.58085463774808290907j) for n in [5, 15, 30, 60, 100]: mp.dps = n assert elliprf(1,2,0).ae('1.3110287771460599052324197949455597068413774757158115814084108519003952935352071251151477664807145467230678763') assert elliprf(0.5,1,0).ae('1.854074677301371918433850347195260046217598823521766905585928045056021776838119978357271861650371897277771871') assert elliprf(j,-j,0).ae('1.854074677301371918433850347195260046217598823521766905585928045056021776838119978357271861650371897277771871') assert elliprf(j-1,j,0).ae(mpc('0.79612586584233913293056938229563057846592264089185680214929401744498956943287031832657642790719940442165621412', '-1.2138566698364959864300942567386038975419875860741507618279563735753073152507112254567291141460317931258599889')) assert elliprf(2,3,4).ae('0.58408284167715170669284916892566789240351359699303216166309375305508295130412919665541330837704050454472379308') assert elliprf(j,-j,2).ae('1.0441445654064360931078658361850779139591660747973017593275012615517220315993723776182276555339288363064476126') assert elliprf(j-1,j,1-j).ae(mpc('0.93912050218619371196624617169781141161485651998254431830645241993282941057500174238125105410055253623847335313', '-0.53296252018635269264859303449447908970360344322834582313172115220559316331271520508208025270300138589669326136')) assert elliprc(0,0.25).ae(+pi) assert elliprc(2.25,2).ae(+ln2) assert elliprc(0,j).ae(mpc('1.1107207345395915617539702475151734246536554223439225557713489017391086982748684776438317336911913093408525532', '-1.1107207345395915617539702475151734246536554223439225557713489017391086982748684776438317336911913093408525532')) assert elliprc(-j,j).ae(mpc('1.2260849569072198222319655083097718755633725139745941606203839524036426936825652935738621522906572884239069297', '-0.34471136988767679699935618332997956653521218571295874986708834375026550946053920574015526038040124556716711353')) assert elliprc(0.25,-2).ae(ln2/3) assert elliprc(j,-1).ae(mpc('0.77778596920447389875196055840799837589537035343923012237628610795937014001905822029050288316217145443865649819', '0.1983248499342877364755170948292130095921681309577950696116251029742793455964385947473103628983664877025779304')) assert elliprj(0,1,2,3).ae('0.77688623778582332014190282640545501102298064276022952731669118325952563819813258230708177398475643634103990878') assert elliprj(2,3,4,5).ae('0.14297579667156753833233879421985774801466647854232626336218889885463800128817976132826443904216546421431528308') assert elliprj(2,3,4,-1+j).ae(mpc('0.13613945827770535203521374457913768360237593025944342652613569368333226052158214183059386307242563164036672709', '-0.38207561624427164249600936454845112611060375760094156571007648297226090050927156176977091273224510621553615189')) assert elliprj(j,-j,0,2).ae('1.6490011662710884518243257224860232300246792717163891216346170272567376981346412066066050103935109581019055806') assert elliprj(-1+j,-1-j,1,2).ae('0.94148358841220238083044612133767270187474673547917988681610772381758628963408843935027667916713866133196845063') assert elliprj(j,-j,0,1-j).ae(mpc('1.8260115229009316249372594065790946657011067182850435297162034335356430755397401849070610280860044610878657501', '1.2290661908643471500163617732957042849283739403009556715926326841959667290840290081010472716420690899886276961')) assert elliprj(-1+j,-1-j,1,-3+j).ae(mpc('-0.61127970812028172123588152373622636829986597243716610650831553882054127570542477508023027578037045504958619422', '-1.0684038390006807880182112972232562745485871763154040245065581157751693730095703406209466903752930797510491155')) assert elliprj(-1+j,-2-j,-j,-1+j).ae(mpc('1.8249027393703805304622013339009022294368078659619988943515764258335975852685224202567854526307030593012768954', '-1.2218475784827035854568450371590419833166777535029296025352291308244564398645467465067845461070602841312456831')) assert elliprg(0,16,16).ae(+pi) assert elliprg(2,3,4).ae('1.7255030280692277601061148835701141842692457170470456590515892070736643637303053506944907685301315299153040991') assert elliprg(0,j,-j).ae('0.42360654239698954330324956174109581824072295516347109253028968632986700241706737986160014699730561497106114281') assert elliprg(j-1,j,0).ae(mpc('0.44660591677018372656731970402124510811555212083508861036067729944477855594654762496407405328607219895053798354', '0.70768352357515390073102719507612395221369717586839400605901402910893345301718731499237159587077682267374159282')) assert elliprg(-j,j-1,j).ae(mpc('0.36023392184473309033675652092928695596803358846377334894215349632203382573844427952830064383286995172598964266', '0.40348623401722113740956336997761033878615232917480045914551915169013722542827052849476969199578321834819903921')) assert elliprg(0, mpf('0.0796'), 4).ae('1.0284758090288040009838871385180217366569777284430590125081211090574701293154645750017813190805144572673802094') mp.dps = 15 def test_issue_238(): assert isnan(qfrom(m=nan)) mpmath-1.1.0/mpmath/tests/test_fp.py000066400000000000000000002576151340375245600174760ustar00rootroot00000000000000""" Easy-to-use test-generating code: cases = ''' exp 2.25 log 2.25 ''' from mpmath import * mp.dps = 20 for test in cases.splitlines(): if not test: continue words = test.split() fname = words[0] args = words[1:] argstr = ", ".join(args) testline = "%s(%s)" % (fname, argstr) ans = str(eval(testline)) print " assert ae(fp.%s, %s)" % (testline, ans) """ from mpmath import fp def ae(x, y, tol=1e-12): if x == y: return True return abs(x-y) <= tol*abs(y) def test_conj(): assert fp.conj(4) == 4 assert fp.conj(3+4j) == 3-4j assert fp.fdot([1,2],[3,2+1j], conjugate=True) == 7-2j def test_fp_number_parts(): assert ae(fp.arg(3), 0.0) assert ae(fp.arg(-3), 3.1415926535897932385) assert ae(fp.arg(3j), 1.5707963267948966192) assert ae(fp.arg(-3j), -1.5707963267948966192) assert ae(fp.arg(2+3j), 0.98279372324732906799) assert ae(fp.arg(-1-1j), -2.3561944901923449288) assert ae(fp.re(2.5), 2.5) assert ae(fp.re(2.5+3j), 2.5) assert ae(fp.im(2.5), 0.0) assert ae(fp.im(2.5+3j), 3.0) assert ae(fp.floor(2.5), 2.0) assert ae(fp.floor(2), 2.0) assert ae(fp.floor(2.0+0j), (2.0 + 0.0j)) assert ae(fp.floor(-1.5-0.5j), (-2.0 - 1.0j)) assert ae(fp.ceil(2.5), 3.0) assert ae(fp.ceil(2), 2.0) assert ae(fp.ceil(2.0+0j), (2.0 + 0.0j)) assert ae(fp.ceil(-1.5-0.5j), (-1.0 + 0.0j)) def test_fp_cospi_sinpi(): assert ae(fp.sinpi(0), 0.0) assert ae(fp.sinpi(0.25), 0.7071067811865475244) assert ae(fp.sinpi(0.5), 1.0) assert ae(fp.sinpi(0.75), 0.7071067811865475244) assert ae(fp.sinpi(1), 0.0) assert ae(fp.sinpi(1.25), -0.7071067811865475244) assert ae(fp.sinpi(1.5), -1.0) assert ae(fp.sinpi(1.75), -0.7071067811865475244) assert ae(fp.sinpi(2), 0.0) assert ae(fp.sinpi(2.25), 0.7071067811865475244) assert ae(fp.sinpi(0+3j), (0.0 + 6195.8238636085899556j)) assert ae(fp.sinpi(0.25+3j), (4381.1091260582448033 + 4381.1090689950686908j)) assert ae(fp.sinpi(0.5+3j), (6195.8239443081075259 + 0.0j)) assert ae(fp.sinpi(0.75+3j), (4381.1091260582448033 - 4381.1090689950686908j)) assert ae(fp.sinpi(1+3j), (0.0 - 6195.8238636085899556j)) assert ae(fp.sinpi(1.25+3j), (-4381.1091260582448033 - 4381.1090689950686908j)) assert ae(fp.sinpi(1.5+3j), (-6195.8239443081075259 + 0.0j)) assert ae(fp.sinpi(1.75+3j), (-4381.1091260582448033 + 4381.1090689950686908j)) assert ae(fp.sinpi(2+3j), (0.0 + 6195.8238636085899556j)) assert ae(fp.sinpi(2.25+3j), (4381.1091260582448033 + 4381.1090689950686908j)) assert ae(fp.sinpi(-0.75), -0.7071067811865475244) assert ae(fp.sinpi(-1e-10), -3.1415926535897933529e-10) assert ae(fp.sinpi(1e-10), 3.1415926535897933529e-10) assert ae(fp.sinpi(1e-10+1e-10j), (3.141592653589793353e-10 + 3.1415926535897933528e-10j)) assert ae(fp.sinpi(1e-10-1e-10j), (3.141592653589793353e-10 - 3.1415926535897933528e-10j)) assert ae(fp.sinpi(-1e-10+1e-10j), (-3.141592653589793353e-10 + 3.1415926535897933528e-10j)) assert ae(fp.sinpi(-1e-10-1e-10j), (-3.141592653589793353e-10 - 3.1415926535897933528e-10j)) assert ae(fp.cospi(0), 1.0) assert ae(fp.cospi(0.25), 0.7071067811865475244) assert ae(fp.cospi(0.5), 0.0) assert ae(fp.cospi(0.75), -0.7071067811865475244) assert ae(fp.cospi(1), -1.0) assert ae(fp.cospi(1.25), -0.7071067811865475244) assert ae(fp.cospi(1.5), 0.0) assert ae(fp.cospi(1.75), 0.7071067811865475244) assert ae(fp.cospi(2), 1.0) assert ae(fp.cospi(2.25), 0.7071067811865475244) assert ae(fp.cospi(0+3j), (6195.8239443081075259 + 0.0j)) assert ae(fp.cospi(0.25+3j), (4381.1091260582448033 - 4381.1090689950686908j)) assert ae(fp.cospi(0.5+3j), (0.0 - 6195.8238636085899556j)) assert ae(fp.cospi(0.75+3j), (-4381.1091260582448033 - 4381.1090689950686908j)) assert ae(fp.cospi(1+3j), (-6195.8239443081075259 + 0.0j)) assert ae(fp.cospi(1.25+3j), (-4381.1091260582448033 + 4381.1090689950686908j)) assert ae(fp.cospi(1.5+3j), (0.0 + 6195.8238636085899556j)) assert ae(fp.cospi(1.75+3j), (4381.1091260582448033 + 4381.1090689950686908j)) assert ae(fp.cospi(2+3j), (6195.8239443081075259 + 0.0j)) assert ae(fp.cospi(2.25+3j), (4381.1091260582448033 - 4381.1090689950686908j)) assert ae(fp.cospi(-0.75), -0.7071067811865475244) assert ae(fp.sinpi(-0.7), -0.80901699437494750611) assert ae(fp.cospi(-0.7), -0.5877852522924730163) assert ae(fp.cospi(-3+2j), (-267.74676148374822225 + 0.0j)) assert ae(fp.sinpi(-3+2j), (0.0 - 267.74489404101651426j)) assert ae(fp.sinpi(-0.7+2j), (-216.6116802292079471 - 157.37650009392034693j)) assert ae(fp.cospi(-0.7+2j), (-157.37759774921754565 + 216.61016943630197336j)) def test_fp_expj(): assert ae(fp.expj(0), (1.0 + 0.0j)) assert ae(fp.expj(1), (0.5403023058681397174 + 0.84147098480789650665j)) assert ae(fp.expj(2), (-0.416146836547142387 + 0.9092974268256816954j)) assert ae(fp.expj(0.75), (0.73168886887382088631 + 0.68163876002333416673j)) assert ae(fp.expj(2+3j), (-0.020718731002242879378 + 0.045271253156092975488j)) assert ae(fp.expjpi(0), (1.0 + 0.0j)) assert ae(fp.expjpi(1), (-1.0 + 0.0j)) assert ae(fp.expjpi(2), (1.0 + 0.0j)) assert ae(fp.expjpi(0.75), (-0.7071067811865475244 + 0.7071067811865475244j)) assert ae(fp.expjpi(2+3j), (0.000080699517570304599239 + 0.0j)) def test_fp_bernoulli(): assert ae(fp.bernoulli(0), 1.0) assert ae(fp.bernoulli(1), -0.5) assert ae(fp.bernoulli(2), 0.16666666666666666667) assert ae(fp.bernoulli(10), 0.075757575757575757576) assert ae(fp.bernoulli(11), 0.0) def test_fp_gamma(): assert ae(fp.gamma(1), 1.0) assert ae(fp.gamma(1.5), 0.88622692545275801365) assert ae(fp.gamma(10), 362880.0) assert ae(fp.gamma(-0.5), -3.5449077018110320546) assert ae(fp.gamma(-7.1), 0.0016478244570263333622) assert ae(fp.gamma(12.3), 83385367.899970000963) assert ae(fp.gamma(2+0j), (1.0 + 0.0j)) assert ae(fp.gamma(-2.5+0j), (-0.94530872048294188123 + 0.0j)) assert ae(fp.gamma(3+4j), (0.0052255384713692141947 - 0.17254707929430018772j)) assert ae(fp.gamma(-3-4j), (0.00001460997305874775607 - 0.000020760733311509070396j)) assert ae(fp.fac(0), 1.0) assert ae(fp.fac(1), 1.0) assert ae(fp.fac(20), 2432902008176640000.0) assert ae(fp.fac(-3.5), -0.94530872048294188123) assert ae(fp.fac(2+3j), (-0.44011340763700171113 - 0.06363724312631702183j)) assert ae(fp.loggamma(1.0), 0.0) assert ae(fp.loggamma(2.0), 0.0) assert ae(fp.loggamma(3.0), 0.69314718055994530942) assert ae(fp.loggamma(7.25), 7.0521854507385394449) assert ae(fp.loggamma(1000.0), 5905.2204232091812118) assert ae(fp.loggamma(1e50), 1.1412925464970229298e+52) assert ae(fp.loggamma(1e25+1e25j), (5.6125802751733671621e+26 + 5.7696599078528568383e+26j)) assert ae(fp.loggamma(3+4j), (-1.7566267846037841105 + 4.7426644380346579282j)) assert ae(fp.loggamma(-0.5), (1.2655121234846453965 - 3.1415926535897932385j)) assert ae(fp.loggamma(-1.25), (1.3664317612369762346 - 6.2831853071795864769j)) assert ae(fp.loggamma(-2.75), (0.0044878975359557733115 - 9.4247779607693797154j)) assert ae(fp.loggamma(-3.5), (-1.3090066849930420464 - 12.566370614359172954j)) assert ae(fp.loggamma(-4.5), (-2.8130840817693161197 - 15.707963267948966192j)) assert ae(fp.loggamma(-2+3j), (-6.776523813485657093 - 4.568791367260286402j)) assert ae(fp.loggamma(-1000.3), (-5912.8440347785205041 - 3144.7342462433830317j)) assert ae(fp.loggamma(-100-100j), (-632.35117666833135562 - 158.37641469650352462j)) assert ae(fp.loggamma(1e-10), 23.025850929882735237) assert ae(fp.loggamma(-1e-10), (23.02585092999817837 - 3.1415926535897932385j)) assert ae(fp.loggamma(1e-10j), (23.025850929940456804 - 1.5707963268526181857j)) assert ae(fp.loggamma(1e-10j-1e-10), (22.679277339718205716 - 2.3561944902500664954j)) def test_fp_psi(): assert ae(fp.psi(0, 3.7), 1.1671535393615114409) assert ae(fp.psi(0, 0.5), -1.9635100260214234794) assert ae(fp.psi(0, 1), -0.57721566490153286061) assert ae(fp.psi(0, -2.5), 1.1031566406452431872) assert ae(fp.psi(0, 12.9), 2.5179671503279156347) assert ae(fp.psi(0, 100), 4.6001618527380874002) assert ae(fp.psi(0, 2500.3), 7.8239660143238547877) assert ae(fp.psi(0, 1e40), 92.103403719761827391) assert ae(fp.psi(0, 1e200), 460.51701859880913677) assert ae(fp.psi(0, 3.7+0j), (1.1671535393615114409 + 0.0j)) assert ae(fp.psi(1, 3), 0.39493406684822643647) assert ae(fp.psi(3, 2+3j), (-0.05383196209159972116 + 0.0076890935247364805218j)) assert ae(fp.psi(4, -0.5+1j), (1.2719531355492328195 - 18.211833410936276774j)) assert ae(fp.harmonic(0), 0.0) assert ae(fp.harmonic(1), 1.0) assert ae(fp.harmonic(2), 1.5) assert ae(fp.harmonic(100), 5.1873775176396202608) assert ae(fp.harmonic(-2.5), 1.2803723055467760478) assert ae(fp.harmonic(2+3j), (1.9390425294578375875 + 0.87336044981834544043j)) assert ae(fp.harmonic(-5-4j), (2.3725754822349437733 - 2.4160904444801621j)) def test_fp_zeta(): assert ae(fp.zeta(1e100), 1.0) assert ae(fp.zeta(3), 1.2020569031595942854) assert ae(fp.zeta(2+0j), (1.6449340668482264365 + 0.0j)) assert ae(fp.zeta(0.93), -13.713619351638164784) assert ae(fp.zeta(1.74), 1.9796863545771774095) assert ae(fp.zeta(0.0), -0.5) assert ae(fp.zeta(-1.0), -0.083333333333333333333) assert ae(fp.zeta(-2.0), 0.0) assert ae(fp.zeta(-3.0), 0.0083333333333333333333) assert ae(fp.zeta(-500.0), 0.0) assert ae(fp.zeta(-7.4), 0.0036537321227995882447) assert ae(fp.zeta(2.1), 1.5602165335033620158) assert ae(fp.zeta(26.9), 1.0000000079854809935) assert ae(fp.zeta(26), 1.0000000149015548284) assert ae(fp.zeta(27), 1.0000000074507117898) assert ae(fp.zeta(28), 1.0000000037253340248) assert ae(fp.zeta(27.1), 1.000000006951755045) assert ae(fp.zeta(32.7), 1.0000000001433243232) assert ae(fp.zeta(100), 1.0) assert ae(fp.altzeta(3.5), 0.92755357777394803511) assert ae(fp.altzeta(1), 0.69314718055994530942) assert ae(fp.altzeta(2), 0.82246703342411321824) assert ae(fp.altzeta(0), 0.5) assert ae(fp.zeta(-2+3j, 1), (0.13297115587929864827 + 0.12305330040458776494j)) assert ae(fp.zeta(-2+3j, 5), (18.384866151867576927 - 11.377015110597711009j)) assert ae(fp.zeta(1.0000000001), 9999999173.1735741337) assert ae(fp.zeta(0.9999999999), -9999999172.0191428039) assert ae(fp.zeta(1+0.000000001j), (0.57721566490153286061 - 999999999.99999993765j)) assert ae(fp.primezeta(2.5+4j), (-0.16922458243438033385 - 0.010847965298387727811j)) assert ae(fp.primezeta(4), 0.076993139764246844943) assert ae(fp.riemannr(3.7), 2.3034079839110855717) assert ae(fp.riemannr(8), 3.9011860449341499474) assert ae(fp.riemannr(3+4j), (2.2369653314259991796 + 1.6339943856990281694j)) def test_fp_hyp2f1(): assert ae(fp.hyp2f1(1, (3,2), 3.25, 5.0), (-0.46600275923108143059 - 0.74393667908854842325j)) assert ae(fp.hyp2f1(1+1j, (3,2), 3.25, 5.0), (-5.9208875603806515987 - 2.3813557707889590686j)) assert ae(fp.hyp2f1(1+1j, (3,2), 3.25, 2+3j), (0.17174552030925080445 + 0.19589781970539389999j)) def test_fp_erf(): assert fp.erf(2) == fp.erf(2.0) == fp.erf(2.0+0.0j) assert fp.erf(fp.inf) == 1.0 assert fp.erf(fp.ninf) == -1.0 assert ae(fp.erf(0), 0.0) assert ae(fp.erf(-0), -0.0) assert ae(fp.erf(0.3), 0.32862675945912741619) assert ae(fp.erf(-0.3), -0.32862675945912741619) assert ae(fp.erf(0.9), 0.79690821242283213966) assert ae(fp.erf(-0.9), -0.79690821242283213966) assert ae(fp.erf(1.0), 0.84270079294971486934) assert ae(fp.erf(-1.0), -0.84270079294971486934) assert ae(fp.erf(1.1), 0.88020506957408172966) assert ae(fp.erf(-1.1), -0.88020506957408172966) assert ae(fp.erf(8.5), 1.0) assert ae(fp.erf(-8.5), -1.0) assert ae(fp.erf(9.1), 1.0) assert ae(fp.erf(-9.1), -1.0) assert ae(fp.erf(20.0), 1.0) assert ae(fp.erf(-20.0), -1.0) assert ae(fp.erf(10000.0), 1.0) assert ae(fp.erf(-10000.0), -1.0) assert ae(fp.erf(1e+50), 1.0) assert ae(fp.erf(-1e+50), -1.0) assert ae(fp.erf(1j), 1.650425758797542876j) assert ae(fp.erf(-1j), -1.650425758797542876j) assert ae(fp.erf((2+3j)), (-20.829461427614568389 + 8.6873182714701631444j)) assert ae(fp.erf(-(2+3j)), -(-20.829461427614568389 + 8.6873182714701631444j)) assert ae(fp.erf((8+9j)), (-1072004.2525062051158 + 364149.91954310255423j)) assert ae(fp.erf(-(8+9j)), -(-1072004.2525062051158 + 364149.91954310255423j)) assert fp.erfc(fp.inf) == 0.0 assert fp.erfc(fp.ninf) == 2.0 assert fp.erfc(0) == 1 assert fp.erfc(-0.0) == 1 assert fp.erfc(0+0j) == 1 assert ae(fp.erfc(0.3), 0.67137324054087258381) assert ae(fp.erfc(-0.3), 1.3286267594591274162) assert ae(fp.erfc(0.9), 0.20309178757716786034) assert ae(fp.erfc(-0.9), 1.7969082124228321397) assert ae(fp.erfc(1.0), 0.15729920705028513066) assert ae(fp.erfc(-1.0), 1.8427007929497148693) assert ae(fp.erfc(1.1), 0.11979493042591827034) assert ae(fp.erfc(-1.1), 1.8802050695740817297) assert ae(fp.erfc(8.5), 2.7623240713337714461e-33) assert ae(fp.erfc(-8.5), 2.0) assert ae(fp.erfc(9.1), 6.6969004279886077452e-38) assert ae(fp.erfc(-9.1), 2.0) assert ae(fp.erfc(20.0), 5.3958656116079009289e-176) assert ae(fp.erfc(-20.0), 2.0) assert ae(fp.erfc(10000.0), 0.0) assert ae(fp.erfc(-10000.0), 2.0) assert ae(fp.erfc(1e+50), 0.0) assert ae(fp.erfc(-1e+50), 2.0) assert ae(fp.erfc(1j), (1.0 - 1.650425758797542876j)) assert ae(fp.erfc(-1j), (1.0 + 1.650425758797542876j)) assert ae(fp.erfc((2+3j)), (21.829461427614568389 - 8.6873182714701631444j), 1e-13) assert ae(fp.erfc(-(2+3j)), (-19.829461427614568389 + 8.6873182714701631444j), 1e-13) assert ae(fp.erfc((8+9j)), (1072005.2525062051158 - 364149.91954310255423j)) assert ae(fp.erfc(-(8+9j)), (-1072003.2525062051158 + 364149.91954310255423j)) assert ae(fp.erfc(20+0j), (5.3958656116079009289e-176 + 0.0j)) def test_fp_lambertw(): assert ae(fp.lambertw(0.0), 0.0) assert ae(fp.lambertw(1.0), 0.567143290409783873) assert ae(fp.lambertw(7.5), 1.5662309537823875394) assert ae(fp.lambertw(-0.25), -0.35740295618138890307) assert ae(fp.lambertw(-10.0), (1.3699809685212708156 + 2.140194527074713196j)) assert ae(fp.lambertw(0+0j), (0.0 + 0.0j)) assert ae(fp.lambertw(4+0j), (1.2021678731970429392 + 0.0j)) assert ae(fp.lambertw(1000.5), 5.2500227450408980127) assert ae(fp.lambertw(1e100), 224.84310644511850156) assert ae(fp.lambertw(-1000.0), (5.1501630246362515223 + 2.6641981432905204596j)) assert ae(fp.lambertw(1e-10), 9.9999999990000003645e-11) assert ae(fp.lambertw(1e-10j), (1.0000000000000000728e-20 + 1.0000000000000000364e-10j)) assert ae(fp.lambertw(3+4j), (1.2815618061237758782 + 0.53309522202097107131j)) assert ae(fp.lambertw(-3-4j), (1.0750730665692549276 - 1.3251023817343588823j)) assert ae(fp.lambertw(10000+1000j), (7.2361526563371602186 + 0.087567810943839352034j)) assert ae(fp.lambertw(0.0, -1), -fp.inf) assert ae(fp.lambertw(1.0, -1), (-1.5339133197935745079 - 4.3751851530618983855j)) assert ae(fp.lambertw(7.5, -1), (0.44125668415098614999 - 4.8039842008452390179j)) assert ae(fp.lambertw(-0.25, -1), -2.1532923641103496492) assert ae(fp.lambertw(-10.0, -1), (1.3699809685212708156 - 2.140194527074713196j)) assert ae(fp.lambertw(0+0j, -1), -fp.inf) assert ae(fp.lambertw(4+0j, -1), (-0.15730793189620765317 - 4.6787800704666656212j)) assert ae(fp.lambertw(1000.5, -1), (4.9153765415404024736 - 5.4465682700815159569j)) assert ae(fp.lambertw(1e100, -1), (224.84272130101601052 - 6.2553713838167244141j)) assert ae(fp.lambertw(-1000.0, -1), (5.1501630246362515223 - 2.6641981432905204596j)) assert ae(fp.lambertw(1e-10, -1), (-26.303186778379041521 - 3.2650939117038283975j)) assert ae(fp.lambertw(1e-10j, -1), (-26.297238779529035028 - 1.6328071613455765135j)) assert ae(fp.lambertw(3+4j, -1), (0.25856740686699741676 - 3.8521166861614355895j)) assert ae(fp.lambertw(-3-4j, -1), (-0.32028750204310768396 - 6.8801677192091972343j)) assert ae(fp.lambertw(10000+1000j, -1), (7.0255308742285435567 - 5.5177506835734067601j)) assert ae(fp.lambertw(0.0, 2), -fp.inf) assert ae(fp.lambertw(1.0, 2), (-2.4015851048680028842 + 10.776299516115070898j)) assert ae(fp.lambertw(7.5, 2), (-0.38003357962843791529 + 10.960916473368746184j)) assert ae(fp.lambertw(-0.25, 2), (-4.0558735269061511898 + 13.852334658567271386j)) assert ae(fp.lambertw(-10.0, 2), (-0.34479123764318858696 + 14.112740596763592363j)) assert ae(fp.lambertw(0+0j, 2), -fp.inf) assert ae(fp.lambertw(4+0j, 2), (-1.0070343323804262788 + 10.903476551861683082j)) assert ae(fp.lambertw(1000.5, 2), (4.4076185165459395295 + 11.365524591091402177j)) assert ae(fp.lambertw(1e100, 2), (224.84156762724875878 + 12.510785262632255672j)) assert ae(fp.lambertw(-1000.0, 2), (4.1984245610246530756 + 14.420478573754313845j)) assert ae(fp.lambertw(1e-10, 2), (-26.362258095445866488 + 9.7800247407031482519j)) assert ae(fp.lambertw(1e-10j, 2), (-26.384250801683084252 + 11.403535950607739763j)) assert ae(fp.lambertw(3+4j, 2), (-0.86554679943333993562 + 11.849956798331992027j)) assert ae(fp.lambertw(-3-4j, 2), (-0.55792273874679112639 + 8.7173627024159324811j)) assert ae(fp.lambertw(10000+1000j, 2), (6.6223802254585662734 + 11.61348646825020766j)) def test_fp_stress_ei_e1(): # Can be tightened on recent Pythons with more accurate math/cmath ATOL = 1e-13 PTOL = 1e-12 v = fp.e1(1.1641532182693481445e-10) assert ae(v, 22.296641293693077672, tol=ATOL) assert type(v) is float v = fp.e1(0.25) assert ae(v, 1.0442826344437381945, tol=ATOL) assert type(v) is float v = fp.e1(1.0) assert ae(v, 0.21938393439552027368, tol=ATOL) assert type(v) is float v = fp.e1(2.0) assert ae(v, 0.048900510708061119567, tol=ATOL) assert type(v) is float v = fp.e1(5.0) assert ae(v, 0.0011482955912753257973, tol=ATOL) assert type(v) is float v = fp.e1(20.0) assert ae(v, 9.8355252906498816904e-11, tol=ATOL) assert type(v) is float v = fp.e1(30.0) assert ae(v, 3.0215520106888125448e-15, tol=ATOL) assert type(v) is float v = fp.e1(40.0) assert ae(v, 1.0367732614516569722e-19, tol=ATOL) assert type(v) is float v = fp.e1(50.0) assert ae(v, 3.7832640295504590187e-24, tol=ATOL) assert type(v) is float v = fp.e1(80.0) assert ae(v, 2.2285432586884729112e-37, tol=ATOL) assert type(v) is float v = fp.e1((1.1641532182693481445e-10 + 0.0j)) assert ae(v, (22.296641293693077672 + 0.0j), tol=ATOL) assert ae(v.real, 22.296641293693077672, tol=PTOL) assert v.imag == 0 v = fp.e1((0.25 + 0.0j)) assert ae(v, (1.0442826344437381945 + 0.0j), tol=ATOL) assert ae(v.real, 1.0442826344437381945, tol=PTOL) assert v.imag == 0 v = fp.e1((1.0 + 0.0j)) assert ae(v, (0.21938393439552027368 + 0.0j), tol=ATOL) assert ae(v.real, 0.21938393439552027368, tol=PTOL) assert v.imag == 0 v = fp.e1((2.0 + 0.0j)) assert ae(v, (0.048900510708061119567 + 0.0j), tol=ATOL) assert ae(v.real, 0.048900510708061119567, tol=PTOL) assert v.imag == 0 v = fp.e1((5.0 + 0.0j)) assert ae(v, (0.0011482955912753257973 + 0.0j), tol=ATOL) assert ae(v.real, 0.0011482955912753257973, tol=PTOL) assert v.imag == 0 v = fp.e1((20.0 + 0.0j)) assert ae(v, (9.8355252906498816904e-11 + 0.0j), tol=ATOL) assert ae(v.real, 9.8355252906498816904e-11, tol=PTOL) assert v.imag == 0 v = fp.e1((30.0 + 0.0j)) assert ae(v, (3.0215520106888125448e-15 + 0.0j), tol=ATOL) assert ae(v.real, 3.0215520106888125448e-15, tol=PTOL) assert v.imag == 0 v = fp.e1((40.0 + 0.0j)) assert ae(v, (1.0367732614516569722e-19 + 0.0j), tol=ATOL) assert ae(v.real, 1.0367732614516569722e-19, tol=PTOL) assert v.imag == 0 v = fp.e1((50.0 + 0.0j)) assert ae(v, (3.7832640295504590187e-24 + 0.0j), tol=ATOL) assert ae(v.real, 3.7832640295504590187e-24, tol=PTOL) assert v.imag == 0 v = fp.e1((80.0 + 0.0j)) assert ae(v, (2.2285432586884729112e-37 + 0.0j), tol=ATOL) assert ae(v.real, 2.2285432586884729112e-37, tol=PTOL) assert v.imag == 0 v = fp.e1((4.6566128730773925781e-10 + 1.1641532182693481445e-10j)) assert ae(v, (20.880034622014215597 - 0.24497866301044883237j), tol=ATOL) assert ae(v.real, 20.880034622014215597, tol=PTOL) assert ae(v.imag, -0.24497866301044883237, tol=PTOL) v = fp.e1((1.0 + 0.25j)) assert ae(v, (0.19731063945004229095 - 0.087366045774299963672j), tol=ATOL) assert ae(v.real, 0.19731063945004229095, tol=PTOL) assert ae(v.imag, -0.087366045774299963672, tol=PTOL) v = fp.e1((4.0 + 1.0j)) assert ae(v, (0.0013106173980145506944 - 0.0034542480199350626699j), tol=ATOL) assert ae(v.real, 0.0013106173980145506944, tol=PTOL) assert ae(v.imag, -0.0034542480199350626699, tol=PTOL) v = fp.e1((8.0 + 2.0j)) assert ae(v, (-0.000022278049065270225945 - 0.000029191940456521555288j), tol=ATOL) assert ae(v.real, -0.000022278049065270225945, tol=PTOL) assert ae(v.imag, -0.000029191940456521555288, tol=PTOL) v = fp.e1((20.0 + 5.0j)) assert ae(v, (4.7711374515765346894e-11 + 8.2902652405126947359e-11j), tol=ATOL) assert ae(v.real, 4.7711374515765346894e-11, tol=PTOL) assert ae(v.imag, 8.2902652405126947359e-11, tol=PTOL) v = fp.e1((80.0 + 20.0j)) assert ae(v, (3.8353473865788235787e-38 - 2.129247592349605139e-37j), tol=ATOL) assert ae(v.real, 3.8353473865788235787e-38, tol=PTOL) assert ae(v.imag, -2.129247592349605139e-37, tol=PTOL) v = fp.e1((120.0 + 30.0j)) assert ae(v, (2.3836002337480334716e-55 + 5.6704043587126198306e-55j), tol=ATOL) assert ae(v.real, 2.3836002337480334716e-55, tol=PTOL) assert ae(v.imag, 5.6704043587126198306e-55, tol=PTOL) v = fp.e1((160.0 + 40.0j)) assert ae(v, (-1.6238022898654510661e-72 - 1.104172355572287367e-72j), tol=ATOL) assert ae(v.real, -1.6238022898654510661e-72, tol=PTOL) assert ae(v.imag, -1.104172355572287367e-72, tol=PTOL) v = fp.e1((200.0 + 50.0j)) assert ae(v, (6.6800061461666228487e-90 + 1.4473816083541016115e-91j), tol=ATOL) assert ae(v.real, 6.6800061461666228487e-90, tol=PTOL) assert ae(v.imag, 1.4473816083541016115e-91, tol=PTOL) v = fp.e1((320.0 + 80.0j)) assert ae(v, (4.2737871527778786157e-143 + 3.1789935525785660314e-142j), tol=ATOL) assert ae(v.real, 4.2737871527778786157e-143, tol=PTOL) assert ae(v.imag, 3.1789935525785660314e-142, tol=PTOL) v = fp.e1((1.1641532182693481445e-10 + 1.1641532182693481445e-10j)) assert ae(v, (21.950067703413105017 - 0.7853981632810329878j), tol=ATOL) assert ae(v.real, 21.950067703413105017, tol=PTOL) assert ae(v.imag, -0.7853981632810329878, tol=PTOL) v = fp.e1((0.25 + 0.25j)) assert ae(v, (0.71092525792923287894 - 0.56491812441304194711j), tol=ATOL) assert ae(v.real, 0.71092525792923287894, tol=PTOL) assert ae(v.imag, -0.56491812441304194711, tol=PTOL) v = fp.e1((1.0 + 1.0j)) assert ae(v, (0.00028162445198141832551 - 0.17932453503935894015j), tol=ATOL) assert ae(v.real, 0.00028162445198141832551, tol=PTOL) assert ae(v.imag, -0.17932453503935894015, tol=PTOL) v = fp.e1((2.0 + 2.0j)) assert ae(v, (-0.033767089606562004246 - 0.018599414169750541925j), tol=ATOL) assert ae(v.real, -0.033767089606562004246, tol=PTOL) assert ae(v.imag, -0.018599414169750541925, tol=PTOL) v = fp.e1((5.0 + 5.0j)) assert ae(v, (0.0007266506660356393891 + 0.00047102780163522245054j), tol=ATOL) assert ae(v.real, 0.0007266506660356393891, tol=PTOL) assert ae(v.imag, 0.00047102780163522245054, tol=PTOL) v = fp.e1((20.0 + 20.0j)) assert ae(v, (-2.3824537449367396579e-11 - 6.6969873156525615158e-11j), tol=ATOL) assert ae(v.real, -2.3824537449367396579e-11, tol=PTOL) assert ae(v.imag, -6.6969873156525615158e-11, tol=PTOL) v = fp.e1((30.0 + 30.0j)) assert ae(v, (1.7316045841744061617e-15 + 1.3065678019487308689e-15j), tol=ATOL) assert ae(v.real, 1.7316045841744061617e-15, tol=PTOL) assert ae(v.imag, 1.3065678019487308689e-15, tol=PTOL) v = fp.e1((40.0 + 40.0j)) assert ae(v, (-7.4001043002899232182e-20 - 4.991847855336816304e-21j), tol=ATOL) assert ae(v.real, -7.4001043002899232182e-20, tol=PTOL) assert ae(v.imag, -4.991847855336816304e-21, tol=PTOL) v = fp.e1((50.0 + 50.0j)) assert ae(v, (2.3566128324644641219e-24 - 1.3188326726201614778e-24j), tol=ATOL) assert ae(v.real, 2.3566128324644641219e-24, tol=PTOL) assert ae(v.imag, -1.3188326726201614778e-24, tol=PTOL) v = fp.e1((80.0 + 80.0j)) assert ae(v, (9.8279750572186526673e-38 + 1.243952841288868831e-37j), tol=ATOL) assert ae(v.real, 9.8279750572186526673e-38, tol=PTOL) assert ae(v.imag, 1.243952841288868831e-37, tol=PTOL) v = fp.e1((1.1641532182693481445e-10 + 4.6566128730773925781e-10j)) assert ae(v, (20.880034621664969632 - 1.3258176632023711778j), tol=ATOL) assert ae(v.real, 20.880034621664969632, tol=PTOL) assert ae(v.imag, -1.3258176632023711778, tol=PTOL) v = fp.e1((0.25 + 1.0j)) assert ae(v, (-0.16868306393667788761 - 0.4858011885947426971j), tol=ATOL) assert ae(v.real, -0.16868306393667788761, tol=PTOL) assert ae(v.imag, -0.4858011885947426971, tol=PTOL) v = fp.e1((1.0 + 4.0j)) assert ae(v, (0.03373591813926547318 + 0.073523452241083821877j), tol=ATOL) assert ae(v.real, 0.03373591813926547318, tol=PTOL) assert ae(v.imag, 0.073523452241083821877, tol=PTOL) v = fp.e1((2.0 + 8.0j)) assert ae(v, (-0.015392833434733785143 - 0.0031747121557605415914j), tol=ATOL) assert ae(v.real, -0.015392833434733785143, tol=PTOL) assert ae(v.imag, -0.0031747121557605415914, tol=PTOL) v = fp.e1((5.0 + 20.0j)) assert ae(v, (-0.00024419662286542966525 - 0.00021008322966152755674j), tol=ATOL) assert ae(v.real, -0.00024419662286542966525, tol=PTOL) assert ae(v.imag, -0.00021008322966152755674, tol=PTOL) v = fp.e1((20.0 + 80.0j)) assert ae(v, (2.3255552781051330088e-11 + 8.9463918891349438007e-12j), tol=ATOL) assert ae(v.real, 2.3255552781051330088e-11, tol=PTOL) assert ae(v.imag, 8.9463918891349438007e-12, tol=PTOL) v = fp.e1((30.0 + 120.0j)) assert ae(v, (-2.7068919097124652332e-16 - 7.0477762411705130239e-16j), tol=ATOL) assert ae(v.real, -2.7068919097124652332e-16, tol=PTOL) assert ae(v.imag, -7.0477762411705130239e-16, tol=PTOL) v = fp.e1((40.0 + 160.0j)) assert ae(v, (-1.1695597827678024687e-20 + 2.2907401455645736661e-20j), tol=ATOL) assert ae(v.real, -1.1695597827678024687e-20, tol=PTOL) assert ae(v.imag, 2.2907401455645736661e-20, tol=PTOL) v = fp.e1((50.0 + 200.0j)) assert ae(v, (9.0323746914410162531e-25 - 2.3950601790033530935e-25j), tol=ATOL) assert ae(v.real, 9.0323746914410162531e-25, tol=PTOL) assert ae(v.imag, -2.3950601790033530935e-25, tol=PTOL) v = fp.e1((80.0 + 320.0j)) assert ae(v, (3.4819106748728063576e-38 - 4.215653005615772724e-38j), tol=ATOL) assert ae(v.real, 3.4819106748728063576e-38, tol=PTOL) assert ae(v.imag, -4.215653005615772724e-38, tol=PTOL) v = fp.e1((0.0 + 1.1641532182693481445e-10j)) assert ae(v, (22.29664129357666235 - 1.5707963266784812974j), tol=ATOL) assert ae(v.real, 22.29664129357666235, tol=PTOL) assert ae(v.imag, -1.5707963266784812974, tol=PTOL) v = fp.e1((0.0 + 0.25j)) assert ae(v, (0.82466306258094565309 - 1.3216627564751394551j), tol=ATOL) assert ae(v.real, 0.82466306258094565309, tol=PTOL) assert ae(v.imag, -1.3216627564751394551, tol=PTOL) v = fp.e1((0.0 + 1.0j)) assert ae(v, (-0.33740392290096813466 - 0.62471325642771360429j), tol=ATOL) assert ae(v.real, -0.33740392290096813466, tol=PTOL) assert ae(v.imag, -0.62471325642771360429, tol=PTOL) v = fp.e1((0.0 + 2.0j)) assert ae(v, (-0.4229808287748649957 + 0.034616650007798229345j), tol=ATOL) assert ae(v.real, -0.4229808287748649957, tol=PTOL) assert ae(v.imag, 0.034616650007798229345, tol=PTOL) v = fp.e1((0.0 + 5.0j)) assert ae(v, (0.19002974965664387862 - 0.020865081850222481957j), tol=ATOL) assert ae(v.real, 0.19002974965664387862, tol=PTOL) assert ae(v.imag, -0.020865081850222481957, tol=PTOL) v = fp.e1((0.0 + 20.0j)) assert ae(v, (-0.04441982084535331654 - 0.022554625751456779068j), tol=ATOL) assert ae(v.real, -0.04441982084535331654, tol=PTOL) assert ae(v.imag, -0.022554625751456779068, tol=PTOL) v = fp.e1((0.0 + 30.0j)) assert ae(v, (0.033032417282071143779 - 0.0040397867645455082476j), tol=ATOL) assert ae(v.real, 0.033032417282071143779, tol=PTOL) assert ae(v.imag, -0.0040397867645455082476, tol=PTOL) v = fp.e1((0.0 + 40.0j)) assert ae(v, (-0.019020007896208766962 + 0.016188792559887887544j), tol=ATOL) assert ae(v.real, -0.019020007896208766962, tol=PTOL) assert ae(v.imag, 0.016188792559887887544, tol=PTOL) v = fp.e1((0.0 + 50.0j)) assert ae(v, (0.0056283863241163054402 - 0.019179254308960724503j), tol=ATOL) assert ae(v.real, 0.0056283863241163054402, tol=PTOL) assert ae(v.imag, -0.019179254308960724503, tol=PTOL) v = fp.e1((0.0 + 80.0j)) assert ae(v, (0.012402501155070958192 + 0.0015345601175906961199j), tol=ATOL) assert ae(v.real, 0.012402501155070958192, tol=PTOL) assert ae(v.imag, 0.0015345601175906961199, tol=PTOL) v = fp.e1((-1.1641532182693481445e-10 + 4.6566128730773925781e-10j)) assert ae(v, (20.880034621432138988 - 1.8157749894560994861j), tol=ATOL) assert ae(v.real, 20.880034621432138988, tol=PTOL) assert ae(v.imag, -1.8157749894560994861, tol=PTOL) v = fp.e1((-0.25 + 1.0j)) assert ae(v, (-0.59066621214766308594 - 0.74474454765205036972j), tol=ATOL) assert ae(v.real, -0.59066621214766308594, tol=PTOL) assert ae(v.imag, -0.74474454765205036972, tol=PTOL) v = fp.e1((-1.0 + 4.0j)) assert ae(v, (0.49739047283060471093 + 0.41543605404038863174j), tol=ATOL) assert ae(v.real, 0.49739047283060471093, tol=PTOL) assert ae(v.imag, 0.41543605404038863174, tol=PTOL) v = fp.e1((-2.0 + 8.0j)) assert ae(v, (-0.8705211147733730969 + 0.24099328498605539667j), tol=ATOL) assert ae(v.real, -0.8705211147733730969, tol=PTOL) assert ae(v.imag, 0.24099328498605539667, tol=PTOL) v = fp.e1((-5.0 + 20.0j)) assert ae(v, (-7.0789514293925893007 - 1.6102177171960790536j), tol=ATOL) assert ae(v.real, -7.0789514293925893007, tol=PTOL) assert ae(v.imag, -1.6102177171960790536, tol=PTOL) v = fp.e1((-20.0 + 80.0j)) assert ae(v, (5855431.4907298084434 - 720920.93315409165707j), tol=ATOL) assert ae(v.real, 5855431.4907298084434, tol=PTOL) assert ae(v.imag, -720920.93315409165707, tol=PTOL) v = fp.e1((-30.0 + 120.0j)) assert ae(v, (-65402491644.703470747 - 56697658399.657460294j), tol=ATOL) assert ae(v.real, -65402491644.703470747, tol=PTOL) assert ae(v.imag, -56697658399.657460294, tol=PTOL) v = fp.e1((-40.0 + 160.0j)) assert ae(v, (25504929379604.776769 + 1429035198630573.2463j), tol=ATOL) assert ae(v.real, 25504929379604.776769, tol=PTOL) assert ae(v.imag, 1429035198630573.2463, tol=PTOL) v = fp.e1((-50.0 + 200.0j)) assert ae(v, (18437746526988116954.0 - 17146362239046152345.0j), tol=ATOL) assert ae(v.real, 18437746526988116954.0, tol=PTOL) assert ae(v.imag, -17146362239046152345.0, tol=PTOL) v = fp.e1((-80.0 + 320.0j)) assert ae(v, (3.3464697299634526706e+31 - 1.6473152633843023919e+32j), tol=ATOL) assert ae(v.real, 3.3464697299634526706e+31, tol=PTOL) assert ae(v.imag, -1.6473152633843023919e+32, tol=PTOL) v = fp.e1((-4.6566128730773925781e-10 + 1.1641532182693481445e-10j)) assert ae(v, (20.880034621082893023 - 2.8966139903465137624j), tol=ATOL) assert ae(v.real, 20.880034621082893023, tol=PTOL) assert ae(v.imag, -2.8966139903465137624, tol=PTOL) v = fp.e1((-1.0 + 0.25j)) assert ae(v, (-1.8942716983721074932 - 2.4689102827070540799j), tol=ATOL) assert ae(v.real, -1.8942716983721074932, tol=PTOL) assert ae(v.imag, -2.4689102827070540799, tol=PTOL) v = fp.e1((-4.0 + 1.0j)) assert ae(v, (-14.806699492675420438 + 9.1384225230837893776j), tol=ATOL) assert ae(v.real, -14.806699492675420438, tol=PTOL) assert ae(v.imag, 9.1384225230837893776, tol=PTOL) v = fp.e1((-8.0 + 2.0j)) assert ae(v, (54.633252667426386294 + 413.20318163814670688j), tol=ATOL) assert ae(v.real, 54.633252667426386294, tol=PTOL) assert ae(v.imag, 413.20318163814670688, tol=PTOL) v = fp.e1((-20.0 + 5.0j)) assert ae(v, (-711836.97165402624643 - 24745250.939695900956j), tol=ATOL) assert ae(v.real, -711836.97165402624643, tol=PTOL) assert ae(v.imag, -24745250.939695900956, tol=PTOL) v = fp.e1((-80.0 + 20.0j)) assert ae(v, (-4.2139911108612653091e+32 + 5.3367124741918251637e+32j), tol=ATOL) assert ae(v.real, -4.2139911108612653091e+32, tol=PTOL) assert ae(v.imag, 5.3367124741918251637e+32, tol=PTOL) v = fp.e1((-120.0 + 30.0j)) assert ae(v, (9.7760616203707508892e+48 - 1.058257682317195792e+50j), tol=ATOL) assert ae(v.real, 9.7760616203707508892e+48, tol=PTOL) assert ae(v.imag, -1.058257682317195792e+50, tol=PTOL) v = fp.e1((-160.0 + 40.0j)) assert ae(v, (8.7065541466623638861e+66 + 1.6577106725141739889e+67j), tol=ATOL) assert ae(v.real, 8.7065541466623638861e+66, tol=PTOL) assert ae(v.imag, 1.6577106725141739889e+67, tol=PTOL) v = fp.e1((-200.0 + 50.0j)) assert ae(v, (-3.070744996327018106e+84 - 1.7243244846769415903e+84j), tol=ATOL) assert ae(v.real, -3.070744996327018106e+84, tol=PTOL) assert ae(v.imag, -1.7243244846769415903e+84, tol=PTOL) v = fp.e1((-320.0 + 80.0j)) assert ae(v, (9.9960598637998647276e+135 - 2.6855081527595608863e+136j), tol=ATOL) assert ae(v.real, 9.9960598637998647276e+135, tol=PTOL) assert ae(v.imag, -2.6855081527595608863e+136, tol=PTOL) v = fp.e1(-1.1641532182693481445e-10) assert ae(v, (22.296641293460247028 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 22.296641293460247028, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-0.25) assert ae(v, (0.54254326466191372953 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 0.54254326466191372953, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-1.0) assert ae(v, (-1.8951178163559367555 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -1.8951178163559367555, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-2.0) assert ae(v, (-4.9542343560018901634 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -4.9542343560018901634, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-5.0) assert ae(v, (-40.185275355803177455 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -40.185275355803177455, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-20.0) assert ae(v, (-25615652.66405658882 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -25615652.66405658882, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-30.0) assert ae(v, (-368973209407.27419706 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -368973209407.27419706, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-40.0) assert ae(v, (-6039718263611241.5784 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -6039718263611241.5784, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-50.0) assert ae(v, (-1.0585636897131690963e+20 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -1.0585636897131690963e+20, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1(-80.0) assert ae(v, (-7.0146000049047999696e+32 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -7.0146000049047999696e+32, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-1.1641532182693481445e-10 + 0.0j)) assert ae(v, (22.296641293460247028 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 22.296641293460247028, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-0.25 + 0.0j)) assert ae(v, (0.54254326466191372953 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 0.54254326466191372953, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-1.0 + 0.0j)) assert ae(v, (-1.8951178163559367555 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -1.8951178163559367555, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-2.0 + 0.0j)) assert ae(v, (-4.9542343560018901634 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -4.9542343560018901634, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-5.0 + 0.0j)) assert ae(v, (-40.185275355803177455 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -40.185275355803177455, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-20.0 + 0.0j)) assert ae(v, (-25615652.66405658882 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -25615652.66405658882, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-30.0 + 0.0j)) assert ae(v, (-368973209407.27419706 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -368973209407.27419706, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-40.0 + 0.0j)) assert ae(v, (-6039718263611241.5784 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -6039718263611241.5784, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-50.0 + 0.0j)) assert ae(v, (-1.0585636897131690963e+20 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -1.0585636897131690963e+20, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-80.0 + 0.0j)) assert ae(v, (-7.0146000049047999696e+32 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -7.0146000049047999696e+32, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.e1((-4.6566128730773925781e-10 - 1.1641532182693481445e-10j)) assert ae(v, (20.880034621082893023 + 2.8966139903465137624j), tol=ATOL) assert ae(v.real, 20.880034621082893023, tol=PTOL) assert ae(v.imag, 2.8966139903465137624, tol=PTOL) v = fp.e1((-1.0 - 0.25j)) assert ae(v, (-1.8942716983721074932 + 2.4689102827070540799j), tol=ATOL) assert ae(v.real, -1.8942716983721074932, tol=PTOL) assert ae(v.imag, 2.4689102827070540799, tol=PTOL) v = fp.e1((-4.0 - 1.0j)) assert ae(v, (-14.806699492675420438 - 9.1384225230837893776j), tol=ATOL) assert ae(v.real, -14.806699492675420438, tol=PTOL) assert ae(v.imag, -9.1384225230837893776, tol=PTOL) v = fp.e1((-8.0 - 2.0j)) assert ae(v, (54.633252667426386294 - 413.20318163814670688j), tol=ATOL) assert ae(v.real, 54.633252667426386294, tol=PTOL) assert ae(v.imag, -413.20318163814670688, tol=PTOL) v = fp.e1((-20.0 - 5.0j)) assert ae(v, (-711836.97165402624643 + 24745250.939695900956j), tol=ATOL) assert ae(v.real, -711836.97165402624643, tol=PTOL) assert ae(v.imag, 24745250.939695900956, tol=PTOL) v = fp.e1((-80.0 - 20.0j)) assert ae(v, (-4.2139911108612653091e+32 - 5.3367124741918251637e+32j), tol=ATOL) assert ae(v.real, -4.2139911108612653091e+32, tol=PTOL) assert ae(v.imag, -5.3367124741918251637e+32, tol=PTOL) v = fp.e1((-120.0 - 30.0j)) assert ae(v, (9.7760616203707508892e+48 + 1.058257682317195792e+50j), tol=ATOL) assert ae(v.real, 9.7760616203707508892e+48, tol=PTOL) assert ae(v.imag, 1.058257682317195792e+50, tol=PTOL) v = fp.e1((-160.0 - 40.0j)) assert ae(v, (8.7065541466623638861e+66 - 1.6577106725141739889e+67j), tol=ATOL) assert ae(v.real, 8.7065541466623638861e+66, tol=PTOL) assert ae(v.imag, -1.6577106725141739889e+67, tol=PTOL) v = fp.e1((-200.0 - 50.0j)) assert ae(v, (-3.070744996327018106e+84 + 1.7243244846769415903e+84j), tol=ATOL) assert ae(v.real, -3.070744996327018106e+84, tol=PTOL) assert ae(v.imag, 1.7243244846769415903e+84, tol=PTOL) v = fp.e1((-320.0 - 80.0j)) assert ae(v, (9.9960598637998647276e+135 + 2.6855081527595608863e+136j), tol=ATOL) assert ae(v.real, 9.9960598637998647276e+135, tol=PTOL) assert ae(v.imag, 2.6855081527595608863e+136, tol=PTOL) v = fp.e1((-1.1641532182693481445e-10 - 1.1641532182693481445e-10j)) assert ae(v, (21.950067703180274374 + 2.356194490075929607j), tol=ATOL) assert ae(v.real, 21.950067703180274374, tol=PTOL) assert ae(v.imag, 2.356194490075929607, tol=PTOL) v = fp.e1((-0.25 - 0.25j)) assert ae(v, (0.21441047326710323254 + 2.0732153554307936389j), tol=ATOL) assert ae(v.real, 0.21441047326710323254, tol=PTOL) assert ae(v.imag, 2.0732153554307936389, tol=PTOL) v = fp.e1((-1.0 - 1.0j)) assert ae(v, (-1.7646259855638540684 + 0.7538228020792708192j), tol=ATOL) assert ae(v.real, -1.7646259855638540684, tol=PTOL) assert ae(v.imag, 0.7538228020792708192, tol=PTOL) v = fp.e1((-2.0 - 2.0j)) assert ae(v, (-1.8920781621855474089 - 2.1753697842428647236j), tol=ATOL) assert ae(v.real, -1.8920781621855474089, tol=PTOL) assert ae(v.imag, -2.1753697842428647236, tol=PTOL) v = fp.e1((-5.0 - 5.0j)) assert ae(v, (13.470936071475245856 + 18.464085049321024206j), tol=ATOL) assert ae(v.real, 13.470936071475245856, tol=PTOL) assert ae(v.imag, 18.464085049321024206, tol=PTOL) v = fp.e1((-20.0 - 20.0j)) assert ae(v, (-16589317.398788971896 - 5831702.3296441771206j), tol=ATOL) assert ae(v.real, -16589317.398788971896, tol=PTOL) assert ae(v.imag, -5831702.3296441771206, tol=PTOL) v = fp.e1((-30.0 - 30.0j)) assert ae(v, (154596484273.69322527 + 204179357837.41389696j), tol=ATOL) assert ae(v.real, 154596484273.69322527, tol=PTOL) assert ae(v.imag, 204179357837.41389696, tol=PTOL) v = fp.e1((-40.0 - 40.0j)) assert ae(v, (-287512180321448.45408 - 4203502407932314.974j), tol=ATOL) assert ae(v.real, -287512180321448.45408, tol=PTOL) assert ae(v.imag, -4203502407932314.974, tol=PTOL) v = fp.e1((-50.0 - 50.0j)) assert ae(v, (-36128528616649268826.0 + 64648801861338741963.0j), tol=ATOL) assert ae(v.real, -36128528616649268826.0, tol=PTOL) assert ae(v.imag, 64648801861338741963.0, tol=PTOL) v = fp.e1((-80.0 - 80.0j)) assert ae(v, (3.8674816337930010217e+32 + 3.0540709639658071041e+32j), tol=ATOL) assert ae(v.real, 3.8674816337930010217e+32, tol=PTOL) assert ae(v.imag, 3.0540709639658071041e+32, tol=PTOL) v = fp.e1((-1.1641532182693481445e-10 - 4.6566128730773925781e-10j)) assert ae(v, (20.880034621432138988 + 1.8157749894560994861j), tol=ATOL) assert ae(v.real, 20.880034621432138988, tol=PTOL) assert ae(v.imag, 1.8157749894560994861, tol=PTOL) v = fp.e1((-0.25 - 1.0j)) assert ae(v, (-0.59066621214766308594 + 0.74474454765205036972j), tol=ATOL) assert ae(v.real, -0.59066621214766308594, tol=PTOL) assert ae(v.imag, 0.74474454765205036972, tol=PTOL) v = fp.e1((-1.0 - 4.0j)) assert ae(v, (0.49739047283060471093 - 0.41543605404038863174j), tol=ATOL) assert ae(v.real, 0.49739047283060471093, tol=PTOL) assert ae(v.imag, -0.41543605404038863174, tol=PTOL) v = fp.e1((-2.0 - 8.0j)) assert ae(v, (-0.8705211147733730969 - 0.24099328498605539667j), tol=ATOL) assert ae(v.real, -0.8705211147733730969, tol=PTOL) assert ae(v.imag, -0.24099328498605539667, tol=PTOL) v = fp.e1((-5.0 - 20.0j)) assert ae(v, (-7.0789514293925893007 + 1.6102177171960790536j), tol=ATOL) assert ae(v.real, -7.0789514293925893007, tol=PTOL) assert ae(v.imag, 1.6102177171960790536, tol=PTOL) v = fp.e1((-20.0 - 80.0j)) assert ae(v, (5855431.4907298084434 + 720920.93315409165707j), tol=ATOL) assert ae(v.real, 5855431.4907298084434, tol=PTOL) assert ae(v.imag, 720920.93315409165707, tol=PTOL) v = fp.e1((-30.0 - 120.0j)) assert ae(v, (-65402491644.703470747 + 56697658399.657460294j), tol=ATOL) assert ae(v.real, -65402491644.703470747, tol=PTOL) assert ae(v.imag, 56697658399.657460294, tol=PTOL) v = fp.e1((-40.0 - 160.0j)) assert ae(v, (25504929379604.776769 - 1429035198630573.2463j), tol=ATOL) assert ae(v.real, 25504929379604.776769, tol=PTOL) assert ae(v.imag, -1429035198630573.2463, tol=PTOL) v = fp.e1((-50.0 - 200.0j)) assert ae(v, (18437746526988116954.0 + 17146362239046152345.0j), tol=ATOL) assert ae(v.real, 18437746526988116954.0, tol=PTOL) assert ae(v.imag, 17146362239046152345.0, tol=PTOL) v = fp.e1((-80.0 - 320.0j)) assert ae(v, (3.3464697299634526706e+31 + 1.6473152633843023919e+32j), tol=ATOL) assert ae(v.real, 3.3464697299634526706e+31, tol=PTOL) assert ae(v.imag, 1.6473152633843023919e+32, tol=PTOL) v = fp.e1((0.0 - 1.1641532182693481445e-10j)) assert ae(v, (22.29664129357666235 + 1.5707963266784812974j), tol=ATOL) assert ae(v.real, 22.29664129357666235, tol=PTOL) assert ae(v.imag, 1.5707963266784812974, tol=PTOL) v = fp.e1((0.0 - 0.25j)) assert ae(v, (0.82466306258094565309 + 1.3216627564751394551j), tol=ATOL) assert ae(v.real, 0.82466306258094565309, tol=PTOL) assert ae(v.imag, 1.3216627564751394551, tol=PTOL) v = fp.e1((0.0 - 1.0j)) assert ae(v, (-0.33740392290096813466 + 0.62471325642771360429j), tol=ATOL) assert ae(v.real, -0.33740392290096813466, tol=PTOL) assert ae(v.imag, 0.62471325642771360429, tol=PTOL) v = fp.e1((0.0 - 2.0j)) assert ae(v, (-0.4229808287748649957 - 0.034616650007798229345j), tol=ATOL) assert ae(v.real, -0.4229808287748649957, tol=PTOL) assert ae(v.imag, -0.034616650007798229345, tol=PTOL) v = fp.e1((0.0 - 5.0j)) assert ae(v, (0.19002974965664387862 + 0.020865081850222481957j), tol=ATOL) assert ae(v.real, 0.19002974965664387862, tol=PTOL) assert ae(v.imag, 0.020865081850222481957, tol=PTOL) v = fp.e1((0.0 - 20.0j)) assert ae(v, (-0.04441982084535331654 + 0.022554625751456779068j), tol=ATOL) assert ae(v.real, -0.04441982084535331654, tol=PTOL) assert ae(v.imag, 0.022554625751456779068, tol=PTOL) v = fp.e1((0.0 - 30.0j)) assert ae(v, (0.033032417282071143779 + 0.0040397867645455082476j), tol=ATOL) assert ae(v.real, 0.033032417282071143779, tol=PTOL) assert ae(v.imag, 0.0040397867645455082476, tol=PTOL) v = fp.e1((0.0 - 40.0j)) assert ae(v, (-0.019020007896208766962 - 0.016188792559887887544j), tol=ATOL) assert ae(v.real, -0.019020007896208766962, tol=PTOL) assert ae(v.imag, -0.016188792559887887544, tol=PTOL) v = fp.e1((0.0 - 50.0j)) assert ae(v, (0.0056283863241163054402 + 0.019179254308960724503j), tol=ATOL) assert ae(v.real, 0.0056283863241163054402, tol=PTOL) assert ae(v.imag, 0.019179254308960724503, tol=PTOL) v = fp.e1((0.0 - 80.0j)) assert ae(v, (0.012402501155070958192 - 0.0015345601175906961199j), tol=ATOL) assert ae(v.real, 0.012402501155070958192, tol=PTOL) assert ae(v.imag, -0.0015345601175906961199, tol=PTOL) v = fp.e1((1.1641532182693481445e-10 - 4.6566128730773925781e-10j)) assert ae(v, (20.880034621664969632 + 1.3258176632023711778j), tol=ATOL) assert ae(v.real, 20.880034621664969632, tol=PTOL) assert ae(v.imag, 1.3258176632023711778, tol=PTOL) v = fp.e1((0.25 - 1.0j)) assert ae(v, (-0.16868306393667788761 + 0.4858011885947426971j), tol=ATOL) assert ae(v.real, -0.16868306393667788761, tol=PTOL) assert ae(v.imag, 0.4858011885947426971, tol=PTOL) v = fp.e1((1.0 - 4.0j)) assert ae(v, (0.03373591813926547318 - 0.073523452241083821877j), tol=ATOL) assert ae(v.real, 0.03373591813926547318, tol=PTOL) assert ae(v.imag, -0.073523452241083821877, tol=PTOL) v = fp.e1((2.0 - 8.0j)) assert ae(v, (-0.015392833434733785143 + 0.0031747121557605415914j), tol=ATOL) assert ae(v.real, -0.015392833434733785143, tol=PTOL) assert ae(v.imag, 0.0031747121557605415914, tol=PTOL) v = fp.e1((5.0 - 20.0j)) assert ae(v, (-0.00024419662286542966525 + 0.00021008322966152755674j), tol=ATOL) assert ae(v.real, -0.00024419662286542966525, tol=PTOL) assert ae(v.imag, 0.00021008322966152755674, tol=PTOL) v = fp.e1((20.0 - 80.0j)) assert ae(v, (2.3255552781051330088e-11 - 8.9463918891349438007e-12j), tol=ATOL) assert ae(v.real, 2.3255552781051330088e-11, tol=PTOL) assert ae(v.imag, -8.9463918891349438007e-12, tol=PTOL) v = fp.e1((30.0 - 120.0j)) assert ae(v, (-2.7068919097124652332e-16 + 7.0477762411705130239e-16j), tol=ATOL) assert ae(v.real, -2.7068919097124652332e-16, tol=PTOL) assert ae(v.imag, 7.0477762411705130239e-16, tol=PTOL) v = fp.e1((40.0 - 160.0j)) assert ae(v, (-1.1695597827678024687e-20 - 2.2907401455645736661e-20j), tol=ATOL) assert ae(v.real, -1.1695597827678024687e-20, tol=PTOL) assert ae(v.imag, -2.2907401455645736661e-20, tol=PTOL) v = fp.e1((50.0 - 200.0j)) assert ae(v, (9.0323746914410162531e-25 + 2.3950601790033530935e-25j), tol=ATOL) assert ae(v.real, 9.0323746914410162531e-25, tol=PTOL) assert ae(v.imag, 2.3950601790033530935e-25, tol=PTOL) v = fp.e1((80.0 - 320.0j)) assert ae(v, (3.4819106748728063576e-38 + 4.215653005615772724e-38j), tol=ATOL) assert ae(v.real, 3.4819106748728063576e-38, tol=PTOL) assert ae(v.imag, 4.215653005615772724e-38, tol=PTOL) v = fp.e1((1.1641532182693481445e-10 - 1.1641532182693481445e-10j)) assert ae(v, (21.950067703413105017 + 0.7853981632810329878j), tol=ATOL) assert ae(v.real, 21.950067703413105017, tol=PTOL) assert ae(v.imag, 0.7853981632810329878, tol=PTOL) v = fp.e1((0.25 - 0.25j)) assert ae(v, (0.71092525792923287894 + 0.56491812441304194711j), tol=ATOL) assert ae(v.real, 0.71092525792923287894, tol=PTOL) assert ae(v.imag, 0.56491812441304194711, tol=PTOL) v = fp.e1((1.0 - 1.0j)) assert ae(v, (0.00028162445198141832551 + 0.17932453503935894015j), tol=ATOL) assert ae(v.real, 0.00028162445198141832551, tol=PTOL) assert ae(v.imag, 0.17932453503935894015, tol=PTOL) v = fp.e1((2.0 - 2.0j)) assert ae(v, (-0.033767089606562004246 + 0.018599414169750541925j), tol=ATOL) assert ae(v.real, -0.033767089606562004246, tol=PTOL) assert ae(v.imag, 0.018599414169750541925, tol=PTOL) v = fp.e1((5.0 - 5.0j)) assert ae(v, (0.0007266506660356393891 - 0.00047102780163522245054j), tol=ATOL) assert ae(v.real, 0.0007266506660356393891, tol=PTOL) assert ae(v.imag, -0.00047102780163522245054, tol=PTOL) v = fp.e1((20.0 - 20.0j)) assert ae(v, (-2.3824537449367396579e-11 + 6.6969873156525615158e-11j), tol=ATOL) assert ae(v.real, -2.3824537449367396579e-11, tol=PTOL) assert ae(v.imag, 6.6969873156525615158e-11, tol=PTOL) v = fp.e1((30.0 - 30.0j)) assert ae(v, (1.7316045841744061617e-15 - 1.3065678019487308689e-15j), tol=ATOL) assert ae(v.real, 1.7316045841744061617e-15, tol=PTOL) assert ae(v.imag, -1.3065678019487308689e-15, tol=PTOL) v = fp.e1((40.0 - 40.0j)) assert ae(v, (-7.4001043002899232182e-20 + 4.991847855336816304e-21j), tol=ATOL) assert ae(v.real, -7.4001043002899232182e-20, tol=PTOL) assert ae(v.imag, 4.991847855336816304e-21, tol=PTOL) v = fp.e1((50.0 - 50.0j)) assert ae(v, (2.3566128324644641219e-24 + 1.3188326726201614778e-24j), tol=ATOL) assert ae(v.real, 2.3566128324644641219e-24, tol=PTOL) assert ae(v.imag, 1.3188326726201614778e-24, tol=PTOL) v = fp.e1((80.0 - 80.0j)) assert ae(v, (9.8279750572186526673e-38 - 1.243952841288868831e-37j), tol=ATOL) assert ae(v.real, 9.8279750572186526673e-38, tol=PTOL) assert ae(v.imag, -1.243952841288868831e-37, tol=PTOL) v = fp.e1((4.6566128730773925781e-10 - 1.1641532182693481445e-10j)) assert ae(v, (20.880034622014215597 + 0.24497866301044883237j), tol=ATOL) assert ae(v.real, 20.880034622014215597, tol=PTOL) assert ae(v.imag, 0.24497866301044883237, tol=PTOL) v = fp.e1((1.0 - 0.25j)) assert ae(v, (0.19731063945004229095 + 0.087366045774299963672j), tol=ATOL) assert ae(v.real, 0.19731063945004229095, tol=PTOL) assert ae(v.imag, 0.087366045774299963672, tol=PTOL) v = fp.e1((4.0 - 1.0j)) assert ae(v, (0.0013106173980145506944 + 0.0034542480199350626699j), tol=ATOL) assert ae(v.real, 0.0013106173980145506944, tol=PTOL) assert ae(v.imag, 0.0034542480199350626699, tol=PTOL) v = fp.e1((8.0 - 2.0j)) assert ae(v, (-0.000022278049065270225945 + 0.000029191940456521555288j), tol=ATOL) assert ae(v.real, -0.000022278049065270225945, tol=PTOL) assert ae(v.imag, 0.000029191940456521555288, tol=PTOL) v = fp.e1((20.0 - 5.0j)) assert ae(v, (4.7711374515765346894e-11 - 8.2902652405126947359e-11j), tol=ATOL) assert ae(v.real, 4.7711374515765346894e-11, tol=PTOL) assert ae(v.imag, -8.2902652405126947359e-11, tol=PTOL) v = fp.e1((80.0 - 20.0j)) assert ae(v, (3.8353473865788235787e-38 + 2.129247592349605139e-37j), tol=ATOL) assert ae(v.real, 3.8353473865788235787e-38, tol=PTOL) assert ae(v.imag, 2.129247592349605139e-37, tol=PTOL) v = fp.e1((120.0 - 30.0j)) assert ae(v, (2.3836002337480334716e-55 - 5.6704043587126198306e-55j), tol=ATOL) assert ae(v.real, 2.3836002337480334716e-55, tol=PTOL) assert ae(v.imag, -5.6704043587126198306e-55, tol=PTOL) v = fp.e1((160.0 - 40.0j)) assert ae(v, (-1.6238022898654510661e-72 + 1.104172355572287367e-72j), tol=ATOL) assert ae(v.real, -1.6238022898654510661e-72, tol=PTOL) assert ae(v.imag, 1.104172355572287367e-72, tol=PTOL) v = fp.e1((200.0 - 50.0j)) assert ae(v, (6.6800061461666228487e-90 - 1.4473816083541016115e-91j), tol=ATOL) assert ae(v.real, 6.6800061461666228487e-90, tol=PTOL) assert ae(v.imag, -1.4473816083541016115e-91, tol=PTOL) v = fp.e1((320.0 - 80.0j)) assert ae(v, (4.2737871527778786157e-143 - 3.1789935525785660314e-142j), tol=ATOL) assert ae(v.real, 4.2737871527778786157e-143, tol=PTOL) assert ae(v.imag, -3.1789935525785660314e-142, tol=PTOL) v = fp.ei(1.1641532182693481445e-10) assert ae(v, -22.296641293460247028, tol=ATOL) assert type(v) is float v = fp.ei(0.25) assert ae(v, -0.54254326466191372953, tol=ATOL) assert type(v) is float v = fp.ei(1.0) assert ae(v, 1.8951178163559367555, tol=ATOL) assert type(v) is float v = fp.ei(2.0) assert ae(v, 4.9542343560018901634, tol=ATOL) assert type(v) is float v = fp.ei(5.0) assert ae(v, 40.185275355803177455, tol=ATOL) assert type(v) is float v = fp.ei(20.0) assert ae(v, 25615652.66405658882, tol=ATOL) assert type(v) is float v = fp.ei(30.0) assert ae(v, 368973209407.27419706, tol=ATOL) assert type(v) is float v = fp.ei(40.0) assert ae(v, 6039718263611241.5784, tol=ATOL) assert type(v) is float v = fp.ei(50.0) assert ae(v, 1.0585636897131690963e+20, tol=ATOL) assert type(v) is float v = fp.ei(80.0) assert ae(v, 7.0146000049047999696e+32, tol=ATOL) assert type(v) is float v = fp.ei((1.1641532182693481445e-10 + 0.0j)) assert ae(v, (-22.296641293460247028 + 0.0j), tol=ATOL) assert ae(v.real, -22.296641293460247028, tol=PTOL) assert v.imag == 0 v = fp.ei((0.25 + 0.0j)) assert ae(v, (-0.54254326466191372953 + 0.0j), tol=ATOL) assert ae(v.real, -0.54254326466191372953, tol=PTOL) assert v.imag == 0 v = fp.ei((1.0 + 0.0j)) assert ae(v, (1.8951178163559367555 + 0.0j), tol=ATOL) assert ae(v.real, 1.8951178163559367555, tol=PTOL) assert v.imag == 0 v = fp.ei((2.0 + 0.0j)) assert ae(v, (4.9542343560018901634 + 0.0j), tol=ATOL) assert ae(v.real, 4.9542343560018901634, tol=PTOL) assert v.imag == 0 v = fp.ei((5.0 + 0.0j)) assert ae(v, (40.185275355803177455 + 0.0j), tol=ATOL) assert ae(v.real, 40.185275355803177455, tol=PTOL) assert v.imag == 0 v = fp.ei((20.0 + 0.0j)) assert ae(v, (25615652.66405658882 + 0.0j), tol=ATOL) assert ae(v.real, 25615652.66405658882, tol=PTOL) assert v.imag == 0 v = fp.ei((30.0 + 0.0j)) assert ae(v, (368973209407.27419706 + 0.0j), tol=ATOL) assert ae(v.real, 368973209407.27419706, tol=PTOL) assert v.imag == 0 v = fp.ei((40.0 + 0.0j)) assert ae(v, (6039718263611241.5784 + 0.0j), tol=ATOL) assert ae(v.real, 6039718263611241.5784, tol=PTOL) assert v.imag == 0 v = fp.ei((50.0 + 0.0j)) assert ae(v, (1.0585636897131690963e+20 + 0.0j), tol=ATOL) assert ae(v.real, 1.0585636897131690963e+20, tol=PTOL) assert v.imag == 0 v = fp.ei((80.0 + 0.0j)) assert ae(v, (7.0146000049047999696e+32 + 0.0j), tol=ATOL) assert ae(v.real, 7.0146000049047999696e+32, tol=PTOL) assert v.imag == 0 v = fp.ei((4.6566128730773925781e-10 + 1.1641532182693481445e-10j)) assert ae(v, (-20.880034621082893023 + 0.24497866324327947603j), tol=ATOL) assert ae(v.real, -20.880034621082893023, tol=PTOL) assert ae(v.imag, 0.24497866324327947603, tol=PTOL) v = fp.ei((1.0 + 0.25j)) assert ae(v, (1.8942716983721074932 + 0.67268237088273915854j), tol=ATOL) assert ae(v.real, 1.8942716983721074932, tol=PTOL) assert ae(v.imag, 0.67268237088273915854, tol=PTOL) v = fp.ei((4.0 + 1.0j)) assert ae(v, (14.806699492675420438 + 12.280015176673582616j), tol=ATOL) assert ae(v.real, 14.806699492675420438, tol=PTOL) assert ae(v.imag, 12.280015176673582616, tol=PTOL) v = fp.ei((8.0 + 2.0j)) assert ae(v, (-54.633252667426386294 + 416.34477429173650012j), tol=ATOL) assert ae(v.real, -54.633252667426386294, tol=PTOL) assert ae(v.imag, 416.34477429173650012, tol=PTOL) v = fp.ei((20.0 + 5.0j)) assert ae(v, (711836.97165402624643 - 24745247.798103247366j), tol=ATOL) assert ae(v.real, 711836.97165402624643, tol=PTOL) assert ae(v.imag, -24745247.798103247366, tol=PTOL) v = fp.ei((80.0 + 20.0j)) assert ae(v, (4.2139911108612653091e+32 + 5.3367124741918251637e+32j), tol=ATOL) assert ae(v.real, 4.2139911108612653091e+32, tol=PTOL) assert ae(v.imag, 5.3367124741918251637e+32, tol=PTOL) v = fp.ei((120.0 + 30.0j)) assert ae(v, (-9.7760616203707508892e+48 - 1.058257682317195792e+50j), tol=ATOL) assert ae(v.real, -9.7760616203707508892e+48, tol=PTOL) assert ae(v.imag, -1.058257682317195792e+50, tol=PTOL) v = fp.ei((160.0 + 40.0j)) assert ae(v, (-8.7065541466623638861e+66 + 1.6577106725141739889e+67j), tol=ATOL) assert ae(v.real, -8.7065541466623638861e+66, tol=PTOL) assert ae(v.imag, 1.6577106725141739889e+67, tol=PTOL) v = fp.ei((200.0 + 50.0j)) assert ae(v, (3.070744996327018106e+84 - 1.7243244846769415903e+84j), tol=ATOL) assert ae(v.real, 3.070744996327018106e+84, tol=PTOL) assert ae(v.imag, -1.7243244846769415903e+84, tol=PTOL) v = fp.ei((320.0 + 80.0j)) assert ae(v, (-9.9960598637998647276e+135 - 2.6855081527595608863e+136j), tol=ATOL) assert ae(v.real, -9.9960598637998647276e+135, tol=PTOL) assert ae(v.imag, -2.6855081527595608863e+136, tol=PTOL) v = fp.ei((1.1641532182693481445e-10 + 1.1641532182693481445e-10j)) assert ae(v, (-21.950067703180274374 + 0.78539816351386363145j), tol=ATOL) assert ae(v.real, -21.950067703180274374, tol=PTOL) assert ae(v.imag, 0.78539816351386363145, tol=PTOL) v = fp.ei((0.25 + 0.25j)) assert ae(v, (-0.21441047326710323254 + 1.0683772981589995996j), tol=ATOL) assert ae(v.real, -0.21441047326710323254, tol=PTOL) assert ae(v.imag, 1.0683772981589995996, tol=PTOL) v = fp.ei((1.0 + 1.0j)) assert ae(v, (1.7646259855638540684 + 2.3877698515105224193j), tol=ATOL) assert ae(v.real, 1.7646259855638540684, tol=PTOL) assert ae(v.imag, 2.3877698515105224193, tol=PTOL) v = fp.ei((2.0 + 2.0j)) assert ae(v, (1.8920781621855474089 + 5.3169624378326579621j), tol=ATOL) assert ae(v.real, 1.8920781621855474089, tol=PTOL) assert ae(v.imag, 5.3169624378326579621, tol=PTOL) v = fp.ei((5.0 + 5.0j)) assert ae(v, (-13.470936071475245856 - 15.322492395731230968j), tol=ATOL) assert ae(v.real, -13.470936071475245856, tol=PTOL) assert ae(v.imag, -15.322492395731230968, tol=PTOL) v = fp.ei((20.0 + 20.0j)) assert ae(v, (16589317.398788971896 + 5831705.4712368307104j), tol=ATOL) assert ae(v.real, 16589317.398788971896, tol=PTOL) assert ae(v.imag, 5831705.4712368307104, tol=PTOL) v = fp.ei((30.0 + 30.0j)) assert ae(v, (-154596484273.69322527 - 204179357834.2723043j), tol=ATOL) assert ae(v.real, -154596484273.69322527, tol=PTOL) assert ae(v.imag, -204179357834.2723043, tol=PTOL) v = fp.ei((40.0 + 40.0j)) assert ae(v, (287512180321448.45408 + 4203502407932318.1156j), tol=ATOL) assert ae(v.real, 287512180321448.45408, tol=PTOL) assert ae(v.imag, 4203502407932318.1156, tol=PTOL) v = fp.ei((50.0 + 50.0j)) assert ae(v, (36128528616649268826.0 - 64648801861338741960.0j), tol=ATOL) assert ae(v.real, 36128528616649268826.0, tol=PTOL) assert ae(v.imag, -64648801861338741960.0, tol=PTOL) v = fp.ei((80.0 + 80.0j)) assert ae(v, (-3.8674816337930010217e+32 - 3.0540709639658071041e+32j), tol=ATOL) assert ae(v.real, -3.8674816337930010217e+32, tol=PTOL) assert ae(v.imag, -3.0540709639658071041e+32, tol=PTOL) v = fp.ei((1.1641532182693481445e-10 + 4.6566128730773925781e-10j)) assert ae(v, (-20.880034621432138988 + 1.3258176641336937524j), tol=ATOL) assert ae(v.real, -20.880034621432138988, tol=PTOL) assert ae(v.imag, 1.3258176641336937524, tol=PTOL) v = fp.ei((0.25 + 1.0j)) assert ae(v, (0.59066621214766308594 + 2.3968481059377428687j), tol=ATOL) assert ae(v.real, 0.59066621214766308594, tol=PTOL) assert ae(v.imag, 2.3968481059377428687, tol=PTOL) v = fp.ei((1.0 + 4.0j)) assert ae(v, (-0.49739047283060471093 + 3.5570287076301818702j), tol=ATOL) assert ae(v.real, -0.49739047283060471093, tol=PTOL) assert ae(v.imag, 3.5570287076301818702, tol=PTOL) v = fp.ei((2.0 + 8.0j)) assert ae(v, (0.8705211147733730969 + 3.3825859385758486351j), tol=ATOL) assert ae(v.real, 0.8705211147733730969, tol=PTOL) assert ae(v.imag, 3.3825859385758486351, tol=PTOL) v = fp.ei((5.0 + 20.0j)) assert ae(v, (7.0789514293925893007 + 1.5313749363937141849j), tol=ATOL) assert ae(v.real, 7.0789514293925893007, tol=PTOL) assert ae(v.imag, 1.5313749363937141849, tol=PTOL) v = fp.ei((20.0 + 80.0j)) assert ae(v, (-5855431.4907298084434 - 720917.79156143806727j), tol=ATOL) assert ae(v.real, -5855431.4907298084434, tol=PTOL) assert ae(v.imag, -720917.79156143806727, tol=PTOL) v = fp.ei((30.0 + 120.0j)) assert ae(v, (65402491644.703470747 - 56697658396.51586764j), tol=ATOL) assert ae(v.real, 65402491644.703470747, tol=PTOL) assert ae(v.imag, -56697658396.51586764, tol=PTOL) v = fp.ei((40.0 + 160.0j)) assert ae(v, (-25504929379604.776769 + 1429035198630576.3879j), tol=ATOL) assert ae(v.real, -25504929379604.776769, tol=PTOL) assert ae(v.imag, 1429035198630576.3879, tol=PTOL) v = fp.ei((50.0 + 200.0j)) assert ae(v, (-18437746526988116954.0 - 17146362239046152342.0j), tol=ATOL) assert ae(v.real, -18437746526988116954.0, tol=PTOL) assert ae(v.imag, -17146362239046152342.0, tol=PTOL) v = fp.ei((80.0 + 320.0j)) assert ae(v, (-3.3464697299634526706e+31 - 1.6473152633843023919e+32j), tol=ATOL) assert ae(v.real, -3.3464697299634526706e+31, tol=PTOL) assert ae(v.imag, -1.6473152633843023919e+32, tol=PTOL) v = fp.ei((0.0 + 1.1641532182693481445e-10j)) assert ae(v, (-22.29664129357666235 + 1.5707963269113119411j), tol=ATOL) assert ae(v.real, -22.29664129357666235, tol=PTOL) assert ae(v.imag, 1.5707963269113119411, tol=PTOL) v = fp.ei((0.0 + 0.25j)) assert ae(v, (-0.82466306258094565309 + 1.8199298971146537833j), tol=ATOL) assert ae(v.real, -0.82466306258094565309, tol=PTOL) assert ae(v.imag, 1.8199298971146537833, tol=PTOL) v = fp.ei((0.0 + 1.0j)) assert ae(v, (0.33740392290096813466 + 2.5168793971620796342j), tol=ATOL) assert ae(v.real, 0.33740392290096813466, tol=PTOL) assert ae(v.imag, 2.5168793971620796342, tol=PTOL) v = fp.ei((0.0 + 2.0j)) assert ae(v, (0.4229808287748649957 + 3.1762093035975914678j), tol=ATOL) assert ae(v.real, 0.4229808287748649957, tol=PTOL) assert ae(v.imag, 3.1762093035975914678, tol=PTOL) v = fp.ei((0.0 + 5.0j)) assert ae(v, (-0.19002974965664387862 + 3.1207275717395707565j), tol=ATOL) assert ae(v.real, -0.19002974965664387862, tol=PTOL) assert ae(v.imag, 3.1207275717395707565, tol=PTOL) v = fp.ei((0.0 + 20.0j)) assert ae(v, (0.04441982084535331654 + 3.1190380278383364594j), tol=ATOL) assert ae(v.real, 0.04441982084535331654, tol=PTOL) assert ae(v.imag, 3.1190380278383364594, tol=PTOL) v = fp.ei((0.0 + 30.0j)) assert ae(v, (-0.033032417282071143779 + 3.1375528668252477302j), tol=ATOL) assert ae(v.real, -0.033032417282071143779, tol=PTOL) assert ae(v.imag, 3.1375528668252477302, tol=PTOL) v = fp.ei((0.0 + 40.0j)) assert ae(v, (0.019020007896208766962 + 3.157781446149681126j), tol=ATOL) assert ae(v.real, 0.019020007896208766962, tol=PTOL) assert ae(v.imag, 3.157781446149681126, tol=PTOL) v = fp.ei((0.0 + 50.0j)) assert ae(v, (-0.0056283863241163054402 + 3.122413399280832514j), tol=ATOL) assert ae(v.real, -0.0056283863241163054402, tol=PTOL) assert ae(v.imag, 3.122413399280832514, tol=PTOL) v = fp.ei((0.0 + 80.0j)) assert ae(v, (-0.012402501155070958192 + 3.1431272137073839346j), tol=ATOL) assert ae(v.real, -0.012402501155070958192, tol=PTOL) assert ae(v.imag, 3.1431272137073839346, tol=PTOL) v = fp.ei((-1.1641532182693481445e-10 + 4.6566128730773925781e-10j)) assert ae(v, (-20.880034621664969632 + 1.8157749903874220607j), tol=ATOL) assert ae(v.real, -20.880034621664969632, tol=PTOL) assert ae(v.imag, 1.8157749903874220607, tol=PTOL) v = fp.ei((-0.25 + 1.0j)) assert ae(v, (0.16868306393667788761 + 2.6557914649950505414j), tol=ATOL) assert ae(v.real, 0.16868306393667788761, tol=PTOL) assert ae(v.imag, 2.6557914649950505414, tol=PTOL) v = fp.ei((-1.0 + 4.0j)) assert ae(v, (-0.03373591813926547318 + 3.2151161058308770603j), tol=ATOL) assert ae(v.real, -0.03373591813926547318, tol=PTOL) assert ae(v.imag, 3.2151161058308770603, tol=PTOL) v = fp.ei((-2.0 + 8.0j)) assert ae(v, (0.015392833434733785143 + 3.1384179414340326969j), tol=ATOL) assert ae(v.real, 0.015392833434733785143, tol=PTOL) assert ae(v.imag, 3.1384179414340326969, tol=PTOL) v = fp.ei((-5.0 + 20.0j)) assert ae(v, (0.00024419662286542966525 + 3.1413825703601317109j), tol=ATOL) assert ae(v.real, 0.00024419662286542966525, tol=PTOL) assert ae(v.imag, 3.1413825703601317109, tol=PTOL) v = fp.ei((-20.0 + 80.0j)) assert ae(v, (-2.3255552781051330088e-11 + 3.1415926535987396304j), tol=ATOL) assert ae(v.real, -2.3255552781051330088e-11, tol=PTOL) assert ae(v.imag, 3.1415926535987396304, tol=PTOL) v = fp.ei((-30.0 + 120.0j)) assert ae(v, (2.7068919097124652332e-16 + 3.1415926535897925337j), tol=ATOL) assert ae(v.real, 2.7068919097124652332e-16, tol=PTOL) assert ae(v.imag, 3.1415926535897925337, tol=PTOL) v = fp.ei((-40.0 + 160.0j)) assert ae(v, (1.1695597827678024687e-20 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 1.1695597827678024687e-20, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-50.0 + 200.0j)) assert ae(v, (-9.0323746914410162531e-25 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -9.0323746914410162531e-25, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-80.0 + 320.0j)) assert ae(v, (-3.4819106748728063576e-38 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -3.4819106748728063576e-38, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-4.6566128730773925781e-10 + 1.1641532182693481445e-10j)) assert ae(v, (-20.880034622014215597 + 2.8966139905793444061j), tol=ATOL) assert ae(v.real, -20.880034622014215597, tol=PTOL) assert ae(v.imag, 2.8966139905793444061, tol=PTOL) v = fp.ei((-1.0 + 0.25j)) assert ae(v, (-0.19731063945004229095 + 3.0542266078154932748j), tol=ATOL) assert ae(v.real, -0.19731063945004229095, tol=PTOL) assert ae(v.imag, 3.0542266078154932748, tol=PTOL) v = fp.ei((-4.0 + 1.0j)) assert ae(v, (-0.0013106173980145506944 + 3.1381384055698581758j), tol=ATOL) assert ae(v.real, -0.0013106173980145506944, tol=PTOL) assert ae(v.imag, 3.1381384055698581758, tol=PTOL) v = fp.ei((-8.0 + 2.0j)) assert ae(v, (0.000022278049065270225945 + 3.1415634616493367169j), tol=ATOL) assert ae(v.real, 0.000022278049065270225945, tol=PTOL) assert ae(v.imag, 3.1415634616493367169, tol=PTOL) v = fp.ei((-20.0 + 5.0j)) assert ae(v, (-4.7711374515765346894e-11 + 3.1415926536726958909j), tol=ATOL) assert ae(v.real, -4.7711374515765346894e-11, tol=PTOL) assert ae(v.imag, 3.1415926536726958909, tol=PTOL) v = fp.ei((-80.0 + 20.0j)) assert ae(v, (-3.8353473865788235787e-38 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -3.8353473865788235787e-38, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-120.0 + 30.0j)) assert ae(v, (-2.3836002337480334716e-55 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -2.3836002337480334716e-55, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-160.0 + 40.0j)) assert ae(v, (1.6238022898654510661e-72 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 1.6238022898654510661e-72, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-200.0 + 50.0j)) assert ae(v, (-6.6800061461666228487e-90 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -6.6800061461666228487e-90, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei((-320.0 + 80.0j)) assert ae(v, (-4.2737871527778786157e-143 + 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -4.2737871527778786157e-143, tol=PTOL) assert ae(v.imag, 3.1415926535897932385, tol=PTOL) v = fp.ei(-1.1641532182693481445e-10) assert ae(v, -22.296641293693077672, tol=ATOL) assert type(v) is float v = fp.ei(-0.25) assert ae(v, -1.0442826344437381945, tol=ATOL) assert type(v) is float v = fp.ei(-1.0) assert ae(v, -0.21938393439552027368, tol=ATOL) assert type(v) is float v = fp.ei(-2.0) assert ae(v, -0.048900510708061119567, tol=ATOL) assert type(v) is float v = fp.ei(-5.0) assert ae(v, -0.0011482955912753257973, tol=ATOL) assert type(v) is float v = fp.ei(-20.0) assert ae(v, -9.8355252906498816904e-11, tol=ATOL) assert type(v) is float v = fp.ei(-30.0) assert ae(v, -3.0215520106888125448e-15, tol=ATOL) assert type(v) is float v = fp.ei(-40.0) assert ae(v, -1.0367732614516569722e-19, tol=ATOL) assert type(v) is float v = fp.ei(-50.0) assert ae(v, -3.7832640295504590187e-24, tol=ATOL) assert type(v) is float v = fp.ei(-80.0) assert ae(v, -2.2285432586884729112e-37, tol=ATOL) assert type(v) is float v = fp.ei((-1.1641532182693481445e-10 + 0.0j)) assert ae(v, (-22.296641293693077672 + 0.0j), tol=ATOL) assert ae(v.real, -22.296641293693077672, tol=PTOL) assert v.imag == 0 v = fp.ei((-0.25 + 0.0j)) assert ae(v, (-1.0442826344437381945 + 0.0j), tol=ATOL) assert ae(v.real, -1.0442826344437381945, tol=PTOL) assert v.imag == 0 v = fp.ei((-1.0 + 0.0j)) assert ae(v, (-0.21938393439552027368 + 0.0j), tol=ATOL) assert ae(v.real, -0.21938393439552027368, tol=PTOL) assert v.imag == 0 v = fp.ei((-2.0 + 0.0j)) assert ae(v, (-0.048900510708061119567 + 0.0j), tol=ATOL) assert ae(v.real, -0.048900510708061119567, tol=PTOL) assert v.imag == 0 v = fp.ei((-5.0 + 0.0j)) assert ae(v, (-0.0011482955912753257973 + 0.0j), tol=ATOL) assert ae(v.real, -0.0011482955912753257973, tol=PTOL) assert v.imag == 0 v = fp.ei((-20.0 + 0.0j)) assert ae(v, (-9.8355252906498816904e-11 + 0.0j), tol=ATOL) assert ae(v.real, -9.8355252906498816904e-11, tol=PTOL) assert v.imag == 0 v = fp.ei((-30.0 + 0.0j)) assert ae(v, (-3.0215520106888125448e-15 + 0.0j), tol=ATOL) assert ae(v.real, -3.0215520106888125448e-15, tol=PTOL) assert v.imag == 0 v = fp.ei((-40.0 + 0.0j)) assert ae(v, (-1.0367732614516569722e-19 + 0.0j), tol=ATOL) assert ae(v.real, -1.0367732614516569722e-19, tol=PTOL) assert v.imag == 0 v = fp.ei((-50.0 + 0.0j)) assert ae(v, (-3.7832640295504590187e-24 + 0.0j), tol=ATOL) assert ae(v.real, -3.7832640295504590187e-24, tol=PTOL) assert v.imag == 0 v = fp.ei((-80.0 + 0.0j)) assert ae(v, (-2.2285432586884729112e-37 + 0.0j), tol=ATOL) assert ae(v.real, -2.2285432586884729112e-37, tol=PTOL) assert v.imag == 0 v = fp.ei((-4.6566128730773925781e-10 - 1.1641532182693481445e-10j)) assert ae(v, (-20.880034622014215597 - 2.8966139905793444061j), tol=ATOL) assert ae(v.real, -20.880034622014215597, tol=PTOL) assert ae(v.imag, -2.8966139905793444061, tol=PTOL) v = fp.ei((-1.0 - 0.25j)) assert ae(v, (-0.19731063945004229095 - 3.0542266078154932748j), tol=ATOL) assert ae(v.real, -0.19731063945004229095, tol=PTOL) assert ae(v.imag, -3.0542266078154932748, tol=PTOL) v = fp.ei((-4.0 - 1.0j)) assert ae(v, (-0.0013106173980145506944 - 3.1381384055698581758j), tol=ATOL) assert ae(v.real, -0.0013106173980145506944, tol=PTOL) assert ae(v.imag, -3.1381384055698581758, tol=PTOL) v = fp.ei((-8.0 - 2.0j)) assert ae(v, (0.000022278049065270225945 - 3.1415634616493367169j), tol=ATOL) assert ae(v.real, 0.000022278049065270225945, tol=PTOL) assert ae(v.imag, -3.1415634616493367169, tol=PTOL) v = fp.ei((-20.0 - 5.0j)) assert ae(v, (-4.7711374515765346894e-11 - 3.1415926536726958909j), tol=ATOL) assert ae(v.real, -4.7711374515765346894e-11, tol=PTOL) assert ae(v.imag, -3.1415926536726958909, tol=PTOL) v = fp.ei((-80.0 - 20.0j)) assert ae(v, (-3.8353473865788235787e-38 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -3.8353473865788235787e-38, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-120.0 - 30.0j)) assert ae(v, (-2.3836002337480334716e-55 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -2.3836002337480334716e-55, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-160.0 - 40.0j)) assert ae(v, (1.6238022898654510661e-72 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 1.6238022898654510661e-72, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-200.0 - 50.0j)) assert ae(v, (-6.6800061461666228487e-90 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -6.6800061461666228487e-90, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-320.0 - 80.0j)) assert ae(v, (-4.2737871527778786157e-143 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -4.2737871527778786157e-143, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-1.1641532182693481445e-10 - 1.1641532182693481445e-10j)) assert ae(v, (-21.950067703413105017 - 2.3561944903087602507j), tol=ATOL) assert ae(v.real, -21.950067703413105017, tol=PTOL) assert ae(v.imag, -2.3561944903087602507, tol=PTOL) v = fp.ei((-0.25 - 0.25j)) assert ae(v, (-0.71092525792923287894 - 2.5766745291767512913j), tol=ATOL) assert ae(v.real, -0.71092525792923287894, tol=PTOL) assert ae(v.imag, -2.5766745291767512913, tol=PTOL) v = fp.ei((-1.0 - 1.0j)) assert ae(v, (-0.00028162445198141832551 - 2.9622681185504342983j), tol=ATOL) assert ae(v.real, -0.00028162445198141832551, tol=PTOL) assert ae(v.imag, -2.9622681185504342983, tol=PTOL) v = fp.ei((-2.0 - 2.0j)) assert ae(v, (0.033767089606562004246 - 3.1229932394200426965j), tol=ATOL) assert ae(v.real, 0.033767089606562004246, tol=PTOL) assert ae(v.imag, -3.1229932394200426965, tol=PTOL) v = fp.ei((-5.0 - 5.0j)) assert ae(v, (-0.0007266506660356393891 - 3.1420636813914284609j), tol=ATOL) assert ae(v.real, -0.0007266506660356393891, tol=PTOL) assert ae(v.imag, -3.1420636813914284609, tol=PTOL) v = fp.ei((-20.0 - 20.0j)) assert ae(v, (2.3824537449367396579e-11 - 3.1415926535228233653j), tol=ATOL) assert ae(v.real, 2.3824537449367396579e-11, tol=PTOL) assert ae(v.imag, -3.1415926535228233653, tol=PTOL) v = fp.ei((-30.0 - 30.0j)) assert ae(v, (-1.7316045841744061617e-15 - 3.141592653589794545j), tol=ATOL) assert ae(v.real, -1.7316045841744061617e-15, tol=PTOL) assert ae(v.imag, -3.141592653589794545, tol=PTOL) v = fp.ei((-40.0 - 40.0j)) assert ae(v, (7.4001043002899232182e-20 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 7.4001043002899232182e-20, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-50.0 - 50.0j)) assert ae(v, (-2.3566128324644641219e-24 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -2.3566128324644641219e-24, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-80.0 - 80.0j)) assert ae(v, (-9.8279750572186526673e-38 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -9.8279750572186526673e-38, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-1.1641532182693481445e-10 - 4.6566128730773925781e-10j)) assert ae(v, (-20.880034621664969632 - 1.8157749903874220607j), tol=ATOL) assert ae(v.real, -20.880034621664969632, tol=PTOL) assert ae(v.imag, -1.8157749903874220607, tol=PTOL) v = fp.ei((-0.25 - 1.0j)) assert ae(v, (0.16868306393667788761 - 2.6557914649950505414j), tol=ATOL) assert ae(v.real, 0.16868306393667788761, tol=PTOL) assert ae(v.imag, -2.6557914649950505414, tol=PTOL) v = fp.ei((-1.0 - 4.0j)) assert ae(v, (-0.03373591813926547318 - 3.2151161058308770603j), tol=ATOL) assert ae(v.real, -0.03373591813926547318, tol=PTOL) assert ae(v.imag, -3.2151161058308770603, tol=PTOL) v = fp.ei((-2.0 - 8.0j)) assert ae(v, (0.015392833434733785143 - 3.1384179414340326969j), tol=ATOL) assert ae(v.real, 0.015392833434733785143, tol=PTOL) assert ae(v.imag, -3.1384179414340326969, tol=PTOL) v = fp.ei((-5.0 - 20.0j)) assert ae(v, (0.00024419662286542966525 - 3.1413825703601317109j), tol=ATOL) assert ae(v.real, 0.00024419662286542966525, tol=PTOL) assert ae(v.imag, -3.1413825703601317109, tol=PTOL) v = fp.ei((-20.0 - 80.0j)) assert ae(v, (-2.3255552781051330088e-11 - 3.1415926535987396304j), tol=ATOL) assert ae(v.real, -2.3255552781051330088e-11, tol=PTOL) assert ae(v.imag, -3.1415926535987396304, tol=PTOL) v = fp.ei((-30.0 - 120.0j)) assert ae(v, (2.7068919097124652332e-16 - 3.1415926535897925337j), tol=ATOL) assert ae(v.real, 2.7068919097124652332e-16, tol=PTOL) assert ae(v.imag, -3.1415926535897925337, tol=PTOL) v = fp.ei((-40.0 - 160.0j)) assert ae(v, (1.1695597827678024687e-20 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, 1.1695597827678024687e-20, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-50.0 - 200.0j)) assert ae(v, (-9.0323746914410162531e-25 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -9.0323746914410162531e-25, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((-80.0 - 320.0j)) assert ae(v, (-3.4819106748728063576e-38 - 3.1415926535897932385j), tol=ATOL) assert ae(v.real, -3.4819106748728063576e-38, tol=PTOL) assert ae(v.imag, -3.1415926535897932385, tol=PTOL) v = fp.ei((0.0 - 1.1641532182693481445e-10j)) assert ae(v, (-22.29664129357666235 - 1.5707963269113119411j), tol=ATOL) assert ae(v.real, -22.29664129357666235, tol=PTOL) assert ae(v.imag, -1.5707963269113119411, tol=PTOL) v = fp.ei((0.0 - 0.25j)) assert ae(v, (-0.82466306258094565309 - 1.8199298971146537833j), tol=ATOL) assert ae(v.real, -0.82466306258094565309, tol=PTOL) assert ae(v.imag, -1.8199298971146537833, tol=PTOL) v = fp.ei((0.0 - 1.0j)) assert ae(v, (0.33740392290096813466 - 2.5168793971620796342j), tol=ATOL) assert ae(v.real, 0.33740392290096813466, tol=PTOL) assert ae(v.imag, -2.5168793971620796342, tol=PTOL) v = fp.ei((0.0 - 2.0j)) assert ae(v, (0.4229808287748649957 - 3.1762093035975914678j), tol=ATOL) assert ae(v.real, 0.4229808287748649957, tol=PTOL) assert ae(v.imag, -3.1762093035975914678, tol=PTOL) v = fp.ei((0.0 - 5.0j)) assert ae(v, (-0.19002974965664387862 - 3.1207275717395707565j), tol=ATOL) assert ae(v.real, -0.19002974965664387862, tol=PTOL) assert ae(v.imag, -3.1207275717395707565, tol=PTOL) v = fp.ei((0.0 - 20.0j)) assert ae(v, (0.04441982084535331654 - 3.1190380278383364594j), tol=ATOL) assert ae(v.real, 0.04441982084535331654, tol=PTOL) assert ae(v.imag, -3.1190380278383364594, tol=PTOL) v = fp.ei((0.0 - 30.0j)) assert ae(v, (-0.033032417282071143779 - 3.1375528668252477302j), tol=ATOL) assert ae(v.real, -0.033032417282071143779, tol=PTOL) assert ae(v.imag, -3.1375528668252477302, tol=PTOL) v = fp.ei((0.0 - 40.0j)) assert ae(v, (0.019020007896208766962 - 3.157781446149681126j), tol=ATOL) assert ae(v.real, 0.019020007896208766962, tol=PTOL) assert ae(v.imag, -3.157781446149681126, tol=PTOL) v = fp.ei((0.0 - 50.0j)) assert ae(v, (-0.0056283863241163054402 - 3.122413399280832514j), tol=ATOL) assert ae(v.real, -0.0056283863241163054402, tol=PTOL) assert ae(v.imag, -3.122413399280832514, tol=PTOL) v = fp.ei((0.0 - 80.0j)) assert ae(v, (-0.012402501155070958192 - 3.1431272137073839346j), tol=ATOL) assert ae(v.real, -0.012402501155070958192, tol=PTOL) assert ae(v.imag, -3.1431272137073839346, tol=PTOL) v = fp.ei((1.1641532182693481445e-10 - 4.6566128730773925781e-10j)) assert ae(v, (-20.880034621432138988 - 1.3258176641336937524j), tol=ATOL) assert ae(v.real, -20.880034621432138988, tol=PTOL) assert ae(v.imag, -1.3258176641336937524, tol=PTOL) v = fp.ei((0.25 - 1.0j)) assert ae(v, (0.59066621214766308594 - 2.3968481059377428687j), tol=ATOL) assert ae(v.real, 0.59066621214766308594, tol=PTOL) assert ae(v.imag, -2.3968481059377428687, tol=PTOL) v = fp.ei((1.0 - 4.0j)) assert ae(v, (-0.49739047283060471093 - 3.5570287076301818702j), tol=ATOL) assert ae(v.real, -0.49739047283060471093, tol=PTOL) assert ae(v.imag, -3.5570287076301818702, tol=PTOL) v = fp.ei((2.0 - 8.0j)) assert ae(v, (0.8705211147733730969 - 3.3825859385758486351j), tol=ATOL) assert ae(v.real, 0.8705211147733730969, tol=PTOL) assert ae(v.imag, -3.3825859385758486351, tol=PTOL) v = fp.ei((5.0 - 20.0j)) assert ae(v, (7.0789514293925893007 - 1.5313749363937141849j), tol=ATOL) assert ae(v.real, 7.0789514293925893007, tol=PTOL) assert ae(v.imag, -1.5313749363937141849, tol=PTOL) v = fp.ei((20.0 - 80.0j)) assert ae(v, (-5855431.4907298084434 + 720917.79156143806727j), tol=ATOL) assert ae(v.real, -5855431.4907298084434, tol=PTOL) assert ae(v.imag, 720917.79156143806727, tol=PTOL) v = fp.ei((30.0 - 120.0j)) assert ae(v, (65402491644.703470747 + 56697658396.51586764j), tol=ATOL) assert ae(v.real, 65402491644.703470747, tol=PTOL) assert ae(v.imag, 56697658396.51586764, tol=PTOL) v = fp.ei((40.0 - 160.0j)) assert ae(v, (-25504929379604.776769 - 1429035198630576.3879j), tol=ATOL) assert ae(v.real, -25504929379604.776769, tol=PTOL) assert ae(v.imag, -1429035198630576.3879, tol=PTOL) v = fp.ei((50.0 - 200.0j)) assert ae(v, (-18437746526988116954.0 + 17146362239046152342.0j), tol=ATOL) assert ae(v.real, -18437746526988116954.0, tol=PTOL) assert ae(v.imag, 17146362239046152342.0, tol=PTOL) v = fp.ei((80.0 - 320.0j)) assert ae(v, (-3.3464697299634526706e+31 + 1.6473152633843023919e+32j), tol=ATOL) assert ae(v.real, -3.3464697299634526706e+31, tol=PTOL) assert ae(v.imag, 1.6473152633843023919e+32, tol=PTOL) v = fp.ei((1.1641532182693481445e-10 - 1.1641532182693481445e-10j)) assert ae(v, (-21.950067703180274374 - 0.78539816351386363145j), tol=ATOL) assert ae(v.real, -21.950067703180274374, tol=PTOL) assert ae(v.imag, -0.78539816351386363145, tol=PTOL) v = fp.ei((0.25 - 0.25j)) assert ae(v, (-0.21441047326710323254 - 1.0683772981589995996j), tol=ATOL) assert ae(v.real, -0.21441047326710323254, tol=PTOL) assert ae(v.imag, -1.0683772981589995996, tol=PTOL) v = fp.ei((1.0 - 1.0j)) assert ae(v, (1.7646259855638540684 - 2.3877698515105224193j), tol=ATOL) assert ae(v.real, 1.7646259855638540684, tol=PTOL) assert ae(v.imag, -2.3877698515105224193, tol=PTOL) v = fp.ei((2.0 - 2.0j)) assert ae(v, (1.8920781621855474089 - 5.3169624378326579621j), tol=ATOL) assert ae(v.real, 1.8920781621855474089, tol=PTOL) assert ae(v.imag, -5.3169624378326579621, tol=PTOL) v = fp.ei((5.0 - 5.0j)) assert ae(v, (-13.470936071475245856 + 15.322492395731230968j), tol=ATOL) assert ae(v.real, -13.470936071475245856, tol=PTOL) assert ae(v.imag, 15.322492395731230968, tol=PTOL) v = fp.ei((20.0 - 20.0j)) assert ae(v, (16589317.398788971896 - 5831705.4712368307104j), tol=ATOL) assert ae(v.real, 16589317.398788971896, tol=PTOL) assert ae(v.imag, -5831705.4712368307104, tol=PTOL) v = fp.ei((30.0 - 30.0j)) assert ae(v, (-154596484273.69322527 + 204179357834.2723043j), tol=ATOL) assert ae(v.real, -154596484273.69322527, tol=PTOL) assert ae(v.imag, 204179357834.2723043, tol=PTOL) v = fp.ei((40.0 - 40.0j)) assert ae(v, (287512180321448.45408 - 4203502407932318.1156j), tol=ATOL) assert ae(v.real, 287512180321448.45408, tol=PTOL) assert ae(v.imag, -4203502407932318.1156, tol=PTOL) v = fp.ei((50.0 - 50.0j)) assert ae(v, (36128528616649268826.0 + 64648801861338741960.0j), tol=ATOL) assert ae(v.real, 36128528616649268826.0, tol=PTOL) assert ae(v.imag, 64648801861338741960.0, tol=PTOL) v = fp.ei((80.0 - 80.0j)) assert ae(v, (-3.8674816337930010217e+32 + 3.0540709639658071041e+32j), tol=ATOL) assert ae(v.real, -3.8674816337930010217e+32, tol=PTOL) assert ae(v.imag, 3.0540709639658071041e+32, tol=PTOL) v = fp.ei((4.6566128730773925781e-10 - 1.1641532182693481445e-10j)) assert ae(v, (-20.880034621082893023 - 0.24497866324327947603j), tol=ATOL) assert ae(v.real, -20.880034621082893023, tol=PTOL) assert ae(v.imag, -0.24497866324327947603, tol=PTOL) v = fp.ei((1.0 - 0.25j)) assert ae(v, (1.8942716983721074932 - 0.67268237088273915854j), tol=ATOL) assert ae(v.real, 1.8942716983721074932, tol=PTOL) assert ae(v.imag, -0.67268237088273915854, tol=PTOL) v = fp.ei((4.0 - 1.0j)) assert ae(v, (14.806699492675420438 - 12.280015176673582616j), tol=ATOL) assert ae(v.real, 14.806699492675420438, tol=PTOL) assert ae(v.imag, -12.280015176673582616, tol=PTOL) v = fp.ei((8.0 - 2.0j)) assert ae(v, (-54.633252667426386294 - 416.34477429173650012j), tol=ATOL) assert ae(v.real, -54.633252667426386294, tol=PTOL) assert ae(v.imag, -416.34477429173650012, tol=PTOL) v = fp.ei((20.0 - 5.0j)) assert ae(v, (711836.97165402624643 + 24745247.798103247366j), tol=ATOL) assert ae(v.real, 711836.97165402624643, tol=PTOL) assert ae(v.imag, 24745247.798103247366, tol=PTOL) v = fp.ei((80.0 - 20.0j)) assert ae(v, (4.2139911108612653091e+32 - 5.3367124741918251637e+32j), tol=ATOL) assert ae(v.real, 4.2139911108612653091e+32, tol=PTOL) assert ae(v.imag, -5.3367124741918251637e+32, tol=PTOL) v = fp.ei((120.0 - 30.0j)) assert ae(v, (-9.7760616203707508892e+48 + 1.058257682317195792e+50j), tol=ATOL) assert ae(v.real, -9.7760616203707508892e+48, tol=PTOL) assert ae(v.imag, 1.058257682317195792e+50, tol=PTOL) v = fp.ei((160.0 - 40.0j)) assert ae(v, (-8.7065541466623638861e+66 - 1.6577106725141739889e+67j), tol=ATOL) assert ae(v.real, -8.7065541466623638861e+66, tol=PTOL) assert ae(v.imag, -1.6577106725141739889e+67, tol=PTOL) v = fp.ei((200.0 - 50.0j)) assert ae(v, (3.070744996327018106e+84 + 1.7243244846769415903e+84j), tol=ATOL) assert ae(v.real, 3.070744996327018106e+84, tol=PTOL) assert ae(v.imag, 1.7243244846769415903e+84, tol=PTOL) v = fp.ei((320.0 - 80.0j)) assert ae(v, (-9.9960598637998647276e+135 + 2.6855081527595608863e+136j), tol=ATOL) assert ae(v.real, -9.9960598637998647276e+135, tol=PTOL) assert ae(v.imag, 2.6855081527595608863e+136, tol=PTOL) mpmath-1.1.0/mpmath/tests/test_functions.py000066400000000000000000000743531340375245600210750ustar00rootroot00000000000000from mpmath.libmp import * from mpmath import * import random import time import math import cmath def mpc_ae(a, b, eps=eps): res = True res = res and a.real.ae(b.real, eps) res = res and a.imag.ae(b.imag, eps) return res #---------------------------------------------------------------------------- # Constants and functions # tpi = "3.1415926535897932384626433832795028841971693993751058209749445923078\ 1640628620899862803482534211706798" te = "2.71828182845904523536028747135266249775724709369995957496696762772407\ 663035354759457138217852516642743" tdegree = "0.017453292519943295769236907684886127134428718885417254560971914\ 4017100911460344944368224156963450948221" teuler = "0.5772156649015328606065120900824024310421593359399235988057672348\ 84867726777664670936947063291746749516" tln2 = "0.693147180559945309417232121458176568075500134360255254120680009493\ 393621969694715605863326996418687542" tln10 = "2.30258509299404568401799145468436420760110148862877297603332790096\ 757260967735248023599720508959829834" tcatalan = "0.91596559417721901505460351493238411077414937428167213426649811\ 9621763019776254769479356512926115106249" tkhinchin = "2.6854520010653064453097148354817956938203822939944629530511523\ 4555721885953715200280114117493184769800" tglaisher = "1.2824271291006226368753425688697917277676889273250011920637400\ 2174040630885882646112973649195820237439420646" tapery = "1.2020569031595942853997381615114499907649862923404988817922715553\ 4183820578631309018645587360933525815" tphi = "1.618033988749894848204586834365638117720309179805762862135448622705\ 26046281890244970720720418939113748475" tmertens = "0.26149721284764278375542683860869585905156664826119920619206421\ 3924924510897368209714142631434246651052" ttwinprime = "0.660161815846869573927812110014555778432623360284733413319448\ 423335405642304495277143760031413839867912" def test_constants(): for prec in [3, 7, 10, 15, 20, 37, 80, 100, 29]: mp.dps = prec assert pi == mpf(tpi) assert e == mpf(te) assert degree == mpf(tdegree) assert euler == mpf(teuler) assert ln2 == mpf(tln2) assert ln10 == mpf(tln10) assert catalan == mpf(tcatalan) assert khinchin == mpf(tkhinchin) assert glaisher == mpf(tglaisher) assert phi == mpf(tphi) if prec < 50: assert mertens == mpf(tmertens) assert twinprime == mpf(ttwinprime) mp.dps = 15 assert pi >= -1 assert pi > 2 assert pi > 3 assert pi < 4 def test_exact_sqrts(): for i in range(20000): assert sqrt(mpf(i*i)) == i random.seed(1) for prec in [100, 300, 1000, 10000]: mp.dps = prec for i in range(20): A = random.randint(10**(prec//2-2), 10**(prec//2-1)) assert sqrt(mpf(A*A)) == A mp.dps = 15 for i in range(100): for a in [1, 8, 25, 112307]: assert sqrt(mpf((a*a, 2*i))) == mpf((a, i)) assert sqrt(mpf((a*a, -2*i))) == mpf((a, -i)) def test_sqrt_rounding(): for i in [2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15]: i = from_int(i) for dps in [7, 15, 83, 106, 2000]: mp.dps = dps a = mpf_pow_int(mpf_sqrt(i, mp.prec, round_down), 2, mp.prec, round_down) b = mpf_pow_int(mpf_sqrt(i, mp.prec, round_up), 2, mp.prec, round_up) assert mpf_lt(a, i) assert mpf_gt(b, i) random.seed(1234) prec = 100 for rnd in [round_down, round_nearest, round_ceiling]: for i in range(100): a = mpf_rand(prec) b = mpf_mul(a, a) assert mpf_sqrt(b, prec, rnd) == a # Test some extreme cases mp.dps = 100 a = mpf(9) + 1e-90 b = mpf(9) - 1e-90 mp.dps = 15 assert sqrt(a, rounding='d') == 3 assert sqrt(a, rounding='n') == 3 assert sqrt(a, rounding='u') > 3 assert sqrt(b, rounding='d') < 3 assert sqrt(b, rounding='n') == 3 assert sqrt(b, rounding='u') == 3 # A worst case, from the MPFR test suite assert sqrt(mpf('7.0503726185518891')) == mpf('2.655253776675949') def test_float_sqrt(): mp.dps = 15 # These should round identically for x in [0, 1e-7, 0.1, 0.5, 1, 2, 3, 4, 5, 0.333, 76.19]: assert sqrt(mpf(x)) == float(x)**0.5 assert sqrt(-1) == 1j assert sqrt(-2).ae(cmath.sqrt(-2)) assert sqrt(-3).ae(cmath.sqrt(-3)) assert sqrt(-100).ae(cmath.sqrt(-100)) assert sqrt(1j).ae(cmath.sqrt(1j)) assert sqrt(-1j).ae(cmath.sqrt(-1j)) assert sqrt(math.pi + math.e*1j).ae(cmath.sqrt(math.pi + math.e*1j)) assert sqrt(math.pi - math.e*1j).ae(cmath.sqrt(math.pi - math.e*1j)) def test_hypot(): assert hypot(0, 0) == 0 assert hypot(0, 0.33) == mpf(0.33) assert hypot(0.33, 0) == mpf(0.33) assert hypot(-0.33, 0) == mpf(0.33) assert hypot(3, 4) == mpf(5) def test_exact_cbrt(): for i in range(0, 20000, 200): assert cbrt(mpf(i*i*i)) == i random.seed(1) for prec in [100, 300, 1000, 10000]: mp.dps = prec A = random.randint(10**(prec//2-2), 10**(prec//2-1)) assert cbrt(mpf(A*A*A)) == A mp.dps = 15 def test_exp(): assert exp(0) == 1 assert exp(10000).ae(mpf('8.8068182256629215873e4342')) assert exp(-10000).ae(mpf('1.1354838653147360985e-4343')) a = exp(mpf((1, 8198646019315405, -53, 53))) assert(a.bc == bitcount(a.man)) mp.prec = 67 a = exp(mpf((1, 1781864658064754565, -60, 61))) assert(a.bc == bitcount(a.man)) mp.prec = 53 assert exp(ln2 * 10).ae(1024) assert exp(2+2j).ae(cmath.exp(2+2j)) def test_issue_73(): mp.dps = 512 a = exp(-1) b = exp(1) mp.dps = 15 assert (+a).ae(0.36787944117144233) assert (+b).ae(2.7182818284590451) def test_log(): mp.dps = 15 assert log(1) == 0 for x in [0.5, 1.5, 2.0, 3.0, 100, 10**50, 1e-50]: assert log(x).ae(math.log(x)) assert log(x, x) == 1 assert log(1024, 2) == 10 assert log(10**1234, 10) == 1234 assert log(2+2j).ae(cmath.log(2+2j)) # Accuracy near 1 assert (log(0.6+0.8j).real*10**17).ae(2.2204460492503131) assert (log(0.6-0.8j).real*10**17).ae(2.2204460492503131) assert (log(0.8-0.6j).real*10**17).ae(2.2204460492503131) assert (log(1+1e-8j).real*10**16).ae(0.5) assert (log(1-1e-8j).real*10**16).ae(0.5) assert (log(-1+1e-8j).real*10**16).ae(0.5) assert (log(-1-1e-8j).real*10**16).ae(0.5) assert (log(1j+1e-8).real*10**16).ae(0.5) assert (log(1j-1e-8).real*10**16).ae(0.5) assert (log(-1j+1e-8).real*10**16).ae(0.5) assert (log(-1j-1e-8).real*10**16).ae(0.5) assert (log(1+1e-40j).real*10**80).ae(0.5) assert (log(1j+1e-40).real*10**80).ae(0.5) # Huge assert log(ldexp(1.234,10**20)).ae(log(2)*1e20) assert log(ldexp(1.234,10**200)).ae(log(2)*1e200) # Some special values assert log(mpc(0,0)) == mpc(-inf,0) assert isnan(log(mpc(nan,0)).real) assert isnan(log(mpc(nan,0)).imag) assert isnan(log(mpc(0,nan)).real) assert isnan(log(mpc(0,nan)).imag) assert isnan(log(mpc(nan,1)).real) assert isnan(log(mpc(nan,1)).imag) assert isnan(log(mpc(1,nan)).real) assert isnan(log(mpc(1,nan)).imag) def test_trig_hyperb_basic(): for x in (list(range(100)) + list(range(-100,0))): t = x / 4.1 assert cos(mpf(t)).ae(math.cos(t)) assert sin(mpf(t)).ae(math.sin(t)) assert tan(mpf(t)).ae(math.tan(t)) assert cosh(mpf(t)).ae(math.cosh(t)) assert sinh(mpf(t)).ae(math.sinh(t)) assert tanh(mpf(t)).ae(math.tanh(t)) assert sin(1+1j).ae(cmath.sin(1+1j)) assert sin(-4-3.6j).ae(cmath.sin(-4-3.6j)) assert cos(1+1j).ae(cmath.cos(1+1j)) assert cos(-4-3.6j).ae(cmath.cos(-4-3.6j)) def test_degrees(): assert cos(0*degree) == 1 assert cos(90*degree).ae(0) assert cos(180*degree).ae(-1) assert cos(270*degree).ae(0) assert cos(360*degree).ae(1) assert sin(0*degree) == 0 assert sin(90*degree).ae(1) assert sin(180*degree).ae(0) assert sin(270*degree).ae(-1) assert sin(360*degree).ae(0) def random_complexes(N): random.seed(1) a = [] for i in range(N): x1 = random.uniform(-10, 10) y1 = random.uniform(-10, 10) x2 = random.uniform(-10, 10) y2 = random.uniform(-10, 10) z1 = complex(x1, y1) z2 = complex(x2, y2) a.append((z1, z2)) return a def test_complex_powers(): for dps in [15, 30, 100]: # Check accuracy for complex square root mp.dps = dps a = mpc(1j)**0.5 assert a.real == a.imag == mpf(2)**0.5 / 2 mp.dps = 15 random.seed(1) for (z1, z2) in random_complexes(100): assert (mpc(z1)**mpc(z2)).ae(z1**z2, 1e-12) assert (e**(-pi*1j)).ae(-1) mp.dps = 50 assert (e**(-pi*1j)).ae(-1) mp.dps = 15 def test_complex_sqrt_accuracy(): def test_mpc_sqrt(lst): for a, b in lst: z = mpc(a + j*b) assert mpc_ae(sqrt(z*z), z) z = mpc(-a + j*b) assert mpc_ae(sqrt(z*z), -z) z = mpc(a - j*b) assert mpc_ae(sqrt(z*z), z) z = mpc(-a - j*b) assert mpc_ae(sqrt(z*z), -z) random.seed(2) N = 10 mp.dps = 30 dps = mp.dps test_mpc_sqrt([(random.uniform(0, 10),random.uniform(0, 10)) for i in range(N)]) test_mpc_sqrt([(i + 0.1, (i + 0.2)*10**i) for i in range(N)]) mp.dps = 15 def test_atan(): mp.dps = 15 assert atan(-2.3).ae(math.atan(-2.3)) assert atan(1e-50) == 1e-50 assert atan(1e50).ae(pi/2) assert atan(-1e-50) == -1e-50 assert atan(-1e50).ae(-pi/2) assert atan(10**1000).ae(pi/2) for dps in [25, 70, 100, 300, 1000]: mp.dps = dps assert (4*atan(1)).ae(pi) mp.dps = 15 pi2 = pi/2 assert atan(mpc(inf,-1)).ae(pi2) assert atan(mpc(inf,0)).ae(pi2) assert atan(mpc(inf,1)).ae(pi2) assert atan(mpc(1,inf)).ae(pi2) assert atan(mpc(0,inf)).ae(pi2) assert atan(mpc(-1,inf)).ae(-pi2) assert atan(mpc(-inf,1)).ae(-pi2) assert atan(mpc(-inf,0)).ae(-pi2) assert atan(mpc(-inf,-1)).ae(-pi2) assert atan(mpc(-1,-inf)).ae(-pi2) assert atan(mpc(0,-inf)).ae(-pi2) assert atan(mpc(1,-inf)).ae(pi2) def test_atan2(): mp.dps = 15 assert atan2(1,1).ae(pi/4) assert atan2(1,-1).ae(3*pi/4) assert atan2(-1,-1).ae(-3*pi/4) assert atan2(-1,1).ae(-pi/4) assert atan2(-1,0).ae(-pi/2) assert atan2(1,0).ae(pi/2) assert atan2(0,0) == 0 assert atan2(inf,0).ae(pi/2) assert atan2(-inf,0).ae(-pi/2) assert isnan(atan2(inf,inf)) assert isnan(atan2(-inf,inf)) assert isnan(atan2(inf,-inf)) assert isnan(atan2(3,nan)) assert isnan(atan2(nan,3)) assert isnan(atan2(0,nan)) assert isnan(atan2(nan,0)) assert atan2(0,inf) == 0 assert atan2(0,-inf).ae(pi) assert atan2(10,inf) == 0 assert atan2(-10,inf) == 0 assert atan2(-10,-inf).ae(-pi) assert atan2(10,-inf).ae(pi) assert atan2(inf,10).ae(pi/2) assert atan2(inf,-10).ae(pi/2) assert atan2(-inf,10).ae(-pi/2) assert atan2(-inf,-10).ae(-pi/2) def test_areal_inverses(): assert asin(mpf(0)) == 0 assert asinh(mpf(0)) == 0 assert acosh(mpf(1)) == 0 assert isinstance(asin(mpf(0.5)), mpf) assert isinstance(asin(mpf(2.0)), mpc) assert isinstance(acos(mpf(0.5)), mpf) assert isinstance(acos(mpf(2.0)), mpc) assert isinstance(atanh(mpf(0.1)), mpf) assert isinstance(atanh(mpf(1.1)), mpc) random.seed(1) for i in range(50): x = random.uniform(0, 1) assert asin(mpf(x)).ae(math.asin(x)) assert acos(mpf(x)).ae(math.acos(x)) x = random.uniform(-10, 10) assert asinh(mpf(x)).ae(cmath.asinh(x).real) assert isinstance(asinh(mpf(x)), mpf) x = random.uniform(1, 10) assert acosh(mpf(x)).ae(cmath.acosh(x).real) assert isinstance(acosh(mpf(x)), mpf) x = random.uniform(-10, 0.999) assert isinstance(acosh(mpf(x)), mpc) x = random.uniform(-1, 1) assert atanh(mpf(x)).ae(cmath.atanh(x).real) assert isinstance(atanh(mpf(x)), mpf) dps = mp.dps mp.dps = 300 assert isinstance(asin(0.5), mpf) mp.dps = 1000 assert asin(1).ae(pi/2) assert asin(-1).ae(-pi/2) mp.dps = dps def test_invhyperb_inaccuracy(): mp.dps = 15 assert (asinh(1e-5)*10**5).ae(0.99999999998333333) assert (asinh(1e-10)*10**10).ae(1) assert (asinh(1e-50)*10**50).ae(1) assert (asinh(-1e-5)*10**5).ae(-0.99999999998333333) assert (asinh(-1e-10)*10**10).ae(-1) assert (asinh(-1e-50)*10**50).ae(-1) assert asinh(10**20).ae(46.744849040440862) assert asinh(-10**20).ae(-46.744849040440862) assert (tanh(1e-10)*10**10).ae(1) assert (tanh(-1e-10)*10**10).ae(-1) assert (atanh(1e-10)*10**10).ae(1) assert (atanh(-1e-10)*10**10).ae(-1) def test_complex_functions(): for x in (list(range(10)) + list(range(-10,0))): for y in (list(range(10)) + list(range(-10,0))): z = complex(x, y)/4.3 + 0.01j assert exp(mpc(z)).ae(cmath.exp(z)) assert log(mpc(z)).ae(cmath.log(z)) assert cos(mpc(z)).ae(cmath.cos(z)) assert sin(mpc(z)).ae(cmath.sin(z)) assert tan(mpc(z)).ae(cmath.tan(z)) assert sinh(mpc(z)).ae(cmath.sinh(z)) assert cosh(mpc(z)).ae(cmath.cosh(z)) assert tanh(mpc(z)).ae(cmath.tanh(z)) def test_complex_inverse_functions(): mp.dps = 15 iv.dps = 15 for (z1, z2) in random_complexes(30): # apparently cmath uses a different branch, so we # can't use it for comparison assert sinh(asinh(z1)).ae(z1) # assert acosh(z1).ae(cmath.acosh(z1)) assert atanh(z1).ae(cmath.atanh(z1)) assert atan(z1).ae(cmath.atan(z1)) # the reason we set a big eps here is that the cmath # functions are inaccurate assert asin(z1).ae(cmath.asin(z1), rel_eps=1e-12) assert acos(z1).ae(cmath.acos(z1), rel_eps=1e-12) one = mpf(1) for i in range(-9, 10, 3): for k in range(-9, 10, 3): a = 0.9*j*10**k + 0.8*one*10**i b = cos(acos(a)) assert b.ae(a) b = sin(asin(a)) assert b.ae(a) one = mpf(1) err = 2*10**-15 for i in range(-9, 9, 3): for k in range(-9, 9, 3): a = -0.9*10**k + j*0.8*one*10**i b = cosh(acosh(a)) assert b.ae(a, err) b = sinh(asinh(a)) assert b.ae(a, err) def test_reciprocal_functions(): assert sec(3).ae(-1.01010866590799375) assert csc(3).ae(7.08616739573718592) assert cot(3).ae(-7.01525255143453347) assert sech(3).ae(0.0993279274194332078) assert csch(3).ae(0.0998215696688227329) assert coth(3).ae(1.00496982331368917) assert asec(3).ae(1.23095941734077468) assert acsc(3).ae(0.339836909454121937) assert acot(3).ae(0.321750554396642193) assert asech(0.5).ae(1.31695789692481671) assert acsch(3).ae(0.327450150237258443) assert acoth(3).ae(0.346573590279972655) assert acot(0).ae(1.5707963267948966192) assert acoth(0).ae(1.5707963267948966192j) def test_ldexp(): mp.dps = 15 assert ldexp(mpf(2.5), 0) == 2.5 assert ldexp(mpf(2.5), -1) == 1.25 assert ldexp(mpf(2.5), 2) == 10 assert ldexp(mpf('inf'), 3) == mpf('inf') def test_frexp(): mp.dps = 15 assert frexp(0) == (0.0, 0) assert frexp(9) == (0.5625, 4) assert frexp(1) == (0.5, 1) assert frexp(0.2) == (0.8, -2) assert frexp(1000) == (0.9765625, 10) def test_aliases(): assert ln(7) == log(7) assert log10(3.75) == log(3.75,10) assert degrees(5.6) == 5.6 / degree assert radians(5.6) == 5.6 * degree assert power(-1,0.5) == j assert fmod(25,7) == 4.0 and isinstance(fmod(25,7), mpf) def test_arg_sign(): assert arg(3) == 0 assert arg(-3).ae(pi) assert arg(j).ae(pi/2) assert arg(-j).ae(-pi/2) assert arg(0) == 0 assert isnan(atan2(3,nan)) assert isnan(atan2(nan,3)) assert isnan(atan2(0,nan)) assert isnan(atan2(nan,0)) assert isnan(atan2(nan,nan)) assert arg(inf) == 0 assert arg(-inf).ae(pi) assert isnan(arg(nan)) #assert arg(inf*j).ae(pi/2) assert sign(0) == 0 assert sign(3) == 1 assert sign(-3) == -1 assert sign(inf) == 1 assert sign(-inf) == -1 assert isnan(sign(nan)) assert sign(j) == j assert sign(-3*j) == -j assert sign(1+j).ae((1+j)/sqrt(2)) def test_misc_bugs(): # test that this doesn't raise an exception mp.dps = 1000 log(1302) mp.dps = 15 def test_arange(): assert arange(10) == [mpf('0.0'), mpf('1.0'), mpf('2.0'), mpf('3.0'), mpf('4.0'), mpf('5.0'), mpf('6.0'), mpf('7.0'), mpf('8.0'), mpf('9.0')] assert arange(-5, 5) == [mpf('-5.0'), mpf('-4.0'), mpf('-3.0'), mpf('-2.0'), mpf('-1.0'), mpf('0.0'), mpf('1.0'), mpf('2.0'), mpf('3.0'), mpf('4.0')] assert arange(0, 1, 0.1) == [mpf('0.0'), mpf('0.10000000000000001'), mpf('0.20000000000000001'), mpf('0.30000000000000004'), mpf('0.40000000000000002'), mpf('0.5'), mpf('0.60000000000000009'), mpf('0.70000000000000007'), mpf('0.80000000000000004'), mpf('0.90000000000000002')] assert arange(17, -9, -3) == [mpf('17.0'), mpf('14.0'), mpf('11.0'), mpf('8.0'), mpf('5.0'), mpf('2.0'), mpf('-1.0'), mpf('-4.0'), mpf('-7.0')] assert arange(0.2, 0.1, -0.1) == [mpf('0.20000000000000001')] assert arange(0) == [] assert arange(1000, -1) == [] assert arange(-1.23, 3.21, -0.0000001) == [] def test_linspace(): assert linspace(2, 9, 7) == [mpf('2.0'), mpf('3.166666666666667'), mpf('4.3333333333333339'), mpf('5.5'), mpf('6.666666666666667'), mpf('7.8333333333333339'), mpf('9.0')] assert linspace(2, 9, 7, endpoint=0) == [mpf('2.0'), mpf('3.0'), mpf('4.0'), mpf('5.0'), mpf('6.0'), mpf('7.0'), mpf('8.0')] assert linspace(2, 7, 1) == [mpf(2)] def test_float_cbrt(): mp.dps = 30 for a in arange(0,10,0.1): assert cbrt(a*a*a).ae(a, eps) assert cbrt(-1).ae(0.5 + j*sqrt(3)/2) one_third = mpf(1)/3 for a in arange(0,10,2.7) + [0.1 + 10**5]: a = mpc(a + 1.1j) r1 = cbrt(a) mp.dps += 10 r2 = pow(a, one_third) mp.dps -= 10 assert r1.ae(r2, eps) mp.dps = 100 for n in range(100, 301, 100): w = 10**n + j*10**-3 z = w*w*w r = cbrt(z) assert mpc_ae(r, w, eps) mp.dps = 15 def test_root(): mp.dps = 30 random.seed(1) a = random.randint(0, 10000) p = a*a*a r = nthroot(mpf(p), 3) assert r == a for n in range(4, 10): p = p*a assert nthroot(mpf(p), n) == a mp.dps = 40 for n in range(10, 5000, 100): for a in [random.random()*10000, random.random()*10**100]: r = nthroot(a, n) r1 = pow(a, mpf(1)/n) assert r.ae(r1) r = nthroot(a, -n) r1 = pow(a, -mpf(1)/n) assert r.ae(r1) # XXX: this is broken right now # tests for nthroot rounding for rnd in ['nearest', 'up', 'down']: mp.rounding = rnd for n in [-5, -3, 3, 5]: prec = 50 for i in range(10): mp.prec = prec a = rand() mp.prec = 2*prec b = a**n mp.prec = prec r = nthroot(b, n) assert r == a mp.dps = 30 for n in range(3, 21): a = (random.random() + j*random.random()) assert nthroot(a, n).ae(pow(a, mpf(1)/n)) assert mpc_ae(nthroot(a, n), pow(a, mpf(1)/n)) a = (random.random()*10**100 + j*random.random()) r = nthroot(a, n) mp.dps += 4 r1 = pow(a, mpf(1)/n) mp.dps -= 4 assert r.ae(r1) assert mpc_ae(r, r1, eps) r = nthroot(a, -n) mp.dps += 4 r1 = pow(a, -mpf(1)/n) mp.dps -= 4 assert r.ae(r1) assert mpc_ae(r, r1, eps) mp.dps = 15 assert nthroot(4, 1) == 4 assert nthroot(4, 0) == 1 assert nthroot(4, -1) == 0.25 assert nthroot(inf, 1) == inf assert nthroot(inf, 2) == inf assert nthroot(inf, 3) == inf assert nthroot(inf, -1) == 0 assert nthroot(inf, -2) == 0 assert nthroot(inf, -3) == 0 assert nthroot(j, 1) == j assert nthroot(j, 0) == 1 assert nthroot(j, -1) == -j assert isnan(nthroot(nan, 1)) assert isnan(nthroot(nan, 0)) assert isnan(nthroot(nan, -1)) assert isnan(nthroot(inf, 0)) assert root(2,3) == nthroot(2,3) assert root(16,4,0) == 2 assert root(16,4,1) == 2j assert root(16,4,2) == -2 assert root(16,4,3) == -2j assert root(16,4,4) == 2 assert root(-125,3,1) == -5 def test_issue_136(): for dps in [20, 80]: mp.dps = dps r = nthroot(mpf('-1e-20'), 4) assert r.ae(mpf(10)**(-5) * (1 + j) * mpf(2)**(-0.5)) mp.dps = 80 assert nthroot('-1e-3', 4).ae(mpf(10)**(-3./4) * (1 + j)/sqrt(2)) assert nthroot('-1e-6', 4).ae((1 + j)/(10 * sqrt(20))) # Check that this doesn't take eternity to compute mp.dps = 20 assert nthroot('-1e100000000', 4).ae((1+j)*mpf('1e25000000')/sqrt(2)) mp.dps = 15 def test_mpcfun_real_imag(): mp.dps = 15 x = mpf(0.3) y = mpf(0.4) assert exp(mpc(x,0)) == exp(x) assert exp(mpc(0,y)) == mpc(cos(y),sin(y)) assert cos(mpc(x,0)) == cos(x) assert sin(mpc(x,0)) == sin(x) assert cos(mpc(0,y)) == cosh(y) assert sin(mpc(0,y)) == mpc(0,sinh(y)) assert cospi(mpc(x,0)) == cospi(x) assert sinpi(mpc(x,0)) == sinpi(x) assert cospi(mpc(0,y)).ae(cosh(pi*y)) assert sinpi(mpc(0,y)).ae(mpc(0,sinh(pi*y))) c, s = cospi_sinpi(mpc(x,0)) assert c == cospi(x) assert s == sinpi(x) c, s = cospi_sinpi(mpc(0,y)) assert c.ae(cosh(pi*y)) assert s.ae(mpc(0,sinh(pi*y))) c, s = cos_sin(mpc(x,0)) assert c == cos(x) assert s == sin(x) c, s = cos_sin(mpc(0,y)) assert c == cosh(y) assert s == mpc(0,sinh(y)) def test_perturbation_rounding(): mp.dps = 100 a = pi/10**50 b = -pi/10**50 c = 1 + a d = 1 + b mp.dps = 15 assert exp(a) == 1 assert exp(a, rounding='c') > 1 assert exp(b, rounding='c') == 1 assert exp(a, rounding='f') == 1 assert exp(b, rounding='f') < 1 assert cos(a) == 1 assert cos(a, rounding='c') == 1 assert cos(b, rounding='c') == 1 assert cos(a, rounding='f') < 1 assert cos(b, rounding='f') < 1 for f in [sin, atan, asinh, tanh]: assert f(a) == +a assert f(a, rounding='c') > a assert f(a, rounding='f') < a assert f(b) == +b assert f(b, rounding='c') > b assert f(b, rounding='f') < b for f in [asin, tan, sinh, atanh]: assert f(a) == +a assert f(b) == +b assert f(a, rounding='c') > a assert f(b, rounding='c') > b assert f(a, rounding='f') < a assert f(b, rounding='f') < b assert ln(c) == +a assert ln(d) == +b assert ln(c, rounding='c') > a assert ln(c, rounding='f') < a assert ln(d, rounding='c') > b assert ln(d, rounding='f') < b assert cosh(a) == 1 assert cosh(b) == 1 assert cosh(a, rounding='c') > 1 assert cosh(b, rounding='c') > 1 assert cosh(a, rounding='f') == 1 assert cosh(b, rounding='f') == 1 def test_integer_parts(): assert floor(3.2) == 3 assert ceil(3.2) == 4 assert floor(3.2+5j) == 3+5j assert ceil(3.2+5j) == 4+5j def test_complex_parts(): assert fabs('3') == 3 assert fabs(3+4j) == 5 assert re(3) == 3 assert re(1+4j) == 1 assert im(3) == 0 assert im(1+4j) == 4 assert conj(3) == 3 assert conj(3+4j) == 3-4j assert mpf(3).conjugate() == 3 def test_cospi_sinpi(): assert sinpi(0) == 0 assert sinpi(0.5) == 1 assert sinpi(1) == 0 assert sinpi(1.5) == -1 assert sinpi(2) == 0 assert sinpi(2.5) == 1 assert sinpi(-0.5) == -1 assert cospi(0) == 1 assert cospi(0.5) == 0 assert cospi(1) == -1 assert cospi(1.5) == 0 assert cospi(2) == 1 assert cospi(2.5) == 0 assert cospi(-0.5) == 0 assert cospi(100000000000.25).ae(sqrt(2)/2) a = cospi(2+3j) assert a.real.ae(cos((2+3j)*pi).real) assert a.imag == 0 b = sinpi(2+3j) assert b.imag.ae(sin((2+3j)*pi).imag) assert b.real == 0 mp.dps = 35 x1 = mpf(10000) - mpf('1e-15') x2 = mpf(10000) + mpf('1e-15') x3 = mpf(10000.5) - mpf('1e-15') x4 = mpf(10000.5) + mpf('1e-15') x5 = mpf(10001) - mpf('1e-15') x6 = mpf(10001) + mpf('1e-15') x7 = mpf(10001.5) - mpf('1e-15') x8 = mpf(10001.5) + mpf('1e-15') mp.dps = 15 M = 10**15 assert (sinpi(x1)*M).ae(-pi) assert (sinpi(x2)*M).ae(pi) assert (cospi(x3)*M).ae(pi) assert (cospi(x4)*M).ae(-pi) assert (sinpi(x5)*M).ae(pi) assert (sinpi(x6)*M).ae(-pi) assert (cospi(x7)*M).ae(-pi) assert (cospi(x8)*M).ae(pi) assert 0.999 < cospi(x1, rounding='d') < 1 assert 0.999 < cospi(x2, rounding='d') < 1 assert 0.999 < sinpi(x3, rounding='d') < 1 assert 0.999 < sinpi(x4, rounding='d') < 1 assert -1 < cospi(x5, rounding='d') < -0.999 assert -1 < cospi(x6, rounding='d') < -0.999 assert -1 < sinpi(x7, rounding='d') < -0.999 assert -1 < sinpi(x8, rounding='d') < -0.999 assert (sinpi(1e-15)*M).ae(pi) assert (sinpi(-1e-15)*M).ae(-pi) assert cospi(1e-15) == 1 assert cospi(1e-15, rounding='d') < 1 def test_expj(): assert expj(0) == 1 assert expj(1).ae(exp(j)) assert expj(j).ae(exp(-1)) assert expj(1+j).ae(exp(j*(1+j))) assert expjpi(0) == 1 assert expjpi(1).ae(exp(j*pi)) assert expjpi(j).ae(exp(-pi)) assert expjpi(1+j).ae(exp(j*pi*(1+j))) assert expjpi(-10**15 * j).ae('2.22579818340535731e+1364376353841841') def test_sinc(): assert sinc(0) == sincpi(0) == 1 assert sinc(inf) == sincpi(inf) == 0 assert sinc(-inf) == sincpi(-inf) == 0 assert sinc(2).ae(0.45464871341284084770) assert sinc(2+3j).ae(0.4463290318402435457-2.7539470277436474940j) assert sincpi(2) == 0 assert sincpi(1.5).ae(-0.212206590789193781) def test_fibonacci(): mp.dps = 15 assert [fibonacci(n) for n in range(-5, 10)] == \ [5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34] assert fib(2.5).ae(1.4893065462657091) assert fib(3+4j).ae(-5248.51130728372 - 14195.962288353j) assert fib(1000).ae(4.3466557686937455e+208) assert str(fib(10**100)) == '6.24499112864607e+2089876402499787337692720892375554168224592399182109535392875613974104853496745963277658556235103534' mp.dps = 2100 a = fib(10000) assert a % 10**10 == 9947366875 mp.dps = 15 assert fibonacci(inf) == inf assert fib(3+0j) == 2 def test_call_with_dps(): mp.dps = 15 assert abs(exp(1, dps=30)-e(dps=35)) < 1e-29 def test_tanh(): mp.dps = 15 assert tanh(0) == 0 assert tanh(inf) == 1 assert tanh(-inf) == -1 assert isnan(tanh(nan)) assert tanh(mpc('inf', '0')) == 1 def test_atanh(): mp.dps = 15 assert atanh(0) == 0 assert atanh(0.5).ae(0.54930614433405484570) assert atanh(-0.5).ae(-0.54930614433405484570) assert atanh(1) == inf assert atanh(-1) == -inf assert isnan(atanh(nan)) assert isinstance(atanh(1), mpf) assert isinstance(atanh(-1), mpf) # Limits at infinity jpi2 = j*pi/2 assert atanh(inf).ae(-jpi2) assert atanh(-inf).ae(jpi2) assert atanh(mpc(inf,-1)).ae(-jpi2) assert atanh(mpc(inf,0)).ae(-jpi2) assert atanh(mpc(inf,1)).ae(jpi2) assert atanh(mpc(1,inf)).ae(jpi2) assert atanh(mpc(0,inf)).ae(jpi2) assert atanh(mpc(-1,inf)).ae(jpi2) assert atanh(mpc(-inf,1)).ae(jpi2) assert atanh(mpc(-inf,0)).ae(jpi2) assert atanh(mpc(-inf,-1)).ae(-jpi2) assert atanh(mpc(-1,-inf)).ae(-jpi2) assert atanh(mpc(0,-inf)).ae(-jpi2) assert atanh(mpc(1,-inf)).ae(-jpi2) def test_expm1(): mp.dps = 15 assert expm1(0) == 0 assert expm1(3).ae(exp(3)-1) assert expm1(inf) == inf assert expm1(1e-50).ae(1e-50) assert (expm1(1e-10)*1e10).ae(1.00000000005) def test_log1p(): mp.dps = 15 assert log1p(0) == 0 assert log1p(3).ae(log(1+3)) assert log1p(inf) == inf assert log1p(1e-50).ae(1e-50) assert (log1p(1e-10)*1e10).ae(0.99999999995) def test_powm1(): mp.dps = 15 assert powm1(2,3) == 7 assert powm1(-1,2) == 0 assert powm1(-1,0) == 0 assert powm1(-2,0) == 0 assert powm1(3+4j,0) == 0 assert powm1(0,1) == -1 assert powm1(0,0) == 0 assert powm1(1,0) == 0 assert powm1(1,2) == 0 assert powm1(1,3+4j) == 0 assert powm1(1,5) == 0 assert powm1(j,4) == 0 assert powm1(-j,4) == 0 assert (powm1(2,1e-100)*1e100).ae(ln2) assert powm1(2,'1e-100000000000') != 0 assert (powm1(fadd(1,1e-100,exact=True), 5)*1e100).ae(5) def test_unitroots(): assert unitroots(1) == [1] assert unitroots(2) == [1, -1] a, b, c = unitroots(3) assert a == 1 assert b.ae(-0.5 + 0.86602540378443864676j) assert c.ae(-0.5 - 0.86602540378443864676j) assert unitroots(1, primitive=True) == [1] assert unitroots(2, primitive=True) == [-1] assert unitroots(3, primitive=True) == unitroots(3)[1:] assert unitroots(4, primitive=True) == [j, -j] assert len(unitroots(17, primitive=True)) == 16 assert len(unitroots(16, primitive=True)) == 8 def test_cyclotomic(): mp.dps = 15 assert [cyclotomic(n,1) for n in range(31)] == [1,0,2,3,2,5,1,7,2,3,1,11,1,13,1,1,2,17,1,19,1,1,1,23,1,5,1,3,1,29,1] assert [cyclotomic(n,-1) for n in range(31)] == [1,-2,0,1,2,1,3,1,2,1,5,1,1,1,7,1,2,1,3,1,1,1,11,1,1,1,13,1,1,1,1] assert [cyclotomic(n,j) for n in range(21)] == [1,-1+j,1+j,j,0,1,-j,j,2,-j,1,j,3,1,-j,1,2,1,j,j,5] assert [cyclotomic(n,-j) for n in range(21)] == [1,-1-j,1-j,-j,0,1,j,-j,2,j,1,-j,3,1,j,1,2,1,-j,-j,5] assert cyclotomic(1624,j) == 1 assert cyclotomic(33600,j) == 1 u = sqrt(j, prec=500) assert cyclotomic(8, u).ae(0) assert cyclotomic(30, u).ae(5.8284271247461900976) assert cyclotomic(2040, u).ae(1) assert cyclotomic(0,2.5) == 1 assert cyclotomic(1,2.5) == 2.5-1 assert cyclotomic(2,2.5) == 2.5+1 assert cyclotomic(3,2.5) == 2.5**2 + 2.5 + 1 assert cyclotomic(7,2.5) == 406.234375 mpmath-1.1.0/mpmath/tests/test_functions2.py000066400000000000000000002753361340375245600211630ustar00rootroot00000000000000import math import pytest from mpmath import * def test_bessel(): mp.dps = 15 assert j0(1).ae(0.765197686557966551) assert j0(pi).ae(-0.304242177644093864) assert j0(1000).ae(0.0247866861524201746) assert j0(-25).ae(0.0962667832759581162) assert j1(1).ae(0.440050585744933516) assert j1(pi).ae(0.284615343179752757) assert j1(1000).ae(0.00472831190708952392) assert j1(-25).ae(0.125350249580289905) assert besselj(5,1).ae(0.000249757730211234431) assert besselj(5+0j,1).ae(0.000249757730211234431) assert besselj(5,pi).ae(0.0521411843671184747) assert besselj(5,1000).ae(0.00502540694523318607) assert besselj(5,-25).ae(0.0660079953984229934) assert besselj(-3,2).ae(-0.128943249474402051) assert besselj(-4,2).ae(0.0339957198075684341) assert besselj(3,3+2j).ae(0.424718794929639595942 + 0.625665327745785804812j) assert besselj(0.25,4).ae(-0.374760630804249715) assert besselj(1+2j,3+4j).ae(0.319247428741872131 - 0.669557748880365678j) assert (besselj(3, 10**10) * 10**5).ae(0.76765081748139204023) assert bessely(-0.5, 0) == 0 assert bessely(0.5, 0) == -inf assert bessely(1.5, 0) == -inf assert bessely(0,0) == -inf assert bessely(-0.4, 0) == -inf assert bessely(-0.6, 0) == inf assert bessely(-1, 0) == inf assert bessely(-1.4, 0) == inf assert bessely(-1.6, 0) == -inf assert bessely(-1, 0) == inf assert bessely(-2, 0) == -inf assert bessely(-3, 0) == inf assert bessely(0.5, 0) == -inf assert bessely(1, 0) == -inf assert bessely(1.5, 0) == -inf assert bessely(2, 0) == -inf assert bessely(2.5, 0) == -inf assert bessely(3, 0) == -inf assert bessely(0,0.5).ae(-0.44451873350670655715) assert bessely(1,0.5).ae(-1.4714723926702430692) assert bessely(-1,0.5).ae(1.4714723926702430692) assert bessely(3.5,0.5).ae(-138.86400867242488443) assert bessely(0,3+4j).ae(4.6047596915010138655-8.8110771408232264208j) assert bessely(0,j).ae(-0.26803248203398854876+1.26606587775200833560j) assert (bessely(3, 10**10) * 10**5).ae(0.21755917537013204058) assert besseli(0,0) == 1 assert besseli(1,0) == 0 assert besseli(2,0) == 0 assert besseli(-1,0) == 0 assert besseli(-2,0) == 0 assert besseli(0,0.5).ae(1.0634833707413235193) assert besseli(1,0.5).ae(0.25789430539089631636) assert besseli(-1,0.5).ae(0.25789430539089631636) assert besseli(3.5,0.5).ae(0.00068103597085793815863) assert besseli(0,3+4j).ae(-3.3924877882755196097-1.3239458916287264815j) assert besseli(0,j).ae(besselj(0,1)) assert (besseli(3, 10**10) * mpf(10)**(-4342944813)).ae(4.2996028505491271875) assert besselk(0,0) == inf assert besselk(1,0) == inf assert besselk(2,0) == inf assert besselk(-1,0) == inf assert besselk(-2,0) == inf assert besselk(0,0.5).ae(0.92441907122766586178) assert besselk(1,0.5).ae(1.6564411200033008937) assert besselk(-1,0.5).ae(1.6564411200033008937) assert besselk(3.5,0.5).ae(207.48418747548460607) assert besselk(0,3+4j).ae(-0.007239051213570155013+0.026510418350267677215j) assert besselk(0,j).ae(-0.13863371520405399968-1.20196971531720649914j) assert (besselk(3, 10**10) * mpf(10)**4342944824).ae(1.1628981033356187851) # test for issue 331, bug reported by Michael Hartmann for n in range(10,100,10): mp.dps = n assert besseli(91.5,24.7708).ae("4.00830632138673963619656140653537080438462342928377020695738635559218797348548092636896796324190271316137982810144874264e-41") def test_bessel_zeros(): mp.dps = 15 assert besseljzero(0,1).ae(2.40482555769577276869) assert besseljzero(2,1).ae(5.1356223018406825563) assert besseljzero(1,50).ae(157.86265540193029781) assert besseljzero(10,1).ae(14.475500686554541220) assert besseljzero(0.5,3).ae(9.4247779607693797153) assert besseljzero(2,1,1).ae(3.0542369282271403228) assert besselyzero(0,1).ae(0.89357696627916752158) assert besselyzero(2,1).ae(3.3842417671495934727) assert besselyzero(1,50).ae(156.29183520147840108) assert besselyzero(10,1).ae(12.128927704415439387) assert besselyzero(0.5,3).ae(7.8539816339744830962) assert besselyzero(2,1,1).ae(5.0025829314460639452) def test_hankel(): mp.dps = 15 assert hankel1(0,0.5).ae(0.93846980724081290423-0.44451873350670655715j) assert hankel1(1,0.5).ae(0.2422684576748738864-1.4714723926702430692j) assert hankel1(-1,0.5).ae(-0.2422684576748738864+1.4714723926702430692j) assert hankel1(1.5,0.5).ae(0.0917016996256513026-2.5214655504213378514j) assert hankel1(1.5,3+4j).ae(0.0066806866476728165382-0.0036684231610839127106j) assert hankel2(0,0.5).ae(0.93846980724081290423+0.44451873350670655715j) assert hankel2(1,0.5).ae(0.2422684576748738864+1.4714723926702430692j) assert hankel2(-1,0.5).ae(-0.2422684576748738864-1.4714723926702430692j) assert hankel2(1.5,0.5).ae(0.0917016996256513026+2.5214655504213378514j) assert hankel2(1.5,3+4j).ae(14.783528526098567526-7.397390270853446512j) def test_struve(): mp.dps = 15 assert struveh(2,3).ae(0.74238666967748318564) assert struveh(-2.5,3).ae(0.41271003220971599344) assert struvel(2,3).ae(1.7476573277362782744) assert struvel(-2.5,3).ae(1.5153394466819651377) def test_whittaker(): mp.dps = 15 assert whitm(2,3,4).ae(49.753745589025246591) assert whitw(2,3,4).ae(14.111656223052932215) def test_kelvin(): mp.dps = 15 assert ber(2,3).ae(0.80836846563726819091) assert ber(3,4).ae(-0.28262680167242600233) assert ber(-3,2).ae(-0.085611448496796363669) assert bei(2,3).ae(-0.89102236377977331571) assert bei(-3,2).ae(-0.14420994155731828415) assert ker(2,3).ae(0.12839126695733458928) assert ker(-3,2).ae(-0.29802153400559142783) assert ker(0.5,3).ae(-0.085662378535217097524) assert kei(2,3).ae(0.036804426134164634000) assert kei(-3,2).ae(0.88682069845786731114) assert kei(0.5,3).ae(0.013633041571314302948) def test_hyper_misc(): mp.dps = 15 assert hyp0f1(1,0) == 1 assert hyp1f1(1,2,0) == 1 assert hyp1f2(1,2,3,0) == 1 assert hyp2f1(1,2,3,0) == 1 assert hyp2f2(1,2,3,4,0) == 1 assert hyp2f3(1,2,3,4,5,0) == 1 # Degenerate case: 0F0 assert hyper([],[],0) == 1 assert hyper([],[],-2).ae(exp(-2)) # Degenerate case: 1F0 assert hyper([2],[],1.5) == 4 # assert hyp2f1((1,3),(2,3),(5,6),mpf(27)/32).ae(1.6) assert hyp2f1((1,4),(1,2),(3,4),mpf(80)/81).ae(1.8) assert hyp2f1((2,3),(1,1),(3,2),(2+j)/3).ae(1.327531603558679093+0.439585080092769253j) mp.dps = 25 v = mpc('1.2282306665029814734863026', '-0.1225033830118305184672133') assert hyper([(3,4),2+j,1],[1,5,j/3],mpf(1)/5+j/8).ae(v) mp.dps = 15 def test_elliptic_integrals(): mp.dps = 15 assert ellipk(0).ae(pi/2) assert ellipk(0.5).ae(gamma(0.25)**2/(4*sqrt(pi))) assert ellipk(1) == inf assert ellipk(1+0j) == inf assert ellipk(-1).ae('1.3110287771460599052') assert ellipk(-2).ae('1.1714200841467698589') assert isinstance(ellipk(-2), mpf) assert isinstance(ellipe(-2), mpf) assert ellipk(-50).ae('0.47103424540873331679') mp.dps = 30 n1 = +fraction(99999,100000) n2 = +fraction(100001,100000) mp.dps = 15 assert ellipk(n1).ae('7.1427724505817781901') assert ellipk(n2).ae(mpc('7.1427417367963090109', '-1.5707923998261688019')) assert ellipe(n1).ae('1.0000332138990829170') v = ellipe(n2) assert v.real.ae('0.999966786328145474069137') assert (v.imag*10**6).ae('7.853952181727432') assert ellipk(2).ae(mpc('1.3110287771460599052', '-1.3110287771460599052')) assert ellipk(50).ae(mpc('0.22326753950210985451', '-0.47434723226254522087')) assert ellipk(3+4j).ae(mpc('0.91119556380496500866', '0.63133428324134524388')) assert ellipk(3-4j).ae(mpc('0.91119556380496500866', '-0.63133428324134524388')) assert ellipk(-3+4j).ae(mpc('0.95357894880405122483', '0.23093044503746114444')) assert ellipk(-3-4j).ae(mpc('0.95357894880405122483', '-0.23093044503746114444')) assert isnan(ellipk(nan)) assert isnan(ellipe(nan)) assert ellipk(inf) == 0 assert isinstance(ellipk(inf), mpc) assert ellipk(-inf) == 0 assert ellipk(1+0j) == inf assert ellipe(0).ae(pi/2) assert ellipe(0.5).ae(pi**(mpf(3)/2)/gamma(0.25)**2 +gamma(0.25)**2/(8*sqrt(pi))) assert ellipe(1) == 1 assert ellipe(1+0j) == 1 assert ellipe(inf) == mpc(0,inf) assert ellipe(-inf) == inf assert ellipe(3+4j).ae(1.4995535209333469543-1.5778790079127582745j) assert ellipe(3-4j).ae(1.4995535209333469543+1.5778790079127582745j) assert ellipe(-3+4j).ae(2.5804237855343377803-0.8306096791000413778j) assert ellipe(-3-4j).ae(2.5804237855343377803+0.8306096791000413778j) assert ellipe(2).ae(0.59907011736779610372+0.59907011736779610372j) assert ellipe('1e-1000000000').ae(pi/2) assert ellipk('1e-1000000000').ae(pi/2) assert ellipe(-pi).ae(2.4535865983838923) mp.dps = 50 assert ellipk(1/pi).ae('1.724756270009501831744438120951614673874904182624739673') assert ellipe(1/pi).ae('1.437129808135123030101542922290970050337425479058225712') assert ellipk(-10*pi).ae('0.5519067523886233967683646782286965823151896970015484512') assert ellipe(-10*pi).ae('5.926192483740483797854383268707108012328213431657645509') v = ellipk(pi) assert v.real.ae('0.973089521698042334840454592642137667227167622330325225') assert v.imag.ae('-1.156151296372835303836814390793087600271609993858798016') v = ellipe(pi) assert v.real.ae('0.4632848917264710404078033487934663562998345622611263332') assert v.imag.ae('1.0637961621753130852473300451583414489944099504180510966') mp.dps = 15 def test_exp_integrals(): mp.dps = 15 x = +e z = e + sqrt(3)*j assert ei(x).ae(8.21168165538361560) assert li(x).ae(1.89511781635593676) assert si(x).ae(1.82104026914756705) assert ci(x).ae(0.213958001340379779) assert shi(x).ae(4.11520706247846193) assert chi(x).ae(4.09647459290515367) assert fresnels(x).ae(0.437189718149787643) assert fresnelc(x).ae(0.401777759590243012) assert airyai(x).ae(0.0108502401568586681) assert airybi(x).ae(8.98245748585468627) assert ei(z).ae(3.72597969491314951 + 7.34213212314224421j) assert li(z).ae(2.28662658112562502 + 1.50427225297269364j) assert si(z).ae(2.48122029237669054 + 0.12684703275254834j) assert ci(z).ae(0.169255590269456633 - 0.892020751420780353j) assert shi(z).ae(1.85810366559344468 + 3.66435842914920263j) assert chi(z).ae(1.86787602931970484 + 3.67777369399304159j) assert fresnels(z/3).ae(0.034534397197008182 + 0.754859844188218737j) assert fresnelc(z/3).ae(1.261581645990027372 + 0.417949198775061893j) assert airyai(z).ae(-0.0162552579839056062 - 0.0018045715700210556j) assert airybi(z).ae(-4.98856113282883371 + 2.08558537872180623j) assert li(0) == 0.0 assert li(1) == -inf assert li(inf) == inf assert isinstance(li(0.7), mpf) assert si(inf).ae(pi/2) assert si(-inf).ae(-pi/2) assert ci(inf) == 0 assert ci(0) == -inf assert isinstance(ei(-0.7), mpf) assert airyai(inf) == 0 assert airybi(inf) == inf assert airyai(-inf) == 0 assert airybi(-inf) == 0 assert fresnels(inf) == 0.5 assert fresnelc(inf) == 0.5 assert fresnels(-inf) == -0.5 assert fresnelc(-inf) == -0.5 assert shi(0) == 0 assert shi(inf) == inf assert shi(-inf) == -inf assert chi(0) == -inf assert chi(inf) == inf def test_ei(): mp.dps = 15 assert ei(0) == -inf assert ei(inf) == inf assert ei(-inf) == -0.0 assert ei(20+70j).ae(6.1041351911152984397e6 - 2.7324109310519928872e6j) # tests for the asymptotic expansion # values checked with Mathematica ExpIntegralEi mp.dps = 50 r = ei(20000) s = '3.8781962825045010930273870085501819470698476975019e+8681' assert str(r) == s r = ei(-200) s = '-6.8852261063076355977108174824557929738368086933303e-90' assert str(r) == s r =ei(20000 + 10*j) sre = '-3.255138234032069402493850638874410725961401274106e+8681' sim = '-2.1081929993474403520785942429469187647767369645423e+8681' assert str(r.real) == sre and str(r.imag) == sim mp.dps = 15 # More asymptotic expansions assert chi(-10**6+100j).ae('1.3077239389562548386e+434288 + 7.6808956999707408158e+434287j') assert shi(-10**6+100j).ae('-1.3077239389562548386e+434288 - 7.6808956999707408158e+434287j') mp.dps = 15 assert ei(10j).ae(-0.0454564330044553726+3.2291439210137706686j) assert ei(100j).ae(-0.0051488251426104921+3.1330217936839529126j) u = ei(fmul(10**20, j, exact=True)) assert u.real.ae(-6.4525128526578084421345e-21, abs_eps=0, rel_eps=8*eps) assert u.imag.ae(pi) assert ei(-10j).ae(-0.0454564330044553726-3.2291439210137706686j) assert ei(-100j).ae(-0.0051488251426104921-3.1330217936839529126j) u = ei(fmul(-10**20, j, exact=True)) assert u.real.ae(-6.4525128526578084421345e-21, abs_eps=0, rel_eps=8*eps) assert u.imag.ae(-pi) assert ei(10+10j).ae(-1576.1504265768517448+436.9192317011328140j) u = ei(-10+10j) assert u.real.ae(7.6698978415553488362543e-7, abs_eps=0, rel_eps=8*eps) assert u.imag.ae(3.141595611735621062025) def test_e1(): mp.dps = 15 assert e1(0) == inf assert e1(inf) == 0 assert e1(-inf) == mpc(-inf, -pi) assert e1(10j).ae(0.045456433004455372635 + 0.087551267423977430100j) assert e1(100j).ae(0.0051488251426104921444 - 0.0085708599058403258790j) assert e1(fmul(10**20, j, exact=True)).ae(6.4525128526578084421e-21 - 7.6397040444172830039e-21j, abs_eps=0, rel_eps=8*eps) assert e1(-10j).ae(0.045456433004455372635 - 0.087551267423977430100j) assert e1(-100j).ae(0.0051488251426104921444 + 0.0085708599058403258790j) assert e1(fmul(-10**20, j, exact=True)).ae(6.4525128526578084421e-21 + 7.6397040444172830039e-21j, abs_eps=0, rel_eps=8*eps) def test_expint(): mp.dps = 15 assert expint(0,0) == inf assert expint(0,1).ae(1/e) assert expint(0,1.5).ae(2/exp(1.5)/3) assert expint(1,1).ae(-ei(-1)) assert expint(2,0).ae(1) assert expint(3,0).ae(1/2.) assert expint(4,0).ae(1/3.) assert expint(-2, 0.5).ae(26/sqrt(e)) assert expint(-1,-1) == 0 assert expint(-2,-1).ae(-e) assert expint(5.5, 0).ae(2/9.) assert expint(2.00000001,0).ae(100000000./100000001) assert expint(2+3j,4-j).ae(0.0023461179581675065414+0.0020395540604713669262j) assert expint('1.01', '1e-1000').ae(99.9999999899412802) assert expint('1.000000000001', 3.5).ae(0.00697013985754701819446) assert expint(2,3).ae(3*ei(-3)+exp(-3)) assert (expint(10,20)*10**10).ae(0.694439055541231353) assert expint(3,inf) == 0 assert expint(3.2,inf) == 0 assert expint(3.2+2j,inf) == 0 assert expint(1,3j).ae(-0.11962978600800032763 + 0.27785620120457163717j) assert expint(1,3).ae(0.013048381094197037413) assert expint(1,-3).ae(-ei(3)-pi*j) #assert expint(3) == expint(1,3) assert expint(1,-20).ae(-25615652.66405658882 - 3.1415926535897932385j) assert expint(1000000,0).ae(1./999999) assert expint(0,2+3j).ae(-0.025019798357114678171 + 0.027980439405104419040j) assert expint(-1,2+3j).ae(-0.022411973626262070419 + 0.038058922011377716932j) assert expint(-1.5,0) == inf def test_trig_integrals(): mp.dps = 30 assert si(mpf(1)/1000000).ae('0.000000999999999999944444444444446111') assert ci(mpf(1)/1000000).ae('-13.2382948930629912435014366276') assert si(10**10).ae('1.5707963267075846569685111517747537') assert ci(10**10).ae('-4.87506025174822653785729773959e-11') assert si(10**100).ae(pi/2) assert (ci(10**100)*10**100).ae('-0.372376123661276688262086695553') assert si(-3) == -si(3) assert ci(-3).ae(ci(3) + pi*j) # Test complex structure mp.dps = 15 assert mp.ci(50).ae(-0.0056283863241163054402) assert mp.ci(50+2j).ae(-0.018378282946133067149+0.070352808023688336193j) assert mp.ci(20j).ae(1.28078263320282943611e7+1.5707963267949j) assert mp.ci(-2+20j).ae(-4.050116856873293505e6+1.207476188206989909e7j) assert mp.ci(-50+2j).ae(-0.0183782829461330671+3.0712398455661049023j) assert mp.ci(-50).ae(-0.0056283863241163054+3.1415926535897932385j) assert mp.ci(-50-2j).ae(-0.0183782829461330671-3.0712398455661049023j) assert mp.ci(-2-20j).ae(-4.050116856873293505e6-1.207476188206989909e7j) assert mp.ci(-20j).ae(1.28078263320282943611e7-1.5707963267949j) assert mp.ci(50-2j).ae(-0.018378282946133067149-0.070352808023688336193j) assert mp.si(50).ae(1.5516170724859358947) assert mp.si(50+2j).ae(1.497884414277228461-0.017515007378437448j) assert mp.si(20j).ae(1.2807826332028294459e7j) assert mp.si(-2+20j).ae(-1.20747603112735722103e7-4.050116856873293554e6j) assert mp.si(-50+2j).ae(-1.497884414277228461-0.017515007378437448j) assert mp.si(-50).ae(-1.5516170724859358947) assert mp.si(-50-2j).ae(-1.497884414277228461+0.017515007378437448j) assert mp.si(-2-20j).ae(-1.20747603112735722103e7+4.050116856873293554e6j) assert mp.si(-20j).ae(-1.2807826332028294459e7j) assert mp.si(50-2j).ae(1.497884414277228461+0.017515007378437448j) assert mp.chi(50j).ae(-0.0056283863241163054+1.5707963267948966192j) assert mp.chi(-2+50j).ae(-0.0183782829461330671+1.6411491348185849554j) assert mp.chi(-20).ae(1.28078263320282943611e7+3.1415926535898j) assert mp.chi(-20-2j).ae(-4.050116856873293505e6+1.20747571696809187053e7j) assert mp.chi(-2-50j).ae(-0.0183782829461330671-1.6411491348185849554j) assert mp.chi(-50j).ae(-0.0056283863241163054-1.5707963267948966192j) assert mp.chi(2-50j).ae(-0.0183782829461330671-1.500443518771208283j) assert mp.chi(20-2j).ae(-4.050116856873293505e6-1.20747603112735722951e7j) assert mp.chi(20).ae(1.2807826332028294361e7) assert mp.chi(2+50j).ae(-0.0183782829461330671+1.500443518771208283j) assert mp.shi(50j).ae(1.5516170724859358947j) assert mp.shi(-2+50j).ae(0.017515007378437448+1.497884414277228461j) assert mp.shi(-20).ae(-1.2807826332028294459e7) assert mp.shi(-20-2j).ae(4.050116856873293554e6-1.20747603112735722103e7j) assert mp.shi(-2-50j).ae(0.017515007378437448-1.497884414277228461j) assert mp.shi(-50j).ae(-1.5516170724859358947j) assert mp.shi(2-50j).ae(-0.017515007378437448-1.497884414277228461j) assert mp.shi(20-2j).ae(-4.050116856873293554e6-1.20747603112735722103e7j) assert mp.shi(20).ae(1.2807826332028294459e7) assert mp.shi(2+50j).ae(-0.017515007378437448+1.497884414277228461j) def ae(x,y,tol=1e-12): return abs(x-y) <= abs(y)*tol assert fp.ci(fp.inf) == 0 assert ae(fp.ci(fp.ninf), fp.pi*1j) assert ae(fp.si(fp.inf), fp.pi/2) assert ae(fp.si(fp.ninf), -fp.pi/2) assert fp.si(0) == 0 assert ae(fp.ci(50), -0.0056283863241163054402) assert ae(fp.ci(50+2j), -0.018378282946133067149+0.070352808023688336193j) assert ae(fp.ci(20j), 1.28078263320282943611e7+1.5707963267949j) assert ae(fp.ci(-2+20j), -4.050116856873293505e6+1.207476188206989909e7j) assert ae(fp.ci(-50+2j), -0.0183782829461330671+3.0712398455661049023j) assert ae(fp.ci(-50), -0.0056283863241163054+3.1415926535897932385j) assert ae(fp.ci(-50-2j), -0.0183782829461330671-3.0712398455661049023j) assert ae(fp.ci(-2-20j), -4.050116856873293505e6-1.207476188206989909e7j) assert ae(fp.ci(-20j), 1.28078263320282943611e7-1.5707963267949j) assert ae(fp.ci(50-2j), -0.018378282946133067149-0.070352808023688336193j) assert ae(fp.si(50), 1.5516170724859358947) assert ae(fp.si(50+2j), 1.497884414277228461-0.017515007378437448j) assert ae(fp.si(20j), 1.2807826332028294459e7j) assert ae(fp.si(-2+20j), -1.20747603112735722103e7-4.050116856873293554e6j) assert ae(fp.si(-50+2j), -1.497884414277228461-0.017515007378437448j) assert ae(fp.si(-50), -1.5516170724859358947) assert ae(fp.si(-50-2j), -1.497884414277228461+0.017515007378437448j) assert ae(fp.si(-2-20j), -1.20747603112735722103e7+4.050116856873293554e6j) assert ae(fp.si(-20j), -1.2807826332028294459e7j) assert ae(fp.si(50-2j), 1.497884414277228461+0.017515007378437448j) assert ae(fp.chi(50j), -0.0056283863241163054+1.5707963267948966192j) assert ae(fp.chi(-2+50j), -0.0183782829461330671+1.6411491348185849554j) assert ae(fp.chi(-20), 1.28078263320282943611e7+3.1415926535898j) assert ae(fp.chi(-20-2j), -4.050116856873293505e6+1.20747571696809187053e7j) assert ae(fp.chi(-2-50j), -0.0183782829461330671-1.6411491348185849554j) assert ae(fp.chi(-50j), -0.0056283863241163054-1.5707963267948966192j) assert ae(fp.chi(2-50j), -0.0183782829461330671-1.500443518771208283j) assert ae(fp.chi(20-2j), -4.050116856873293505e6-1.20747603112735722951e7j) assert ae(fp.chi(20), 1.2807826332028294361e7) assert ae(fp.chi(2+50j), -0.0183782829461330671+1.500443518771208283j) assert ae(fp.shi(50j), 1.5516170724859358947j) assert ae(fp.shi(-2+50j), 0.017515007378437448+1.497884414277228461j) assert ae(fp.shi(-20), -1.2807826332028294459e7) assert ae(fp.shi(-20-2j), 4.050116856873293554e6-1.20747603112735722103e7j) assert ae(fp.shi(-2-50j), 0.017515007378437448-1.497884414277228461j) assert ae(fp.shi(-50j), -1.5516170724859358947j) assert ae(fp.shi(2-50j), -0.017515007378437448-1.497884414277228461j) assert ae(fp.shi(20-2j), -4.050116856873293554e6-1.20747603112735722103e7j) assert ae(fp.shi(20), 1.2807826332028294459e7) assert ae(fp.shi(2+50j), -0.017515007378437448+1.497884414277228461j) def test_airy(): mp.dps = 15 assert (airyai(10)*10**10).ae(1.1047532552898687) assert (airybi(10)/10**9).ae(0.45564115354822515) assert (airyai(1000)*10**9158).ae(9.306933063179556004) assert (airybi(1000)/10**9154).ae(5.4077118391949465477) assert airyai(-1000).ae(0.055971895773019918842) assert airybi(-1000).ae(-0.083264574117080633012) assert (airyai(100+100j)*10**188).ae(2.9099582462207032076 + 2.353013591706178756j) assert (airybi(100+100j)/10**185).ae(1.7086751714463652039 - 3.1416590020830804578j) def test_hyper_0f1(): mp.dps = 15 v = 8.63911136507950465 assert hyper([],[(1,3)],1.5).ae(v) assert hyper([],[1/3.],1.5).ae(v) assert hyp0f1(1/3.,1.5).ae(v) assert hyp0f1((1,3),1.5).ae(v) # Asymptotic expansion assert hyp0f1(3,1e9).ae('4.9679055380347771271e+27455') assert hyp0f1(3,1e9j).ae('-2.1222788784457702157e+19410 + 5.0840597555401854116e+19410j') def test_hyper_1f1(): mp.dps = 15 v = 1.2917526488617656673 assert hyper([(1,2)],[(3,2)],0.7).ae(v) assert hyper([(1,2)],[(3,2)],0.7+0j).ae(v) assert hyper([0.5],[(3,2)],0.7).ae(v) assert hyper([0.5],[1.5],0.7).ae(v) assert hyper([0.5],[(3,2)],0.7+0j).ae(v) assert hyper([0.5],[1.5],0.7+0j).ae(v) assert hyper([(1,2)],[1.5+0j],0.7).ae(v) assert hyper([0.5+0j],[1.5],0.7).ae(v) assert hyper([0.5+0j],[1.5+0j],0.7+0j).ae(v) assert hyp1f1(0.5,1.5,0.7).ae(v) assert hyp1f1((1,2),1.5,0.7).ae(v) # Asymptotic expansion assert hyp1f1(2,3,1e10).ae('2.1555012157015796988e+4342944809') assert (hyp1f1(2,3,1e10j)*10**10).ae(-0.97501205020039745852 - 1.7462392454512132074j) # Shouldn't use asymptotic expansion assert hyp1f1(-2, 1, 10000).ae(49980001) # Bug assert hyp1f1(1j,fraction(1,3),0.415-69.739j).ae(25.857588206024346592 + 15.738060264515292063j) def test_hyper_2f1(): mp.dps = 15 v = 1.0652207633823291032 assert hyper([(1,2), (3,4)], [2], 0.3).ae(v) assert hyper([(1,2), 0.75], [2], 0.3).ae(v) assert hyper([0.5, 0.75], [2.0], 0.3).ae(v) assert hyper([0.5, 0.75], [2.0], 0.3+0j).ae(v) assert hyper([0.5+0j, (3,4)], [2.0], 0.3+0j).ae(v) assert hyper([0.5+0j, (3,4)], [2.0], 0.3).ae(v) assert hyper([0.5, (3,4)], [2.0+0j], 0.3).ae(v) assert hyper([0.5+0j, 0.75+0j], [2.0+0j], 0.3+0j).ae(v) v = 1.09234681096223231717 + 0.18104859169479360380j assert hyper([(1,2),0.75+j], [2], 0.5).ae(v) assert hyper([0.5,0.75+j], [2.0], 0.5).ae(v) assert hyper([0.5,0.75+j], [2.0], 0.5+0j).ae(v) assert hyper([0.5,0.75+j], [2.0+0j], 0.5+0j).ae(v) v = 0.9625 - 0.125j assert hyper([(3,2),-1],[4], 0.1+j/3).ae(v) assert hyper([1.5,-1.0],[4], 0.1+j/3).ae(v) assert hyper([1.5,-1.0],[4+0j], 0.1+j/3).ae(v) assert hyper([1.5+0j,-1.0+0j],[4+0j], 0.1+j/3).ae(v) v = 1.02111069501693445001 - 0.50402252613466859521j assert hyper([(2,10),(3,10)],[(4,10)],1.5).ae(v) assert hyper([0.2,(3,10)],[0.4+0j],1.5).ae(v) assert hyper([0.2,(3,10)],[0.4+0j],1.5+0j).ae(v) v = 0.76922501362865848528 + 0.32640579593235886194j assert hyper([(2,10),(3,10)],[(4,10)],4+2j).ae(v) assert hyper([0.2,(3,10)],[0.4+0j],4+2j).ae(v) assert hyper([0.2,(3,10)],[(4,10)],4+2j).ae(v) def test_hyper_2f1_hard(): mp.dps = 15 # Singular cases assert hyp2f1(2,-1,-1,3).ae(7) assert hyp2f1(2,-1,-1,3,eliminate_all=True).ae(0.25) assert hyp2f1(2,-2,-2,3).ae(34) assert hyp2f1(2,-2,-2,3,eliminate_all=True).ae(0.25) assert hyp2f1(2,-2,-3,3) == 14 assert hyp2f1(2,-3,-2,3) == inf assert hyp2f1(2,-1.5,-1.5,3) == 0.25 assert hyp2f1(1,2,3,0) == 1 assert hyp2f1(0,1,0,0) == 1 assert hyp2f1(0,0,0,0) == 1 assert isnan(hyp2f1(1,1,0,0)) assert hyp2f1(2,-1,-5, 0.25+0.25j).ae(1.1+0.1j) assert hyp2f1(2,-5,-5, 0.25+0.25j, eliminate=False).ae(163./128 + 125./128*j) assert hyp2f1(0.7235, -1, -5, 0.3).ae(1.04341) assert hyp2f1(0.7235, -5, -5, 0.3, eliminate=False).ae(1.2939225017815903812) assert hyp2f1(-1,-2,4,1) == 1.5 assert hyp2f1(1,2,-3,1) == inf assert hyp2f1(-2,-2,1,1) == 6 assert hyp2f1(1,-2,-4,1).ae(5./3) assert hyp2f1(0,-6,-4,1) == 1 assert hyp2f1(0,-3,-4,1) == 1 assert hyp2f1(0,0,0,1) == 1 assert hyp2f1(1,0,0,1,eliminate=False) == 1 assert hyp2f1(1,1,0,1) == inf assert hyp2f1(1,-6,-4,1) == inf assert hyp2f1(-7.2,-0.5,-4.5,1) == 0 assert hyp2f1(-7.2,-1,-2,1).ae(-2.6) assert hyp2f1(1,-0.5,-4.5, 1) == inf assert hyp2f1(1,0.5,-4.5, 1) == -inf # Check evaluation on / close to unit circle z = exp(j*pi/3) w = (nthroot(2,3)+1)*exp(j*pi/12)/nthroot(3,4)**3 assert hyp2f1('1/2','1/6','1/3', z).ae(w) assert hyp2f1('1/2','1/6','1/3', z.conjugate()).ae(w.conjugate()) assert hyp2f1(0.25, (1,3), 2, '0.999').ae(1.06826449496030635) assert hyp2f1(0.25, (1,3), 2, '1.001').ae(1.06867299254830309446-0.00001446586793975874j) assert hyp2f1(0.25, (1,3), 2, -1).ae(0.96656584492524351673) assert hyp2f1(0.25, (1,3), 2, j).ae(0.99041766248982072266+0.03777135604180735522j) assert hyp2f1(2,3,5,'0.99').ae(27.699347904322690602) assert hyp2f1((3,2),-0.5,3,'0.99').ae(0.68403036843911661388) assert hyp2f1(2,3,5,1j).ae(0.37290667145974386127+0.59210004902748285917j) assert fsum([hyp2f1((7,10),(2,3),(-1,2), 0.95*exp(j*k)) for k in range(1,15)]).ae(52.851400204289452922+6.244285013912953225j) assert fsum([hyp2f1((7,10),(2,3),(-1,2), 1.05*exp(j*k)) for k in range(1,15)]).ae(54.506013786220655330-3.000118813413217097j) assert fsum([hyp2f1((7,10),(2,3),(-1,2), exp(j*k)) for k in range(1,15)]).ae(55.792077935955314887+1.731986485778500241j) assert hyp2f1(2,2.5,-3.25,0.999).ae(218373932801217082543180041.33) # Branches assert hyp2f1(1,1,2,1.01).ae(4.5595744415723676911-3.1104877758314784539j) assert hyp2f1(1,1,2,1.01+0.1j).ae(2.4149427480552782484+1.4148224796836938829j) assert hyp2f1(1,1,2,3+4j).ae(0.14576709331407297807+0.48379185417980360773j) assert hyp2f1(1,1,2,4).ae(-0.27465307216702742285 - 0.78539816339744830962j) assert hyp2f1(1,1,2,-4).ae(0.40235947810852509365) # Other: # Cancellation with a large parameter involved (bug reported on sage-devel) assert hyp2f1(112, (51,10), (-9,10), -0.99999).ae(-1.6241361047970862961e-24, abs_eps=0, rel_eps=eps*16) def test_hyper_3f2_etc(): assert hyper([1,2,3],[1.5,8],-1).ae(0.67108992351533333030) assert hyper([1,2,3,4],[5,6,7], -1).ae(0.90232988035425506008) assert hyper([1,2,3],[1.25,5], 1).ae(28.924181329701905701) assert hyper([1,2,3,4],[5,6,7],5).ae(1.5192307344006649499-1.1529845225075537461j) assert hyper([1,2,3,4,5],[6,7,8,9],-1).ae(0.96288759462882357253) assert hyper([1,2,3,4,5],[6,7,8,9],1).ae(1.0428697385885855841) assert hyper([1,2,3,4,5],[6,7,8,9],5).ae(1.33980653631074769423-0.07143405251029226699j) assert hyper([1,2.79,3.08,4.37],[5.2,6.1,7.3],5).ae(1.0996321464692607231-1.7748052293979985001j) assert hyper([1,1,1],[1,2],1) == inf assert hyper([1,1,1],[2,(101,100)],1).ae(100.01621213528313220) # slow -- covered by doctests #assert hyper([1,1,1],[2,3],0.9999).ae(1.2897972005319693905) def test_hyper_u(): mp.dps = 15 assert hyperu(2,-3,0).ae(0.05) assert hyperu(2,-3.5,0).ae(4./99) assert hyperu(2,0,0) == 0.5 assert hyperu(-5,1,0) == -120 assert hyperu(-5,2,0) == inf assert hyperu(-5,-2,0) == 0 assert hyperu(7,7,3).ae(0.00014681269365593503986) #exp(3)*gammainc(-6,3) assert hyperu(2,-3,4).ae(0.011836478100271995559) assert hyperu(3,4,5).ae(1./125) assert hyperu(2,3,0.0625) == 256 assert hyperu(-1,2,0.25+0.5j) == -1.75+0.5j assert hyperu(0.5,1.5,7.25).ae(2/sqrt(29)) assert hyperu(2,6,pi).ae(0.55804439825913399130) assert (hyperu((3,2),8,100+201j)*10**4).ae(-0.3797318333856738798 - 2.9974928453561707782j) assert (hyperu((5,2),(-1,2),-5000)*10**10).ae(-5.6681877926881664678j) # XXX: fails because of undetected cancellation in low level series code # Alternatively: could use asymptotic series here, if convergence test # tweaked back to recognize this one #assert (hyperu((5,2),(-1,2),-500)*10**7).ae(-1.82526906001593252847j) def test_hyper_2f0(): mp.dps = 15 assert hyper([1,2],[],3) == hyp2f0(1,2,3) assert hyp2f0(2,3,7).ae(0.0116108068639728714668 - 0.0073727413865865802130j) assert hyp2f0(2,3,0) == 1 assert hyp2f0(0,0,0) == 1 assert hyp2f0(-1,-1,1).ae(2) assert hyp2f0(-4,1,1.5).ae(62.5) assert hyp2f0(-4,1,50).ae(147029801) assert hyp2f0(-4,1,0.0001).ae(0.99960011997600240000) assert hyp2f0(0.5,0.25,0.001).ae(1.0001251174078538115) assert hyp2f0(0.5,0.25,3+4j).ae(0.85548875824755163518 + 0.21636041283392292973j) # Important: cancellation check assert hyp2f0((1,6),(5,6),-0.02371708245126284498).ae(0.996785723120804309) # Should be exact; polynomial case assert hyp2f0(-2,1,0.5+0.5j,zeroprec=200) == 0 assert hyp2f0(1,-2,0.5+0.5j,zeroprec=200) == 0 # There used to be a bug in thresholds that made one of the following hang for d in [15, 50, 80]: mp.dps = d assert hyp2f0(1.5, 0.5, 0.009).ae('1.006867007239309717945323585695344927904000945829843527398772456281301440034218290443367270629519483 + 1.238277162240704919639384945859073461954721356062919829456053965502443570466701567100438048602352623e-46j') def test_hyper_1f2(): mp.dps = 15 assert hyper([1],[2,3],4) == hyp1f2(1,2,3,4) a1,b1,b2 = (1,10),(2,3),1./16 assert hyp1f2(a1,b1,b2,10).ae(298.7482725554557568) assert hyp1f2(a1,b1,b2,100).ae(224128961.48602947604) assert hyp1f2(a1,b1,b2,1000).ae(1.1669528298622675109e+27) assert hyp1f2(a1,b1,b2,10000).ae(2.4780514622487212192e+86) assert hyp1f2(a1,b1,b2,100000).ae(1.3885391458871523997e+274) assert hyp1f2(a1,b1,b2,1000000).ae('9.8851796978960318255e+867') assert hyp1f2(a1,b1,b2,10**7).ae('1.1505659189516303646e+2746') assert hyp1f2(a1,b1,b2,10**8).ae('1.4672005404314334081e+8685') assert hyp1f2(a1,b1,b2,10**20).ae('3.6888217332150976493e+8685889636') assert hyp1f2(a1,b1,b2,10*j).ae(-16.163252524618572878 - 44.321567896480184312j) assert hyp1f2(a1,b1,b2,100*j).ae(61938.155294517848171 + 637349.45215942348739j) assert hyp1f2(a1,b1,b2,1000*j).ae(8455057657257695958.7 + 6261969266997571510.6j) assert hyp1f2(a1,b1,b2,10000*j).ae(-8.9771211184008593089e+60 + 4.6550528111731631456e+59j) assert hyp1f2(a1,b1,b2,100000*j).ae(2.6398091437239324225e+193 + 4.1658080666870618332e+193j) assert hyp1f2(a1,b1,b2,1000000*j).ae('3.5999042951925965458e+613 + 1.5026014707128947992e+613j') assert hyp1f2(a1,b1,b2,10**7*j).ae('-8.3208715051623234801e+1939 - 3.6752883490851869429e+1941j') assert hyp1f2(a1,b1,b2,10**8*j).ae('2.0724195707891484454e+6140 - 1.3276619482724266387e+6141j') assert hyp1f2(a1,b1,b2,10**20*j).ae('-1.1734497974795488504e+6141851462 + 1.1498106965385471542e+6141851462j') def test_hyper_2f3(): mp.dps = 15 assert hyper([1,2],[3,4,5],6) == hyp2f3(1,2,3,4,5,6) a1,a2,b1,b2,b3 = (1,10),(2,3),(3,10), 2, 1./16 # Check asymptotic expansion assert hyp2f3(a1,a2,b1,b2,b3,10).ae(128.98207160698659976) assert hyp2f3(a1,a2,b1,b2,b3,1000).ae(6.6309632883131273141e25) assert hyp2f3(a1,a2,b1,b2,b3,10000).ae(4.6863639362713340539e84) assert hyp2f3(a1,a2,b1,b2,b3,100000).ae(8.6632451236103084119e271) assert hyp2f3(a1,a2,b1,b2,b3,10**6).ae('2.0291718386574980641e865') assert hyp2f3(a1,a2,b1,b2,b3,10**7).ae('7.7639836665710030977e2742') assert hyp2f3(a1,a2,b1,b2,b3,10**8).ae('3.2537462584071268759e8681') assert hyp2f3(a1,a2,b1,b2,b3,10**20).ae('1.2966030542911614163e+8685889627') assert hyp2f3(a1,a2,b1,b2,b3,10*j).ae(-18.551602185587547854 - 13.348031097874113552j) assert hyp2f3(a1,a2,b1,b2,b3,100*j).ae(78634.359124504488695 + 74459.535945281973996j) assert hyp2f3(a1,a2,b1,b2,b3,1000*j).ae(597682550276527901.59 - 65136194809352613.078j) assert hyp2f3(a1,a2,b1,b2,b3,10000*j).ae(-1.1779696326238582496e+59 + 1.2297607505213133872e+59j) assert hyp2f3(a1,a2,b1,b2,b3,100000*j).ae(2.9844228969804380301e+191 + 7.5587163231490273296e+190j) assert hyp2f3(a1,a2,b1,b2,b3,1000000*j).ae('7.4859161049322370311e+610 - 2.8467477015940090189e+610j') assert hyp2f3(a1,a2,b1,b2,b3,10**7*j).ae('-1.7477645579418800826e+1938 - 1.7606522995808116405e+1938j') assert hyp2f3(a1,a2,b1,b2,b3,10**8*j).ae('-1.6932731942958401784e+6137 - 2.4521909113114629368e+6137j') assert hyp2f3(a1,a2,b1,b2,b3,10**20*j).ae('-2.0988815677627225449e+6141851451 + 5.7708223542739208681e+6141851452j') def test_hyper_2f2(): mp.dps = 15 assert hyper([1,2],[3,4],5) == hyp2f2(1,2,3,4,5) a1,a2,b1,b2 = (3,10),4,(1,2),1./16 assert hyp2f2(a1,a2,b1,b2,10).ae(448225936.3377556696) assert hyp2f2(a1,a2,b1,b2,10000).ae('1.2012553712966636711e+4358') assert hyp2f2(a1,a2,b1,b2,-20000).ae(-0.04182343755661214626) assert hyp2f2(a1,a2,b1,b2,10**20).ae('1.1148680024303263661e+43429448190325182840') def test_orthpoly(): mp.dps = 15 assert jacobi(-4,2,3,0.7).ae(22800./4913) assert jacobi(3,2,4,5.5) == 4133.125 assert jacobi(1.5,5/6.,4,0).ae(-1.0851951434075508417) assert jacobi(-2, 1, 2, 4).ae(-0.16) assert jacobi(2, -1, 2.5, 4).ae(34.59375) #assert jacobi(2, -1, 2, 4) == 28.5 assert legendre(5, 7) == 129367 assert legendre(0.5,0).ae(0.53935260118837935667) assert legendre(-1,-1) == 1 assert legendre(0,-1) == 1 assert legendre(0, 1) == 1 assert legendre(1, -1) == -1 assert legendre(7, 1) == 1 assert legendre(7, -1) == -1 assert legendre(8,1.5).ae(15457523./32768) assert legendre(j,-j).ae(2.4448182735671431011 + 0.6928881737669934843j) assert chebyu(5,1) == 6 assert chebyt(3,2) == 26 assert legendre(3.5,-1) == inf assert legendre(4.5,-1) == -inf assert legendre(3.5+1j,-1) == mpc(inf,inf) assert legendre(4.5+1j,-1) == mpc(-inf,-inf) assert laguerre(4, -2, 3).ae(-1.125) assert laguerre(3, 1+j, 0.5).ae(0.2291666666666666667 + 2.5416666666666666667j) def test_hermite(): mp.dps = 15 assert hermite(-2, 0).ae(0.5) assert hermite(-1, 0).ae(0.88622692545275801365) assert hermite(0, 0).ae(1) assert hermite(1, 0) == 0 assert hermite(2, 0).ae(-2) assert hermite(0, 2).ae(1) assert hermite(1, 2).ae(4) assert hermite(1, -2).ae(-4) assert hermite(2, -2).ae(14) assert hermite(0.5, 0).ae(0.69136733903629335053) assert hermite(9, 0) == 0 assert hermite(4,4).ae(3340) assert hermite(3,4).ae(464) assert hermite(-4,4).ae(0.00018623860287512396181) assert hermite(-3,4).ae(0.0016540169879668766270) assert hermite(9, 2.5j).ae(13638725j) assert hermite(9, -2.5j).ae(-13638725j) assert hermite(9, 100).ae(511078883759363024000) assert hermite(9, -100).ae(-511078883759363024000) assert hermite(9, 100j).ae(512922083920643024000j) assert hermite(9, -100j).ae(-512922083920643024000j) assert hermite(-9.5, 2.5j).ae(-2.9004951258126778174e-6 + 1.7601372934039951100e-6j) assert hermite(-9.5, -2.5j).ae(-2.9004951258126778174e-6 - 1.7601372934039951100e-6j) assert hermite(-9.5, 100).ae(1.3776300722767084162e-22, abs_eps=0, rel_eps=eps) assert hermite(-9.5, -100).ae('1.3106082028470671626e4355') assert hermite(-9.5, 100j).ae(-9.7900218581864768430e-23 - 9.7900218581864768430e-23j, abs_eps=0, rel_eps=eps) assert hermite(-9.5, -100j).ae(-9.7900218581864768430e-23 + 9.7900218581864768430e-23j, abs_eps=0, rel_eps=eps) assert hermite(2+3j, -1-j).ae(851.3677063883687676 - 1496.4373467871007997j) def test_gegenbauer(): mp.dps = 15 assert gegenbauer(1,2,3).ae(12) assert gegenbauer(2,3,4).ae(381) assert gegenbauer(0,0,0) == 0 assert gegenbauer(2,-1,3) == 0 assert gegenbauer(-7, 0.5, 3).ae(8989) assert gegenbauer(1, -0.5, 3).ae(-3) assert gegenbauer(1, -1.5, 3).ae(-9) assert gegenbauer(1, -0.5, 3).ae(-3) assert gegenbauer(-0.5, -0.5, 3).ae(-2.6383553159023906245) assert gegenbauer(2+3j, 1-j, 3+4j).ae(14.880536623203696780 + 20.022029711598032898j) #assert gegenbauer(-2, -0.5, 3).ae(-12) def test_legenp(): mp.dps = 15 assert legenp(2,0,4) == legendre(2,4) assert legenp(-2, -1, 0.5).ae(0.43301270189221932338) assert legenp(-2, -1, 0.5, type=3).ae(0.43301270189221932338j) assert legenp(-2, 1, 0.5).ae(-0.86602540378443864676) assert legenp(2+j, 3+4j, -j).ae(134742.98773236786148 + 429782.72924463851745j) assert legenp(2+j, 3+4j, -j, type=3).ae(802.59463394152268507 - 251.62481308942906447j) assert legenp(2,4,3).ae(0) assert legenp(2,4,3,type=3).ae(0) assert legenp(2,1,0.5).ae(-1.2990381056766579701) assert legenp(2,1,0.5,type=3).ae(1.2990381056766579701j) assert legenp(3,2,3).ae(-360) assert legenp(3,3,3).ae(240j*2**0.5) assert legenp(3,4,3).ae(0) assert legenp(0,0.5,2).ae(0.52503756790433198939 - 0.52503756790433198939j) assert legenp(-1,-0.5,2).ae(0.60626116232846498110 + 0.60626116232846498110j) assert legenp(-2,0.5,2).ae(1.5751127037129959682 - 1.5751127037129959682j) assert legenp(-2,0.5,-0.5).ae(-0.85738275810499171286) def test_legenq(): mp.dps = 15 f = legenq # Evaluation at poles assert isnan(f(3,2,1)) assert isnan(f(3,2,-1)) assert isnan(f(3,2,1,type=3)) assert isnan(f(3,2,-1,type=3)) # Evaluation at 0 assert f(0,1,0,type=2).ae(-1) assert f(-2,2,0,type=2,zeroprec=200).ae(0) assert f(1.5,3,0,type=2).ae(-2.2239343475841951023) assert f(0,1,0,type=3).ae(j) assert f(-2,2,0,type=3,zeroprec=200).ae(0) assert f(1.5,3,0,type=3).ae(2.2239343475841951022*(1-1j)) # Standard case, degree 0 assert f(0,0,-1.5).ae(-0.8047189562170501873 + 1.5707963267948966192j) assert f(0,0,-0.5).ae(-0.54930614433405484570) assert f(0,0,0,zeroprec=200).ae(0) assert f(0,0,0.5).ae(0.54930614433405484570) assert f(0,0,1.5).ae(0.8047189562170501873 - 1.5707963267948966192j) assert f(0,0,-1.5,type=3).ae(-0.80471895621705018730) assert f(0,0,-0.5,type=3).ae(-0.5493061443340548457 - 1.5707963267948966192j) assert f(0,0,0,type=3).ae(-1.5707963267948966192j) assert f(0,0,0.5,type=3).ae(0.5493061443340548457 - 1.5707963267948966192j) assert f(0,0,1.5,type=3).ae(0.80471895621705018730) # Standard case, degree 1 assert f(1,0,-1.5).ae(0.2070784343255752810 - 2.3561944901923449288j) assert f(1,0,-0.5).ae(-0.72534692783297257715) assert f(1,0,0).ae(-1) assert f(1,0,0.5).ae(-0.72534692783297257715) assert f(1,0,1.5).ae(0.2070784343255752810 - 2.3561944901923449288j) # Standard case, degree 2 assert f(2,0,-1.5).ae(-0.0635669991240192885 + 4.5160394395353277803j) assert f(2,0,-0.5).ae(0.81866326804175685571) assert f(2,0,0,zeroprec=200).ae(0) assert f(2,0,0.5).ae(-0.81866326804175685571) assert f(2,0,1.5).ae(0.0635669991240192885 - 4.5160394395353277803j) # Misc orders and degrees assert f(2,3,1.5,type=2).ae(-5.7243340223994616228j) assert f(2,3,1.5,type=3).ae(-5.7243340223994616228) assert f(2,3,0.5,type=2).ae(-12.316805742712016310) assert f(2,3,0.5,type=3).ae(-12.316805742712016310j) assert f(2,3,-1.5,type=2).ae(-5.7243340223994616228j) assert f(2,3,-1.5,type=3).ae(5.7243340223994616228) assert f(2,3,-0.5,type=2).ae(-12.316805742712016310) assert f(2,3,-0.5,type=3).ae(-12.316805742712016310j) assert f(2+3j, 3+4j, 0.5, type=3).ae(0.0016119404873235186807 - 0.0005885900510718119836j) assert f(2+3j, 3+4j, -1.5, type=3).ae(0.008451400254138808670 + 0.020645193304593235298j) assert f(-2.5,1,-1.5).ae(3.9553395527435335749j) assert f(-2.5,1,-0.5).ae(1.9290561746445456908) assert f(-2.5,1,0).ae(1.2708196271909686299) assert f(-2.5,1,0.5).ae(-0.31584812990742202869) assert f(-2.5,1,1.5).ae(-3.9553395527435335742 + 0.2993235655044701706j) assert f(-2.5,1,-1.5,type=3).ae(0.29932356550447017254j) assert f(-2.5,1,-0.5,type=3).ae(-0.3158481299074220287 - 1.9290561746445456908j) assert f(-2.5,1,0,type=3).ae(1.2708196271909686292 - 1.2708196271909686299j) assert f(-2.5,1,0.5,type=3).ae(1.9290561746445456907 + 0.3158481299074220287j) assert f(-2.5,1,1.5,type=3).ae(-0.29932356550447017254) def test_agm(): mp.dps = 15 assert agm(0,0) == 0 assert agm(0,1) == 0 assert agm(1,1) == 1 assert agm(7,7) == 7 assert agm(j,j) == j assert (1/agm(1,sqrt(2))).ae(0.834626841674073186) assert agm(1,2).ae(1.4567910310469068692) assert agm(1,3).ae(1.8636167832448965424) assert agm(1,j).ae(0.599070117367796104+0.599070117367796104j) assert agm(2) == agm(1,2) assert agm(-3,4).ae(0.63468509766550907+1.3443087080896272j) def test_gammainc(): mp.dps = 15 assert gammainc(2,5).ae(6*exp(-5)) assert gammainc(2,0,5).ae(1-6*exp(-5)) assert gammainc(2,3,5).ae(-6*exp(-5)+4*exp(-3)) assert gammainc(-2.5,-0.5).ae(-0.9453087204829418812-5.3164237738936178621j) assert gammainc(0,2,4).ae(0.045121158298212213088) assert gammainc(0,3).ae(0.013048381094197037413) assert gammainc(0,2+j,1-j).ae(0.00910653685850304839-0.22378752918074432574j) assert gammainc(0,1-j).ae(0.00028162445198141833+0.17932453503935894015j) assert gammainc(3,4,5,True).ae(0.11345128607046320253) assert gammainc(3.5,0,inf).ae(gamma(3.5)) assert gammainc(-150.5,500).ae('6.9825435345798951153e-627') assert gammainc(-150.5,800).ae('4.6885137549474089431e-788') assert gammainc(-3.5, -20.5).ae(0.27008820585226911 - 1310.31447140574997636j) assert gammainc(-3.5, -200.5).ae(0.27008820585226911 - 5.3264597096208368435e76j) # XXX real part assert gammainc(0,0,2) == inf assert gammainc(1,b=1).ae(0.6321205588285576784) assert gammainc(3,2,2) == 0 assert gammainc(2,3+j,3-j).ae(-0.28135485191849314194j) assert gammainc(4+0j,1).ae(5.8860710587430771455) # GH issue #301 assert gammainc(-1,-1).ae(-0.8231640121031084799 + 3.1415926535897932385j) assert gammainc(-2,-1).ae(1.7707229202810768576 - 1.5707963267948966192j) assert gammainc(-3,-1).ae(-1.4963349162467073643 + 0.5235987755982988731j) assert gammainc(-4,-1).ae(1.05365418617643814992 - 0.13089969389957471827j) # Regularized upper gamma assert isnan(gammainc(0, 0, regularized=True)) assert gammainc(-1, 0, regularized=True) == inf assert gammainc(1, 0, regularized=True) == 1 assert gammainc(0, 5, regularized=True) == 0 assert gammainc(0, 2+3j, regularized=True) == 0 assert gammainc(0, 5000, regularized=True) == 0 assert gammainc(0, 10**30, regularized=True) == 0 assert gammainc(-1, 5, regularized=True) == 0 assert gammainc(-1, 5000, regularized=True) == 0 assert gammainc(-1, 10**30, regularized=True) == 0 assert gammainc(-1, -5, regularized=True) == 0 assert gammainc(-1, -5000, regularized=True) == 0 assert gammainc(-1, -10**30, regularized=True) == 0 assert gammainc(-1, 3+4j, regularized=True) == 0 assert gammainc(1, 5, regularized=True).ae(exp(-5)) assert gammainc(1, 5000, regularized=True).ae(exp(-5000)) assert gammainc(1, 10**30, regularized=True).ae(exp(-10**30)) assert gammainc(1, 3+4j, regularized=True).ae(exp(-3-4j)) assert gammainc(-1000000,2).ae('1.3669297209397347754e-301037', abs_eps=0, rel_eps=8*eps) assert gammainc(-1000000,2,regularized=True) == 0 assert gammainc(-1000000,3+4j).ae('-1.322575609404222361e-698979 - 4.9274570591854533273e-698978j', abs_eps=0, rel_eps=8*eps) assert gammainc(-1000000,3+4j,regularized=True) == 0 assert gammainc(2+3j, 4+5j, regularized=True).ae(0.085422013530993285774-0.052595379150390078503j) assert gammainc(1000j, 1000j, regularized=True).ae(0.49702647628921131761 + 0.00297355675013575341j) # Generalized assert gammainc(3,4,2) == -gammainc(3,2,4) assert gammainc(4, 2, 3).ae(1.2593494302978947396) assert gammainc(4, 2, 3, regularized=True).ae(0.20989157171631578993) assert gammainc(0, 2, 3).ae(0.035852129613864082155) assert gammainc(0, 2, 3, regularized=True) == 0 assert gammainc(-1, 2, 3).ae(0.015219822548487616132) assert gammainc(-1, 2, 3, regularized=True) == 0 assert gammainc(0, 2, 3).ae(0.035852129613864082155) assert gammainc(0, 2, 3, regularized=True) == 0 # Should use upper gammas assert gammainc(5, 10000, 12000).ae('1.1359381951461801687e-4327', abs_eps=0, rel_eps=8*eps) # Should use lower gammas assert gammainc(10000, 2, 3).ae('8.1244514125995785934e4765') # GH issue 306 assert gammainc(3,-1-1j) == 0 assert gammainc(3,-1+1j) == 0 assert gammainc(2,-1) == 0 assert gammainc(2,-1+0j) == 0 assert gammainc(2+0j,-1) == 0 def test_gammainc_expint_n(): # These tests are intended to check all cases of the low-level code # for upper gamma and expint with small integer index. # Need to cover positive/negative arguments; small/large/huge arguments # for both positive and negative indices, as well as indices 0 and 1 # which may be special-cased mp.dps = 15 assert expint(-3,3.5).ae(0.021456366563296693987) assert expint(-2,3.5).ae(0.014966633183073309405) assert expint(-1,3.5).ae(0.011092916359219041088) assert expint(0,3.5).ae(0.0086278238349481430685) assert expint(1,3.5).ae(0.0069701398575483929193) assert expint(2,3.5).ae(0.0058018939208991255223) assert expint(3,3.5).ae(0.0049453773495857807058) assert expint(-3,-3.5).ae(-4.6618170604073311319) assert expint(-2,-3.5).ae(-5.5996974157555515963) assert expint(-1,-3.5).ae(-6.7582555017739415818) assert expint(0,-3.5).ae(-9.4615577024835182145) assert expint(1,-3.5).ae(-13.925353995152335292 - 3.1415926535897932385j) assert expint(2,-3.5).ae(-15.62328702434085977 - 10.995574287564276335j) assert expint(3,-3.5).ae(-10.783026313250347722 - 19.242255003237483586j) assert expint(-3,350).ae(2.8614825451252838069e-155, abs_eps=0, rel_eps=8*eps) assert expint(-2,350).ae(2.8532837224504675901e-155, abs_eps=0, rel_eps=8*eps) assert expint(-1,350).ae(2.8451316155828634555e-155, abs_eps=0, rel_eps=8*eps) assert expint(0,350).ae(2.8370258275042797989e-155, abs_eps=0, rel_eps=8*eps) assert expint(1,350).ae(2.8289659656701459404e-155, abs_eps=0, rel_eps=8*eps) assert expint(2,350).ae(2.8209516419468505006e-155, abs_eps=0, rel_eps=8*eps) assert expint(3,350).ae(2.8129824725501272171e-155, abs_eps=0, rel_eps=8*eps) assert expint(-3,-350).ae(-2.8528796154044839443e+149) assert expint(-2,-350).ae(-2.8610072121701264351e+149) assert expint(-1,-350).ae(-2.8691813842677537647e+149) assert expint(0,-350).ae(-2.8774025343659421709e+149) u = expint(1,-350) assert u.ae(-2.8856710698020863568e+149) assert u.imag.ae(-3.1415926535897932385) u = expint(2,-350) assert u.ae(-2.8939874026504650534e+149) assert u.imag.ae(-1099.5574287564276335) u = expint(3,-350) assert u.ae(-2.9023519497915044349e+149) assert u.imag.ae(-192422.55003237483586) assert expint(-3,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(-2,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(-1,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(0,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(1,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(2,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(3,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert expint(-3,-350000000000000000000000).ae('-3.7805306852415755699e+152003068666138139677871') assert expint(-2,-350000000000000000000000).ae('-3.7805306852415755699e+152003068666138139677871') assert expint(-1,-350000000000000000000000).ae('-3.7805306852415755699e+152003068666138139677871') assert expint(0,-350000000000000000000000).ae('-3.7805306852415755699e+152003068666138139677871') u = expint(1,-350000000000000000000000) assert u.ae('-3.7805306852415755699e+152003068666138139677871') assert u.imag.ae(-3.1415926535897932385) u = expint(2,-350000000000000000000000) assert u.imag.ae(-1.0995574287564276335e+24) assert u.ae('-3.7805306852415755699e+152003068666138139677871') u = expint(3,-350000000000000000000000) assert u.imag.ae(-1.9242255003237483586e+47) assert u.ae('-3.7805306852415755699e+152003068666138139677871') # Small case; no branch cut assert gammainc(-3,3.5).ae(0.00010020262545203707109) assert gammainc(-2,3.5).ae(0.00040370427343557393517) assert gammainc(-1,3.5).ae(0.0016576839773997501492) assert gammainc(0,3.5).ae(0.0069701398575483929193) assert gammainc(1,3.5).ae(0.03019738342231850074) assert gammainc(2,3.5).ae(0.13588822540043325333) assert gammainc(3,3.5).ae(0.64169439772426814072) # Small case; with branch cut assert gammainc(-3,-3.5).ae(0.03595832954467563286 + 0.52359877559829887308j) assert gammainc(-2,-3.5).ae(-0.88024704597962022221 - 1.5707963267948966192j) assert gammainc(-1,-3.5).ae(4.4637962926688170771 + 3.1415926535897932385j) assert gammainc(0,-3.5).ae(-13.925353995152335292 - 3.1415926535897932385j) assert gammainc(1,-3.5).ae(33.115451958692313751) assert gammainc(2,-3.5).ae(-82.788629896730784377) assert gammainc(3,-3.5).ae(240.08702670051927469) # Asymptotic case; no branch cut assert gammainc(-3,350).ae(6.5424095113340358813e-163, abs_eps=0, rel_eps=8*eps) assert gammainc(-2,350).ae(2.296312222489899769e-160, abs_eps=0, rel_eps=8*eps) assert gammainc(-1,350).ae(8.059861834133858573e-158, abs_eps=0, rel_eps=8*eps) assert gammainc(0,350).ae(2.8289659656701459404e-155, abs_eps=0, rel_eps=8*eps) assert gammainc(1,350).ae(9.9295903962649792963e-153, abs_eps=0, rel_eps=8*eps) assert gammainc(2,350).ae(3.485286229089007733e-150, abs_eps=0, rel_eps=8*eps) assert gammainc(3,350).ae(1.2233453960006379793e-147, abs_eps=0, rel_eps=8*eps) # Asymptotic case; branch cut u = gammainc(-3,-350) assert u.ae(6.7889565783842895085e+141) assert u.imag.ae(0.52359877559829887308) u = gammainc(-2,-350) assert u.ae(-2.3692668977889832121e+144) assert u.imag.ae(-1.5707963267948966192) u = gammainc(-1,-350) assert u.ae(8.2685354361441858669e+146) assert u.imag.ae(3.1415926535897932385) u = gammainc(0,-350) assert u.ae(-2.8856710698020863568e+149) assert u.imag.ae(-3.1415926535897932385) u = gammainc(1,-350) assert u.ae(1.0070908870280797598e+152) assert u.imag == 0 u = gammainc(2,-350) assert u.ae(-3.5147471957279983618e+154) assert u.imag == 0 u = gammainc(3,-350) assert u.ae(1.2266568422179417091e+157) assert u.imag == 0 # Extreme asymptotic case assert gammainc(-3,350000000000000000000000).ae('5.0362468738874738859e-152003068666138139677990', abs_eps=0, rel_eps=8*eps) assert gammainc(-2,350000000000000000000000).ae('1.7626864058606158601e-152003068666138139677966', abs_eps=0, rel_eps=8*eps) assert gammainc(-1,350000000000000000000000).ae('6.1694024205121555102e-152003068666138139677943', abs_eps=0, rel_eps=8*eps) assert gammainc(0,350000000000000000000000).ae('2.1592908471792544286e-152003068666138139677919', abs_eps=0, rel_eps=8*eps) assert gammainc(1,350000000000000000000000).ae('7.5575179651273905e-152003068666138139677896', abs_eps=0, rel_eps=8*eps) assert gammainc(2,350000000000000000000000).ae('2.645131287794586675e-152003068666138139677872', abs_eps=0, rel_eps=8*eps) assert gammainc(3,350000000000000000000000).ae('9.2579595072810533625e-152003068666138139677849', abs_eps=0, rel_eps=8*eps) u = gammainc(-3,-350000000000000000000000) assert u.ae('8.8175642804468234866e+152003068666138139677800') assert u.imag.ae(0.52359877559829887308) u = gammainc(-2,-350000000000000000000000) assert u.ae('-3.0861474981563882203e+152003068666138139677824') assert u.imag.ae(-1.5707963267948966192) u = gammainc(-1,-350000000000000000000000) assert u.ae('1.0801516243547358771e+152003068666138139677848') assert u.imag.ae(3.1415926535897932385) u = gammainc(0,-350000000000000000000000) assert u.ae('-3.7805306852415755699e+152003068666138139677871') assert u.imag.ae(-3.1415926535897932385) assert gammainc(1,-350000000000000000000000).ae('1.3231857398345514495e+152003068666138139677895') assert gammainc(2,-350000000000000000000000).ae('-4.6311500894209300731e+152003068666138139677918') assert gammainc(3,-350000000000000000000000).ae('1.6209025312973255256e+152003068666138139677942') def test_incomplete_beta(): mp.dps = 15 assert betainc(-2,-3,0.5,0.75).ae(63.4305673311255413583969) assert betainc(4.5,0.5+2j,2.5,6).ae(0.2628801146130621387903065 + 0.5162565234467020592855378j) assert betainc(4,5,0,6).ae(90747.77142857142857142857) def test_erf(): mp.dps = 15 assert erf(0) == 0 assert erf(1).ae(0.84270079294971486934) assert erf(3+4j).ae(-120.186991395079444098 - 27.750337293623902498j) assert erf(-4-3j).ae(-0.99991066178539168236 + 0.00004972026054496604j) assert erf(pi).ae(0.99999112385363235839) assert erf(1j).ae(1.6504257587975428760j) assert erf(-1j).ae(-1.6504257587975428760j) assert isinstance(erf(1), mpf) assert isinstance(erf(-1), mpf) assert isinstance(erf(0), mpf) assert isinstance(erf(0j), mpc) assert erf(inf) == 1 assert erf(-inf) == -1 assert erfi(0) == 0 assert erfi(1/pi).ae(0.371682698493894314) assert erfi(inf) == inf assert erfi(-inf) == -inf assert erf(1+0j) == erf(1) assert erfc(1+0j) == erfc(1) assert erf(0.2+0.5j).ae(1 - erfc(0.2+0.5j)) assert erfc(0) == 1 assert erfc(1).ae(1-erf(1)) assert erfc(-1).ae(1-erf(-1)) assert erfc(1/pi).ae(1-erf(1/pi)) assert erfc(-10) == 2 assert erfc(-1000000) == 2 assert erfc(-inf) == 2 assert erfc(inf) == 0 assert isnan(erfc(nan)) assert (erfc(10**4)*mpf(10)**43429453).ae('3.63998738656420') assert erf(8+9j).ae(-1072004.2525062051158 + 364149.91954310255423j) assert erfc(8+9j).ae(1072005.2525062051158 - 364149.91954310255423j) assert erfc(-8-9j).ae(-1072003.2525062051158 + 364149.91954310255423j) mp.dps = 50 # This one does not use the asymptotic series assert (erfc(10)*10**45).ae('2.0884875837625447570007862949577886115608181193212') # This one does assert (erfc(50)*10**1088).ae('2.0709207788416560484484478751657887929322509209954') mp.dps = 15 assert str(erfc(10**50)) == '3.66744826532555e-4342944819032518276511289189166050822943970058036665661144537831658646492088707747292249493384317534' assert erfinv(0) == 0 assert erfinv(0.5).ae(0.47693627620446987338) assert erfinv(-0.5).ae(-0.47693627620446987338) assert erfinv(1) == inf assert erfinv(-1) == -inf assert erf(erfinv(0.95)).ae(0.95) assert erf(erfinv(0.999999999995)).ae(0.999999999995) assert erf(erfinv(-0.999999999995)).ae(-0.999999999995) mp.dps = 50 assert erf(erfinv('0.99999999999999999999999999999995')).ae('0.99999999999999999999999999999995') assert erf(erfinv('0.999999999999999999999999999999995')).ae('0.999999999999999999999999999999995') assert erf(erfinv('-0.999999999999999999999999999999995')).ae('-0.999999999999999999999999999999995') mp.dps = 15 # Complex asymptotic expansions v = erfc(50j) assert v.real == 1 assert v.imag.ae('-6.1481820666053078736e+1083') assert erfc(-100+5j).ae(2) assert (erfc(100+5j)*10**4335).ae(2.3973567853824133572 - 3.9339259530609420597j) assert erfc(100+100j).ae(0.00065234366376857698698 - 0.0039357263629214118437j) def test_pdf(): mp.dps = 15 assert npdf(-inf) == 0 assert npdf(inf) == 0 assert npdf(5,0,2).ae(npdf(5+4,4,2)) assert quadts(lambda x: npdf(x,-0.5,0.8), [-inf, inf]) == 1 assert ncdf(0) == 0.5 assert ncdf(3,3) == 0.5 assert ncdf(-inf) == 0 assert ncdf(inf) == 1 assert ncdf(10) == 1 # Verify that this is computed accurately assert (ncdf(-10)*10**24).ae(7.619853024160526) def test_lambertw(): mp.dps = 15 assert lambertw(0) == 0 assert lambertw(0+0j) == 0 assert lambertw(inf) == inf assert isnan(lambertw(nan)) assert lambertw(inf,1).real == inf assert lambertw(inf,1).imag.ae(2*pi) assert lambertw(-inf,1).real == inf assert lambertw(-inf,1).imag.ae(3*pi) assert lambertw(0,-1) == -inf assert lambertw(0,1) == -inf assert lambertw(0,3) == -inf assert lambertw(e).ae(1) assert lambertw(1).ae(0.567143290409783873) assert lambertw(-pi/2).ae(j*pi/2) assert lambertw(-log(2)/2).ae(-log(2)) assert lambertw(0.25).ae(0.203888354702240164) assert lambertw(-0.25).ae(-0.357402956181388903) assert lambertw(-1./10000,0).ae(-0.000100010001500266719) assert lambertw(-0.25,-1).ae(-2.15329236411034965) assert lambertw(0.25,-1).ae(-3.00899800997004620-4.07652978899159763j) assert lambertw(-0.25,-1).ae(-2.15329236411034965) assert lambertw(0.25,1).ae(-3.00899800997004620+4.07652978899159763j) assert lambertw(-0.25,1).ae(-3.48973228422959210+7.41405453009603664j) assert lambertw(-4).ae(0.67881197132094523+1.91195078174339937j) assert lambertw(-4,1).ae(-0.66743107129800988+7.76827456802783084j) assert lambertw(-4,-1).ae(0.67881197132094523-1.91195078174339937j) assert lambertw(1000).ae(5.24960285240159623) assert lambertw(1000,1).ae(4.91492239981054535+5.44652615979447070j) assert lambertw(1000,-1).ae(4.91492239981054535-5.44652615979447070j) assert lambertw(1000,5).ae(3.5010625305312892+29.9614548941181328j) assert lambertw(3+4j).ae(1.281561806123775878+0.533095222020971071j) assert lambertw(-0.4+0.4j).ae(-0.10396515323290657+0.61899273315171632j) assert lambertw(3+4j,1).ae(-0.11691092896595324+5.61888039871282334j) assert lambertw(3+4j,-1).ae(0.25856740686699742-3.85211668616143559j) assert lambertw(-0.5,-1).ae(-0.794023632344689368-0.770111750510379110j) assert lambertw(-1./10000,1).ae(-11.82350837248724344+6.80546081842002101j) assert lambertw(-1./10000,-1).ae(-11.6671145325663544) assert lambertw(-1./10000,-2).ae(-11.82350837248724344-6.80546081842002101j) assert lambertw(-1./100000,4).ae(-14.9186890769540539+26.1856750178782046j) assert lambertw(-1./100000,5).ae(-15.0931437726379218666+32.5525721210262290086j) assert lambertw((2+j)/10).ae(0.173704503762911669+0.071781336752835511j) assert lambertw((2+j)/10,1).ae(-3.21746028349820063+4.56175438896292539j) assert lambertw((2+j)/10,-1).ae(-3.03781405002993088-3.53946629633505737j) assert lambertw((2+j)/10,4).ae(-4.6878509692773249+23.8313630697683291j) assert lambertw(-(2+j)/10).ae(-0.226933772515757933-0.164986470020154580j) assert lambertw(-(2+j)/10,1).ae(-2.43569517046110001+0.76974067544756289j) assert lambertw(-(2+j)/10,-1).ae(-3.54858738151989450-6.91627921869943589j) assert lambertw(-(2+j)/10,4).ae(-4.5500846928118151+20.6672982215434637j) mp.dps = 50 assert lambertw(pi).ae('1.073658194796149172092178407024821347547745350410314531') mp.dps = 15 # Former bug in generated branch assert lambertw(-0.5+0.002j).ae(-0.78917138132659918344 + 0.76743539379990327749j) assert lambertw(-0.5-0.002j).ae(-0.78917138132659918344 - 0.76743539379990327749j) assert lambertw(-0.448+0.4j).ae(-0.11855133765652382241 + 0.66570534313583423116j) assert lambertw(-0.448-0.4j).ae(-0.11855133765652382241 - 0.66570534313583423116j) assert lambertw(-0.65475+0.0001j).ae(-0.61053421111385310898+1.0396534993944097723803j) # Huge branch index w = lambertw(1,10**20) assert w.real.ae(-47.889578926290259164) assert w.imag.ae(6.2831853071795864769e+20) def test_lambertw_hard(): def check(x,y): y = convert(y) type_ok = True if isinstance(y, mpf): type_ok = isinstance(x, mpf) real_ok = abs(x.real-y.real) <= abs(y.real)*8*eps imag_ok = abs(x.imag-y.imag) <= abs(y.imag)*8*eps #print x, y, abs(x.real-y.real), abs(x.imag-y.imag) return real_ok and imag_ok # Evaluation near 0 mp.dps = 15 assert check(lambertw(1e-10), 9.999999999000000000e-11) assert check(lambertw(-1e-10), -1.000000000100000000e-10) assert check(lambertw(1e-10j), 9.999999999999999999733e-21 + 9.99999999999999999985e-11j) assert check(lambertw(-1e-10j), 9.999999999999999999733e-21 - 9.99999999999999999985e-11j) assert check(lambertw(1e-10,1), -26.303186778379041559 + 3.265093911703828397j) assert check(lambertw(-1e-10,1), -26.326236166739163892 + 6.526183280686333315j) assert check(lambertw(1e-10j,1), -26.312931726911421551 + 4.896366881798013421j) assert check(lambertw(-1e-10j,1), -26.297238779529035066 + 1.632807161345576513j) assert check(lambertw(1e-10,-1), -26.303186778379041559 - 3.265093911703828397j) assert check(lambertw(-1e-10,-1), -26.295238819246925694) assert check(lambertw(1e-10j,-1), -26.297238779529035028 - 1.6328071613455765135j) assert check(lambertw(-1e-10j,-1), -26.312931726911421551 - 4.896366881798013421j) # Test evaluation very close to the branch point -1/e # on the -1, 0, and 1 branches add = lambda x, y: fadd(x,y,exact=True) sub = lambda x, y: fsub(x,y,exact=True) addj = lambda x, y: fadd(x,fmul(y,1j,exact=True),exact=True) subj = lambda x, y: fadd(x,fmul(y,-1j,exact=True),exact=True) mp.dps = 1500 a = -1/e + 10*eps d3 = mpf('1e-3') d10 = mpf('1e-10') d20 = mpf('1e-20') d40 = mpf('1e-40') d80 = mpf('1e-80') d300 = mpf('1e-300') d1000 = mpf('1e-1000') mp.dps = 15 # ---- Branch 0 ---- # -1/e + eps assert check(lambertw(add(a,d3)), -0.92802015005456704876) assert check(lambertw(add(a,d10)), -0.99997668374140088071) assert check(lambertw(add(a,d20)), -0.99999999976683560186) assert lambertw(add(a,d40)) == -1 assert lambertw(add(a,d80)) == -1 assert lambertw(add(a,d300)) == -1 assert lambertw(add(a,d1000)) == -1 # -1/e - eps assert check(lambertw(sub(a,d3)), -0.99819016149860989001+0.07367191188934638577j) assert check(lambertw(sub(a,d10)), -0.9999999998187812114595992+0.0000233164398140346109194j) assert check(lambertw(sub(a,d20)), -0.99999999999999999998187+2.331643981597124203344e-10j) assert check(lambertw(sub(a,d40)), -1.0+2.33164398159712420336e-20j) assert check(lambertw(sub(a,d80)), -1.0+2.33164398159712420336e-40j) assert check(lambertw(sub(a,d300)), -1.0+2.33164398159712420336e-150j) assert check(lambertw(sub(a,d1000)), mpc(-1,'2.33164398159712420336e-500')) # -1/e + eps*j assert check(lambertw(addj(a,d3)), -0.94790387486938526634+0.05036819639190132490j) assert check(lambertw(addj(a,d10)), -0.9999835127872943680999899+0.0000164870314895821225256j) assert check(lambertw(addj(a,d20)), -0.999999999835127872929987+1.64872127051890935830e-10j) assert check(lambertw(addj(a,d40)), -0.9999999999999999999835+1.6487212707001281468305e-20j) assert check(lambertw(addj(a,d80)), -1.0 + 1.64872127070012814684865e-40j) assert check(lambertw(addj(a,d300)), -1.0 + 1.64872127070012814684865e-150j) assert check(lambertw(addj(a,d1000)), mpc(-1.0,'1.64872127070012814684865e-500')) # -1/e - eps*j assert check(lambertw(subj(a,d3)), -0.94790387486938526634-0.05036819639190132490j) assert check(lambertw(subj(a,d10)), -0.9999835127872943680999899-0.0000164870314895821225256j) assert check(lambertw(subj(a,d20)), -0.999999999835127872929987-1.64872127051890935830e-10j) assert check(lambertw(subj(a,d40)), -0.9999999999999999999835-1.6487212707001281468305e-20j) assert check(lambertw(subj(a,d80)), -1.0 - 1.64872127070012814684865e-40j) assert check(lambertw(subj(a,d300)), -1.0 - 1.64872127070012814684865e-150j) assert check(lambertw(subj(a,d1000)), mpc(-1.0,'-1.64872127070012814684865e-500')) # ---- Branch 1 ---- assert check(lambertw(addj(a,d3),1), -3.088501303219933378005990 + 7.458676867597474813950098j) assert check(lambertw(addj(a,d80),1), -3.088843015613043855957087 + 7.461489285654254556906117j) assert check(lambertw(addj(a,d300),1), -3.088843015613043855957087 + 7.461489285654254556906117j) assert check(lambertw(addj(a,d1000),1), -3.088843015613043855957087 + 7.461489285654254556906117j) assert check(lambertw(subj(a,d3),1), -1.0520914180450129534365906 + 0.0539925638125450525673175j) assert check(lambertw(subj(a,d10),1), -1.0000164872127056318529390 + 0.000016487393927159250398333077j) assert check(lambertw(subj(a,d20),1), -1.0000000001648721270700128 + 1.64872127088134693542628e-10j) assert check(lambertw(subj(a,d40),1), -1.000000000000000000016487 + 1.64872127070012814686677e-20j) assert check(lambertw(subj(a,d80),1), -1.0 + 1.64872127070012814684865e-40j) assert check(lambertw(subj(a,d300),1), -1.0 + 1.64872127070012814684865e-150j) assert check(lambertw(subj(a,d1000),1), mpc(-1.0, '1.64872127070012814684865e-500')) # ---- Branch -1 ---- # -1/e + eps assert check(lambertw(add(a,d3),-1), -1.075608941186624989414945) assert check(lambertw(add(a,d10),-1), -1.000023316621036696460620) assert check(lambertw(add(a,d20),-1), -1.000000000233164398177834) assert lambertw(add(a,d40),-1) == -1 assert lambertw(add(a,d80),-1) == -1 assert lambertw(add(a,d300),-1) == -1 assert lambertw(add(a,d1000),-1) == -1 # -1/e - eps assert check(lambertw(sub(a,d3),-1), -0.99819016149860989001-0.07367191188934638577j) assert check(lambertw(sub(a,d10),-1), -0.9999999998187812114595992-0.0000233164398140346109194j) assert check(lambertw(sub(a,d20),-1), -0.99999999999999999998187-2.331643981597124203344e-10j) assert check(lambertw(sub(a,d40),-1), -1.0-2.33164398159712420336e-20j) assert check(lambertw(sub(a,d80),-1), -1.0-2.33164398159712420336e-40j) assert check(lambertw(sub(a,d300),-1), -1.0-2.33164398159712420336e-150j) assert check(lambertw(sub(a,d1000),-1), mpc(-1,'-2.33164398159712420336e-500')) # -1/e + eps*j assert check(lambertw(addj(a,d3),-1), -1.0520914180450129534365906 - 0.0539925638125450525673175j) assert check(lambertw(addj(a,d10),-1), -1.0000164872127056318529390 - 0.0000164873939271592503983j) assert check(lambertw(addj(a,d20),-1), -1.0000000001648721270700 - 1.64872127088134693542628e-10j) assert check(lambertw(addj(a,d40),-1), -1.00000000000000000001648 - 1.6487212707001281468667726e-20j) assert check(lambertw(addj(a,d80),-1), -1.0 - 1.64872127070012814684865e-40j) assert check(lambertw(addj(a,d300),-1), -1.0 - 1.64872127070012814684865e-150j) assert check(lambertw(addj(a,d1000),-1), mpc(-1.0,'-1.64872127070012814684865e-500')) # -1/e - eps*j assert check(lambertw(subj(a,d3),-1), -3.088501303219933378005990-7.458676867597474813950098j) assert check(lambertw(subj(a,d10),-1), -3.088843015579260686911033-7.461489285372968780020716j) assert check(lambertw(subj(a,d20),-1), -3.088843015613043855953708-7.461489285654254556877988j) assert check(lambertw(subj(a,d40),-1), -3.088843015613043855957087-7.461489285654254556906117j) assert check(lambertw(subj(a,d80),-1), -3.088843015613043855957087 - 7.461489285654254556906117j) assert check(lambertw(subj(a,d300),-1), -3.088843015613043855957087 - 7.461489285654254556906117j) assert check(lambertw(subj(a,d1000),-1), -3.088843015613043855957087 - 7.461489285654254556906117j) # One more case, testing higher precision mp.dps = 500 x = -1/e + mpf('1e-13') ans = "-0.99999926266961377166355784455394913638782494543377383"\ "744978844374498153493943725364881490261187530235150668593869563"\ "168276697689459394902153960200361935311512317183678882" mp.dps = 15 assert lambertw(x).ae(ans) mp.dps = 50 assert lambertw(x).ae(ans) mp.dps = 150 assert lambertw(x).ae(ans) def test_meijerg(): mp.dps = 15 assert meijerg([[2,3],[1]],[[0.5,2],[3,4]], 2.5).ae(4.2181028074787439386) assert meijerg([[],[1+j]],[[1],[1]], 3+4j).ae(271.46290321152464592 - 703.03330399954820169j) assert meijerg([[0.25],[1]],[[0.5],[2]],0) == 0 assert meijerg([[0],[]],[[0,0,'1/3','2/3'], []], '2/27').ae(2.2019391389653314120) # Verify 1/z series being used assert meijerg([[-3],[-0.5]], [[-1],[-2.5]], -0.5).ae(-1.338096165935754898687431) assert meijerg([[1-(-1)],[1-(-2.5)]], [[1-(-3)],[1-(-0.5)]], -2.0).ae(-1.338096165935754898687431) assert meijerg([[-3],[-0.5]], [[-1],[-2.5]], -1).ae(-(pi+4)/(4*pi)) a = 2.5 b = 1.25 for z in [mpf(0.25), mpf(2)]: x1 = hyp1f1(a,b,z) x2 = gamma(b)/gamma(a)*meijerg([[1-a],[]],[[0],[1-b]],-z) x3 = gamma(b)/gamma(a)*meijerg([[1-0],[1-(1-b)]],[[1-(1-a)],[]],-1/z) assert x1.ae(x2) assert x1.ae(x3) def test_appellf1(): mp.dps = 15 assert appellf1(2,-2,1,1,2,3).ae(-1.75) assert appellf1(2,1,-2,1,2,3).ae(-8) assert appellf1(2,1,-2,1,0.5,0.25).ae(1.5) assert appellf1(-2,1,3,2,3,3).ae(19) assert appellf1(1,2,3,4,0.5,0.125).ae( 1.53843285792549786518) def test_coulomb(): # Note: most tests are doctests # Test for a bug: mp.dps = 15 assert coulombg(mpc(-5,0),2,3).ae(20.087729487721430394) def test_hyper_param_accuracy(): mp.dps = 15 As = [n+1e-10 for n in range(-5,-1)] Bs = [n+1e-10 for n in range(-12,-5)] assert hyper(As,Bs,10).ae(-381757055858.652671927) assert legenp(0.5, 100, 0.25).ae(-2.4124576567211311755e+144) assert (hyp1f1(1000,1,-100)*10**24).ae(5.2589445437370169113) assert (hyp2f1(10, -900, 10.5, 0.99)*10**24).ae(1.9185370579660768203) assert (hyp2f1(1000,1.5,-3.5,-1.5)*10**385).ae(-2.7367529051334000764) assert hyp2f1(-5, 10, 3, 0.5, zeroprec=500) == 0 assert (hyp1f1(-10000, 1000, 100)*10**424).ae(-3.1046080515824859974) assert (hyp2f1(1000,1.5,-3.5,-0.75,maxterms=100000)*10**231).ae(-4.0534790813913998643) assert legenp(2, 3, 0.25) == 0 pytest.raises(ValueError, lambda: hypercomb(lambda a: [([],[],[],[],[a],[-a],0.5)], [3])) assert hypercomb(lambda a: [([],[],[],[],[a],[-a],0.5)], [3], infprec=200) == inf assert meijerg([[],[]],[[0,0,0,0],[]],0.1).ae(1.5680822343832351418) assert (besselk(400,400)*10**94).ae(1.4387057277018550583) mp.dps = 5 (hyp1f1(-5000.5, 1500, 100)*10**185).ae(8.5185229673381935522) (hyp1f1(-5000, 1500, 100)*10**185).ae(9.1501213424563944311) mp.dps = 15 (hyp1f1(-5000.5, 1500, 100)*10**185).ae(8.5185229673381935522) (hyp1f1(-5000, 1500, 100)*10**185).ae(9.1501213424563944311) assert hyp0f1(fadd(-20,'1e-100',exact=True), 0.25).ae(1.85014429040102783e+49) assert hyp0f1((-20*10**100+1, 10**100), 0.25).ae(1.85014429040102783e+49) def test_hypercomb_zero_pow(): # check that 0^0 = 1 assert hypercomb(lambda a: (([0],[a],[],[],[],[],0),), [0]) == 1 assert meijerg([[-1.5],[]],[[0],[-0.75]],0).ae(1.4464090846320771425) def test_spherharm(): mp.dps = 15 t = 0.5; r = 0.25 assert spherharm(0,0,t,r).ae(0.28209479177387814347) assert spherharm(1,-1,t,r).ae(0.16048941205971996369 - 0.04097967481096344271j) assert spherharm(1,0,t,r).ae(0.42878904414183579379) assert spherharm(1,1,t,r).ae(-0.16048941205971996369 - 0.04097967481096344271j) assert spherharm(2,-2,t,r).ae(0.077915886919031181734 - 0.042565643022253962264j) assert spherharm(2,-1,t,r).ae(0.31493387233497459884 - 0.08041582001959297689j) assert spherharm(2,0,t,r).ae(0.41330596756220761898) assert spherharm(2,1,t,r).ae(-0.31493387233497459884 - 0.08041582001959297689j) assert spherharm(2,2,t,r).ae(0.077915886919031181734 + 0.042565643022253962264j) assert spherharm(3,-3,t,r).ae(0.033640236589690881646 - 0.031339125318637082197j) assert spherharm(3,-2,t,r).ae(0.18091018743101461963 - 0.09883168583167010241j) assert spherharm(3,-1,t,r).ae(0.42796713930907320351 - 0.10927795157064962317j) assert spherharm(3,0,t,r).ae(0.27861659336351639787) assert spherharm(3,1,t,r).ae(-0.42796713930907320351 - 0.10927795157064962317j) assert spherharm(3,2,t,r).ae(0.18091018743101461963 + 0.09883168583167010241j) assert spherharm(3,3,t,r).ae(-0.033640236589690881646 - 0.031339125318637082197j) assert spherharm(0,-1,t,r) == 0 assert spherharm(0,-2,t,r) == 0 assert spherharm(0,1,t,r) == 0 assert spherharm(0,2,t,r) == 0 assert spherharm(1,2,t,r) == 0 assert spherharm(1,3,t,r) == 0 assert spherharm(1,-2,t,r) == 0 assert spherharm(1,-3,t,r) == 0 assert spherharm(2,3,t,r) == 0 assert spherharm(2,4,t,r) == 0 assert spherharm(2,-3,t,r) == 0 assert spherharm(2,-4,t,r) == 0 assert spherharm(3,4.5,0.5,0.25).ae(-22.831053442240790148 + 10.910526059510013757j) assert spherharm(2+3j, 1-j, 1+j, 3+4j).ae(-2.6582752037810116935 - 1.0909214905642160211j) assert spherharm(-6,2.5,t,r).ae(0.39383644983851448178 + 0.28414687085358299021j) assert spherharm(-3.5, 3, 0.5, 0.25).ae(0.014516852987544698924 - 0.015582769591477628495j) assert spherharm(-3, 3, 0.5, 0.25) == 0 assert spherharm(-6, 3, 0.5, 0.25).ae(-0.16544349818782275459 - 0.15412657723253924562j) assert spherharm(-6, 1.5, 0.5, 0.25).ae(0.032208193499767402477 + 0.012678000924063664921j) assert spherharm(3,0,0,1).ae(0.74635266518023078283) assert spherharm(3,-2,0,1) == 0 assert spherharm(3,-2,1,1).ae(-0.16270707338254028971 - 0.35552144137546777097j) def test_qfunctions(): mp.dps = 15 assert qp(2,3,100).ae('2.7291482267247332183e2391') def test_issue_239(): mp.prec = 150 x = ldexp(2476979795053773,-52) assert betainc(206, 385, 0, 0.55, 1).ae('0.99999999999999999999996570910644857895771110649954') mp.dps = 15 pytest.raises(ValueError, lambda: hyp2f1(-5,5,0.5,0.5)) # Extra stress testing for Bessel functions # Reference zeros generated with the aid of scipy.special # jn_zero, jnp_zero, yn_zero, ynp_zero V = 15 M = 15 jn_small_zeros = \ [[2.4048255576957728, 5.5200781102863106, 8.6537279129110122, 11.791534439014282, 14.930917708487786, 18.071063967910923, 21.211636629879259, 24.352471530749303, 27.493479132040255, 30.634606468431975, 33.775820213573569, 36.917098353664044, 40.058425764628239, 43.19979171317673, 46.341188371661814], [3.8317059702075123, 7.0155866698156188, 10.173468135062722, 13.323691936314223, 16.470630050877633, 19.615858510468242, 22.760084380592772, 25.903672087618383, 29.046828534916855, 32.189679910974404, 35.332307550083865, 38.474766234771615, 41.617094212814451, 44.759318997652822, 47.901460887185447], [5.1356223018406826, 8.4172441403998649, 11.619841172149059, 14.795951782351261, 17.959819494987826, 21.116997053021846, 24.270112313573103, 27.420573549984557, 30.569204495516397, 33.7165195092227, 36.86285651128381, 40.008446733478192, 43.153453778371463, 46.297996677236919, 49.442164110416873], [6.3801618959239835, 9.7610231299816697, 13.015200721698434, 16.223466160318768, 19.409415226435012, 22.582729593104442, 25.748166699294978, 28.908350780921758, 32.064852407097709, 35.218670738610115, 38.370472434756944, 41.520719670406776, 44.669743116617253, 47.817785691533302, 50.965029906205183], [7.5883424345038044, 11.064709488501185, 14.37253667161759, 17.615966049804833, 20.826932956962388, 24.01901952477111, 27.199087765981251, 30.371007667117247, 33.537137711819223, 36.699001128744649, 39.857627302180889, 43.01373772335443, 46.167853512924375, 49.320360686390272, 52.471551398458023], [8.771483815959954, 12.338604197466944, 15.700174079711671, 18.980133875179921, 22.217799896561268, 25.430341154222704, 28.626618307291138, 31.811716724047763, 34.988781294559295, 38.159868561967132, 41.326383254047406, 44.489319123219673, 47.649399806697054, 50.80716520300633, 53.963026558378149], [9.9361095242176849, 13.589290170541217, 17.003819667816014, 20.320789213566506, 23.58608443558139, 26.820151983411405, 30.033722386570469, 33.233041762847123, 36.422019668258457, 39.603239416075404, 42.778481613199507, 45.949015998042603, 49.11577372476426, 52.279453903601052, 55.440592068853149], [11.086370019245084, 14.821268727013171, 18.287582832481726, 21.641541019848401, 24.934927887673022, 28.191188459483199, 31.42279419226558, 34.637089352069324, 37.838717382853611, 41.030773691585537, 44.21540850526126, 47.394165755570512, 50.568184679795566, 53.738325371963291, 56.905249991978781], [12.225092264004655, 16.037774190887709, 19.554536430997055, 22.94517313187462, 26.266814641176644, 29.54565967099855, 32.795800037341462, 36.025615063869571, 39.240447995178135, 42.443887743273558, 45.638444182199141, 48.825930381553857, 52.007691456686903, 55.184747939289049, 58.357889025269694], [13.354300477435331, 17.241220382489128, 20.807047789264107, 24.233885257750552, 27.583748963573006, 30.885378967696675, 34.154377923855096, 37.400099977156589, 40.628553718964528, 43.843801420337347, 47.048700737654032, 50.245326955305383, 53.435227157042058, 56.619580266508436, 59.799301630960228], [14.475500686554541, 18.433463666966583, 22.046985364697802, 25.509450554182826, 28.887375063530457, 32.211856199712731, 35.499909205373851, 38.761807017881651, 42.004190236671805, 45.231574103535045, 48.447151387269394, 51.653251668165858, 54.851619075963349, 58.043587928232478, 61.230197977292681], [15.589847884455485, 19.61596690396692, 23.275853726263409, 26.773322545509539, 30.17906117878486, 33.526364075588624, 36.833571341894905, 40.111823270954241, 43.368360947521711, 46.608132676274944, 49.834653510396724, 53.050498959135054, 56.257604715114484, 59.457456908388002, 62.651217388202912], [16.698249933848246, 20.789906360078443, 24.494885043881354, 28.026709949973129, 31.45996003531804, 34.829986990290238, 38.156377504681354, 41.451092307939681, 44.721943543191147, 47.974293531269048, 51.211967004101068, 54.437776928325074, 57.653844811906946, 60.8618046824805, 64.062937824850136], [17.801435153282442, 21.95624406783631, 25.705103053924724, 29.270630441874802, 32.731053310978403, 36.123657666448762, 39.469206825243883, 42.780439265447158, 46.06571091157561, 49.330780096443524, 52.579769064383396, 55.815719876305778, 59.040934037249271, 62.257189393731728, 65.465883797232125], [18.899997953174024, 23.115778347252756, 26.907368976182104, 30.505950163896036, 33.993184984781542, 37.408185128639695, 40.772827853501868, 44.100590565798301, 47.400347780543231, 50.678236946479898, 53.93866620912693, 57.184898598119301, 60.419409852130297, 63.644117508962281, 66.860533012260103]] jnp_small_zeros = \ [[0.0, 3.8317059702075123, 7.0155866698156188, 10.173468135062722, 13.323691936314223, 16.470630050877633, 19.615858510468242, 22.760084380592772, 25.903672087618383, 29.046828534916855, 32.189679910974404, 35.332307550083865, 38.474766234771615, 41.617094212814451, 44.759318997652822], [1.8411837813406593, 5.3314427735250326, 8.5363163663462858, 11.706004902592064, 14.863588633909033, 18.015527862681804, 21.16436985918879, 24.311326857210776, 27.457050571059246, 30.601922972669094, 33.746182898667383, 36.889987409236811, 40.033444053350675, 43.176628965448822, 46.319597561173912], [3.0542369282271403, 6.7061331941584591, 9.9694678230875958, 13.170370856016123, 16.347522318321783, 19.512912782488205, 22.671581772477426, 25.826037141785263, 28.977672772993679, 32.127327020443474, 35.275535050674691, 38.422654817555906, 41.568934936074314, 44.714553532819734, 47.859641607992093], [4.2011889412105285, 8.0152365983759522, 11.345924310743006, 14.585848286167028, 17.78874786606647, 20.9724769365377, 24.144897432909265, 27.310057930204349, 30.470268806290424, 33.626949182796679, 36.781020675464386, 39.933108623659488, 43.083652662375079, 46.232971081836478, 49.381300092370349], [5.3175531260839944, 9.2823962852416123, 12.681908442638891, 15.964107037731551, 19.196028800048905, 22.401032267689004, 25.589759681386733, 28.767836217666503, 31.938539340972783, 35.103916677346764, 38.265316987088158, 41.423666498500732, 44.579623137359257, 47.733667523865744, 50.886159153182682], [6.4156163757002403, 10.519860873772308, 13.9871886301403, 17.312842487884625, 20.575514521386888, 23.803581476593863, 27.01030789777772, 30.20284907898166, 33.385443901010121, 36.560777686880356, 39.730640230067416, 42.896273163494417, 46.058566273567043, 49.218174614666636, 52.375591529563596], [7.501266144684147, 11.734935953042708, 15.268181461097873, 18.637443009666202, 21.931715017802236, 25.183925599499626, 28.409776362510085, 31.617875716105035, 34.81339298429743, 37.999640897715301, 41.178849474321413, 44.352579199070217, 47.521956905768113, 50.687817781723741, 53.85079463676896], [8.5778364897140741, 12.932386237089576, 16.529365884366944, 19.941853366527342, 23.268052926457571, 26.545032061823576, 29.790748583196614, 33.015178641375142, 36.224380548787162, 39.422274578939259, 42.611522172286684, 45.793999658055002, 48.971070951900596, 52.143752969301988, 55.312820330403446], [9.6474216519972168, 14.115518907894618, 17.774012366915256, 21.229062622853124, 24.587197486317681, 27.889269427955092, 31.155326556188325, 34.39662855427218, 37.620078044197086, 40.830178681822041, 44.030010337966153, 47.221758471887113, 50.407020967034367, 53.586995435398319, 56.762598475105272], [10.711433970699945, 15.28673766733295, 19.004593537946053, 22.501398726777283, 25.891277276839136, 29.218563499936081, 32.505247352375523, 35.763792928808799, 39.001902811514218, 42.224638430753279, 45.435483097475542, 48.636922645305525, 51.830783925834728, 55.01844255063594, 58.200955824859509], [11.770876674955582, 16.447852748486498, 20.223031412681701, 23.760715860327448, 27.182021527190532, 30.534504754007074, 33.841965775135715, 37.118000423665604, 40.371068905333891, 43.606764901379516, 46.828959446564562, 50.040428970943456, 53.243223214220535, 56.438892058982552, 59.628631306921512], [12.826491228033465, 17.600266557468326, 21.430854238060294, 25.008518704644261, 28.460857279654847, 31.838424458616998, 35.166714427392629, 38.460388720328256, 41.728625562624312, 44.977526250903469, 48.211333836373288, 51.433105171422278, 54.645106240447105, 57.849056857839799, 61.046288512821078], [13.878843069697276, 18.745090916814406, 22.629300302835503, 26.246047773946584, 29.72897816891134, 33.131449953571661, 36.480548302231658, 39.791940718940855, 43.075486800191012, 46.337772104541405, 49.583396417633095, 52.815686826850452, 56.037118687012179, 59.249577075517968, 62.454525995970462], [14.928374492964716, 19.88322436109951, 23.81938909003628, 27.474339750968247, 30.987394331665278, 34.414545662167183, 37.784378506209499, 41.113512376883377, 44.412454519229281, 47.688252845993366, 50.945849245830813, 54.188831071035124, 57.419876154678179, 60.641030026538746, 63.853885828967512], [15.975438807484321, 21.015404934568315, 25.001971500138194, 28.694271223110755, 32.236969407878118, 35.688544091185301, 39.078998185245057, 42.425854432866141, 45.740236776624833, 49.029635055514276, 52.299319390331728, 55.553127779547459, 58.793933759028134, 62.02393848337554, 65.244860767043859]] yn_small_zeros = \ [[0.89357696627916752, 3.9576784193148579, 7.0860510603017727, 10.222345043496417, 13.361097473872763, 16.500922441528091, 19.64130970088794, 22.782028047291559, 25.922957653180923, 29.064030252728398, 32.205204116493281, 35.346452305214321, 38.487756653081537, 41.629104466213808, 44.770486607221993], [2.197141326031017, 5.4296810407941351, 8.5960058683311689, 11.749154830839881, 14.897442128336725, 18.043402276727856, 21.188068934142213, 24.331942571356912, 27.475294980449224, 30.618286491641115, 33.761017796109326, 36.90355531614295, 40.045944640266876, 43.188218097393211, 46.330399250701687], [3.3842417671495935, 6.7938075132682675, 10.023477979360038, 13.209986710206416, 16.378966558947457, 19.539039990286384, 22.69395593890929, 25.845613720902269, 28.995080395650151, 32.143002257627551, 35.289793869635804, 38.435733485446343, 41.581014867297885, 44.725777117640461, 47.870122696676504], [4.5270246611496439, 8.0975537628604907, 11.396466739595867, 14.623077742393873, 17.81845523294552, 20.997284754187761, 24.166235758581828, 27.328799850405162, 30.486989604098659, 33.642049384702463, 36.794791029185579, 39.945767226378749, 43.095367507846703, 46.2438744334407, 49.391498015725107], [5.6451478942208959, 9.3616206152445429, 12.730144474090465, 15.999627085382479, 19.22442895931681, 22.424810599698521, 25.610267054939328, 28.785893657666548, 31.954686680031668, 35.118529525584828, 38.278668089521758, 41.435960629910073, 44.591018225353424, 47.744288086361052, 50.896105199722123], [6.7471838248710219, 10.597176726782031, 14.033804104911233, 17.347086393228382, 20.602899017175335, 23.826536030287532, 27.030134937138834, 30.220335654231385, 33.401105611047908, 36.574972486670962, 39.743627733020277, 42.908248189569535, 46.069679073215439, 49.228543693445843, 52.385312123112282], [7.8377378223268716, 11.811037107609447, 15.313615118517857, 18.670704965906724, 21.958290897126571, 25.206207715021249, 28.429037095235496, 31.634879502950644, 34.828638524084437, 38.013473399691765, 41.19151880917741, 44.364272633271975, 47.53281875312084, 50.697961822183806, 53.860312300118388], [8.919605734873789, 13.007711435388313, 16.573915129085334, 19.974342312352426, 23.293972585596648, 26.5667563757203, 29.809531451608321, 33.031769327150685, 36.239265816598239, 39.435790312675323, 42.623910919472727, 45.805442883111651, 48.981708325514764, 52.153694518185572, 55.322154420959698], [9.9946283820824834, 14.190361295800141, 17.817887841179873, 21.26093227125945, 24.612576377421522, 27.910524883974868, 31.173701563441602, 34.412862242025045, 37.634648706110989, 40.843415321050884, 44.04214994542435, 47.232978012841169, 50.417456447370186, 53.596753874948731, 56.771765754432457], [11.064090256031013, 15.361301343575925, 19.047949646361388, 22.532765416313869, 25.91620496332662, 29.2394205079349, 32.523270869465881, 35.779715464475261, 39.016196664616095, 42.237627509803703, 45.4474001519274, 48.647941127433196, 51.841036928216499, 55.028034667184916, 58.209970905250097], [12.128927704415439, 16.522284394784426, 20.265984501212254, 23.791669719454272, 27.206568881574774, 30.555020011020762, 33.859683872746356, 37.133649760307504, 40.385117593813002, 43.619533085646856, 46.840676630553575, 50.051265851897857, 53.253310556711732, 56.448332488918971, 59.637507005589829], [13.189846995683845, 17.674674253171487, 21.473493977824902, 25.03913093040942, 28.485081336558058, 31.858644293774859, 35.184165245422787, 38.475796636190897, 41.742455848758449, 44.990096293791186, 48.222870660068338, 51.443777308699826, 54.655042589416311, 57.858358441436511, 61.055036135780528], [14.247395665073945, 18.819555894710682, 22.671697117872794, 26.276375544903892, 29.752925495549038, 33.151412708998983, 36.497763772987645, 39.807134090704376, 43.089121522203808, 46.350163579538652, 49.594769786270069, 52.82620892320143, 56.046916910756961, 59.258751140598783, 62.463155567737854], [15.30200785858925, 19.957808654258601, 23.861599172945054, 27.504429642227545, 31.011103429019229, 34.434283425782942, 37.801385632318459, 41.128514139788358, 44.425913324440663, 47.700482714581842, 50.957073905278458, 54.199216028087261, 57.429547607017405, 60.65008661807661, 63.862406280068586], [16.354034360047551, 21.090156519983806, 25.044040298785627, 28.724161640881914, 32.260472459522644, 35.708083982611664, 39.095820003878235, 42.440684315990936, 45.75353669045622, 49.041718113283529, 52.310408280968073, 55.56338698149062, 58.803488508906895, 62.032886550960831, 65.253280088312461]] ynp_small_zeros = \ [[2.197141326031017, 5.4296810407941351, 8.5960058683311689, 11.749154830839881, 14.897442128336725, 18.043402276727856, 21.188068934142213, 24.331942571356912, 27.475294980449224, 30.618286491641115, 33.761017796109326, 36.90355531614295, 40.045944640266876, 43.188218097393211, 46.330399250701687], [3.6830228565851777, 6.9414999536541757, 10.123404655436613, 13.285758156782854, 16.440058007293282, 19.590241756629495, 22.738034717396327, 25.884314618788867, 29.029575819372535, 32.174118233366201, 35.318134458192094, 38.461753870997549, 41.605066618873108, 44.74813744908079, 47.891014070791065], [5.0025829314460639, 8.3507247014130795, 11.574195465217647, 14.760909306207676, 17.931285939466855, 21.092894504412739, 24.249231678519058, 27.402145837145258, 30.552708880564553, 33.70158627151572, 36.849213419846257, 39.995887376143356, 43.141817835750686, 46.287157097544201, 49.432018469138281], [6.2536332084598136, 9.6987879841487711, 12.972409052292216, 16.19044719506921, 19.38238844973613, 22.559791857764261, 25.728213194724094, 28.890678419054777, 32.048984005266337, 35.204266606440635, 38.357281675961019, 41.508551443818436, 44.658448731963676, 47.807246956681162, 50.95515126455207], [7.4649217367571329, 11.005169149809189, 14.3317235192331, 17.58443601710272, 20.801062338411128, 23.997004122902644, 27.179886689853435, 30.353960608554323, 33.521797098666792, 36.685048382072301, 39.844826969405863, 43.001910515625288, 46.15685955107263, 49.310088614282257, 52.461911043685864], [8.6495562436971983, 12.280868725807848, 15.660799304540377, 18.949739756016503, 22.192841809428241, 25.409072788867674, 28.608039283077593, 31.795195353138159, 34.973890634255288, 38.14630522169358, 41.313923188794905, 44.477791768537617, 47.638672065035628, 50.797131066967842, 53.953600129601663], [9.8147970120105779, 13.532811875789828, 16.965526446046053, 20.291285512443867, 23.56186260680065, 26.799499736027237, 30.015665481543419, 33.216968050039509, 36.407516858984748, 39.590015243560459, 42.766320595957378, 45.937754257017323, 49.105283450953203, 52.269633324547373, 55.431358715604255], [10.965152105242974, 14.765687379508912, 18.250123150217555, 21.612750053384621, 24.911310600813573, 28.171051927637585, 31.40518108895689, 34.621401012564177, 37.824552065973114, 41.017847386464902, 44.203512240871601, 47.3831408366063, 50.557907466622796, 53.728697478957026, 56.896191727313342], [12.103641941939539, 15.982840905145284, 19.517731005559611, 22.916962141504605, 26.243700855690533, 29.525960140695407, 32.778568197561124, 36.010261572392516, 39.226578757802172, 42.43122493258747, 45.626783824134354, 48.815117837929515, 51.997606404328863, 55.175294723956816, 58.348990221754937], [13.232403808592215, 17.186756572616758, 20.770762917490496, 24.206152448722253, 27.561059462697153, 30.866053571250639, 34.137476603379774, 37.385039772270268, 40.614946085165892, 43.831373184731238, 47.037251786726299, 50.234705848765229, 53.425316228549359, 56.610286079882087, 59.790548623216652], [14.35301374369987, 18.379337301642568, 22.011118775283494, 25.482116178696707, 28.865046588695164, 32.192853922166294, 35.483296655830277, 38.747005493021857, 41.990815194320955, 45.219355876831731, 48.435892856078888, 51.642803925173029, 54.84186659475857, 58.034439083840155, 61.221578745109862], [15.466672066554263, 19.562077985759503, 23.240325531101082, 26.746322986645901, 30.157042415639891, 33.507642948240263, 36.817212798512775, 40.097251300178642, 43.355193847719752, 46.596103410173672, 49.823567279972794, 53.040208868780832, 56.247996968470062, 59.448441365714251, 62.642721301357187], [16.574317035530872, 20.73617763753932, 24.459631728238804, 27.999993668839644, 31.438208790267783, 34.811512070805535, 38.140243708611251, 41.436725143893739, 44.708963264433333, 47.962435051891027, 51.201037321915983, 54.427630745992975, 57.644369734615238, 60.852911791989989, 64.054555435720397], [17.676697936439624, 21.9026148697762, 25.670073356263225, 29.244155124266438, 32.709534477396028, 36.105399554497548, 39.453272918267025, 42.766255701958017, 46.052899215578358, 49.319076602061401, 52.568982147952547, 55.805705507386287, 59.031580956740466, 62.248409689597653, 65.457606670836759], [18.774423978290318, 23.06220035979272, 26.872520985976736, 30.479680663499762, 33.971869047372436, 37.390118854896324, 40.757072537673599, 44.086572292170345, 47.387688809191869, 50.66667461073936, 53.928009929563275, 57.175005343085052, 60.410169281219877, 63.635442539153021, 66.85235358587768]] @pytest.mark.slow def test_bessel_zeros_extra(): mp.dps = 15 for v in range(V): for m in range(1,M+1): print(v, m, "of", V, M) # Twice to test cache (if used) assert besseljzero(v,m).ae(jn_small_zeros[v][m-1]) assert besseljzero(v,m).ae(jn_small_zeros[v][m-1]) assert besseljzero(v,m,1).ae(jnp_small_zeros[v][m-1]) assert besseljzero(v,m,1).ae(jnp_small_zeros[v][m-1]) assert besselyzero(v,m).ae(yn_small_zeros[v][m-1]) assert besselyzero(v,m).ae(yn_small_zeros[v][m-1]) assert besselyzero(v,m,1).ae(ynp_small_zeros[v][m-1]) assert besselyzero(v,m,1).ae(ynp_small_zeros[v][m-1]) mpmath-1.1.0/mpmath/tests/test_gammazeta.py000066400000000000000000000660171340375245600210310ustar00rootroot00000000000000from mpmath import * from mpmath.libmp import round_up, from_float, mpf_zeta_int def test_zeta_int_bug(): assert mpf_zeta_int(0, 10) == from_float(-0.5) def test_bernoulli(): assert bernfrac(0) == (1,1) assert bernfrac(1) == (-1,2) assert bernfrac(2) == (1,6) assert bernfrac(3) == (0,1) assert bernfrac(4) == (-1,30) assert bernfrac(5) == (0,1) assert bernfrac(6) == (1,42) assert bernfrac(8) == (-1,30) assert bernfrac(10) == (5,66) assert bernfrac(12) == (-691,2730) assert bernfrac(18) == (43867,798) p, q = bernfrac(228) assert p % 10**10 == 164918161 assert q == 625170 p, q = bernfrac(1000) assert p % 10**10 == 7950421099 assert q == 342999030 mp.dps = 15 assert bernoulli(0) == 1 assert bernoulli(1) == -0.5 assert bernoulli(2).ae(1./6) assert bernoulli(3) == 0 assert bernoulli(4).ae(-1./30) assert bernoulli(5) == 0 assert bernoulli(6).ae(1./42) assert str(bernoulli(10)) == '0.0757575757575758' assert str(bernoulli(234)) == '7.62772793964344e+267' assert str(bernoulli(10**5)) == '-5.82229431461335e+376755' assert str(bernoulli(10**8+2)) == '1.19570355039953e+676752584' mp.dps = 50 assert str(bernoulli(10)) == '0.075757575757575757575757575757575757575757575757576' assert str(bernoulli(234)) == '7.6277279396434392486994969020496121553385863373331e+267' assert str(bernoulli(10**5)) == '-5.8222943146133508236497045360612887555320691004308e+376755' assert str(bernoulli(10**8+2)) == '1.1957035503995297272263047884604346914602088317782e+676752584' mp.dps = 1000 assert bernoulli(10).ae(mpf(5)/66) mp.dps = 50000 assert bernoulli(10).ae(mpf(5)/66) mp.dps = 15 def test_bernpoly_eulerpoly(): mp.dps = 15 assert bernpoly(0,-1).ae(1) assert bernpoly(0,0).ae(1) assert bernpoly(0,'1/2').ae(1) assert bernpoly(0,'3/4').ae(1) assert bernpoly(0,1).ae(1) assert bernpoly(0,2).ae(1) assert bernpoly(1,-1).ae('-3/2') assert bernpoly(1,0).ae('-1/2') assert bernpoly(1,'1/2').ae(0) assert bernpoly(1,'3/4').ae('1/4') assert bernpoly(1,1).ae('1/2') assert bernpoly(1,2).ae('3/2') assert bernpoly(2,-1).ae('13/6') assert bernpoly(2,0).ae('1/6') assert bernpoly(2,'1/2').ae('-1/12') assert bernpoly(2,'3/4').ae('-1/48') assert bernpoly(2,1).ae('1/6') assert bernpoly(2,2).ae('13/6') assert bernpoly(3,-1).ae(-3) assert bernpoly(3,0).ae(0) assert bernpoly(3,'1/2').ae(0) assert bernpoly(3,'3/4').ae('-3/64') assert bernpoly(3,1).ae(0) assert bernpoly(3,2).ae(3) assert bernpoly(4,-1).ae('119/30') assert bernpoly(4,0).ae('-1/30') assert bernpoly(4,'1/2').ae('7/240') assert bernpoly(4,'3/4').ae('7/3840') assert bernpoly(4,1).ae('-1/30') assert bernpoly(4,2).ae('119/30') assert bernpoly(5,-1).ae(-5) assert bernpoly(5,0).ae(0) assert bernpoly(5,'1/2').ae(0) assert bernpoly(5,'3/4').ae('25/1024') assert bernpoly(5,1).ae(0) assert bernpoly(5,2).ae(5) assert bernpoly(10,-1).ae('665/66') assert bernpoly(10,0).ae('5/66') assert bernpoly(10,'1/2').ae('-2555/33792') assert bernpoly(10,'3/4').ae('-2555/34603008') assert bernpoly(10,1).ae('5/66') assert bernpoly(10,2).ae('665/66') assert bernpoly(11,-1).ae(-11) assert bernpoly(11,0).ae(0) assert bernpoly(11,'1/2').ae(0) assert bernpoly(11,'3/4').ae('-555731/4194304') assert bernpoly(11,1).ae(0) assert bernpoly(11,2).ae(11) assert eulerpoly(0,-1).ae(1) assert eulerpoly(0,0).ae(1) assert eulerpoly(0,'1/2').ae(1) assert eulerpoly(0,'3/4').ae(1) assert eulerpoly(0,1).ae(1) assert eulerpoly(0,2).ae(1) assert eulerpoly(1,-1).ae('-3/2') assert eulerpoly(1,0).ae('-1/2') assert eulerpoly(1,'1/2').ae(0) assert eulerpoly(1,'3/4').ae('1/4') assert eulerpoly(1,1).ae('1/2') assert eulerpoly(1,2).ae('3/2') assert eulerpoly(2,-1).ae(2) assert eulerpoly(2,0).ae(0) assert eulerpoly(2,'1/2').ae('-1/4') assert eulerpoly(2,'3/4').ae('-3/16') assert eulerpoly(2,1).ae(0) assert eulerpoly(2,2).ae(2) assert eulerpoly(3,-1).ae('-9/4') assert eulerpoly(3,0).ae('1/4') assert eulerpoly(3,'1/2').ae(0) assert eulerpoly(3,'3/4').ae('-11/64') assert eulerpoly(3,1).ae('-1/4') assert eulerpoly(3,2).ae('9/4') assert eulerpoly(4,-1).ae(2) assert eulerpoly(4,0).ae(0) assert eulerpoly(4,'1/2').ae('5/16') assert eulerpoly(4,'3/4').ae('57/256') assert eulerpoly(4,1).ae(0) assert eulerpoly(4,2).ae(2) assert eulerpoly(5,-1).ae('-3/2') assert eulerpoly(5,0).ae('-1/2') assert eulerpoly(5,'1/2').ae(0) assert eulerpoly(5,'3/4').ae('361/1024') assert eulerpoly(5,1).ae('1/2') assert eulerpoly(5,2).ae('3/2') assert eulerpoly(10,-1).ae(2) assert eulerpoly(10,0).ae(0) assert eulerpoly(10,'1/2').ae('-50521/1024') assert eulerpoly(10,'3/4').ae('-36581523/1048576') assert eulerpoly(10,1).ae(0) assert eulerpoly(10,2).ae(2) assert eulerpoly(11,-1).ae('-699/4') assert eulerpoly(11,0).ae('691/4') assert eulerpoly(11,'1/2').ae(0) assert eulerpoly(11,'3/4').ae('-512343611/4194304') assert eulerpoly(11,1).ae('-691/4') assert eulerpoly(11,2).ae('699/4') # Potential accuracy issues assert bernpoly(10000,10000).ae('5.8196915936323387117e+39999') assert bernpoly(200,17.5).ae(3.8048418524583064909e244) assert eulerpoly(200,17.5).ae(-3.7309911582655785929e275) def test_gamma(): mp.dps = 15 assert gamma(0.25).ae(3.6256099082219083119) assert gamma(0.0001).ae(9999.4228832316241908) assert gamma(300).ae('1.0201917073881354535e612') assert gamma(-0.5).ae(-3.5449077018110320546) assert gamma(-7.43).ae(0.00026524416464197007186) #assert gamma(Rational(1,2)) == gamma(0.5) #assert gamma(Rational(-7,3)).ae(gamma(mpf(-7)/3)) assert gamma(1+1j).ae(0.49801566811835604271 - 0.15494982830181068512j) assert gamma(-1+0.01j).ae(-0.422733904013474115 + 99.985883082635367436j) assert gamma(20+30j).ae(-1453876687.5534810 + 1163777777.8031573j) # Should always give exact factorials when they can # be represented as mpfs under the current working precision fact = 1 for i in range(1, 18): assert gamma(i) == fact fact *= i for dps in [170, 600]: fact = 1 mp.dps = dps for i in range(1, 105): assert gamma(i) == fact fact *= i mp.dps = 100 assert gamma(0.5).ae(sqrt(pi)) mp.dps = 15 assert factorial(0) == fac(0) == 1 assert factorial(3) == 6 assert isnan(gamma(nan)) assert gamma(1100).ae('4.8579168073569433667e2866') assert rgamma(0) == 0 assert rgamma(-1) == 0 assert rgamma(2) == 1.0 assert rgamma(3) == 0.5 assert loggamma(2+8j).ae(-8.5205176753667636926 + 10.8569497125597429366j) assert loggamma('1e10000').ae('2.302485092994045684017991e10004') assert loggamma('1e10000j').ae(mpc('-1.570796326794896619231322e10000','2.302485092994045684017991e10004')) def test_fac2(): mp.dps = 15 assert [fac2(n) for n in range(10)] == [1,1,2,3,8,15,48,105,384,945] assert fac2(-5).ae(1./3) assert fac2(-11).ae(-1./945) assert fac2(50).ae(5.20469842636666623e32) assert fac2(0.5+0.75j).ae(0.81546769394688069176-0.34901016085573266889j) assert fac2(inf) == inf assert isnan(fac2(-inf)) def test_gamma_quotients(): mp.dps = 15 h = 1e-8 ep = 1e-4 G = gamma assert gammaprod([-1],[-3,-4]) == 0 assert gammaprod([-1,0],[-5]) == inf assert abs(gammaprod([-1],[-2]) - G(-1+h)/G(-2+h)) < 1e-4 assert abs(gammaprod([-4,-3],[-2,0]) - G(-4+h)*G(-3+h)/G(-2+h)/G(0+h)) < 1e-4 assert rf(3,0) == 1 assert rf(2.5,1) == 2.5 assert rf(-5,2) == 20 assert rf(j,j).ae(gamma(2*j)/gamma(j)) assert rf('-255.5815971722918','-0.5119253100282322').ae('-0.1952720278805729485') # issue 421 assert ff(-2,0) == 1 assert ff(-2,1) == -2 assert ff(4,3) == 24 assert ff(3,4) == 0 assert binomial(0,0) == 1 assert binomial(1,0) == 1 assert binomial(0,-1) == 0 assert binomial(3,2) == 3 assert binomial(5,2) == 10 assert binomial(5,3) == 10 assert binomial(5,5) == 1 assert binomial(-1,0) == 1 assert binomial(-2,-4) == 3 assert binomial(4.5, 1.5) == 6.5625 assert binomial(1100,1) == 1100 assert binomial(1100,2) == 604450 assert beta(1,1) == 1 assert beta(0,0) == inf assert beta(3,0) == inf assert beta(-1,-1) == inf assert beta(1.5,1).ae(2/3.) assert beta(1.5,2.5).ae(pi/16) assert (10**15*beta(10,100)).ae(2.3455339739604649879) assert beta(inf,inf) == 0 assert isnan(beta(-inf,inf)) assert isnan(beta(-3,inf)) assert isnan(beta(0,inf)) assert beta(inf,0.5) == beta(0.5,inf) == 0 assert beta(inf,-1.5) == inf assert beta(inf,-0.5) == -inf assert beta(1+2j,-1-j/2).ae(1.16396542451069943086+0.08511695947832914640j) assert beta(-0.5,0.5) == 0 assert beta(-3,3).ae(-1/3.) assert beta('-255.5815971722918','-0.5119253100282322').ae('18.157330562703710339') # issue 421 def test_zeta(): mp.dps = 15 assert zeta(2).ae(pi**2 / 6) assert zeta(2.0).ae(pi**2 / 6) assert zeta(mpc(2)).ae(pi**2 / 6) assert zeta(100).ae(1) assert zeta(0).ae(-0.5) assert zeta(0.5).ae(-1.46035450880958681) assert zeta(-1).ae(-mpf(1)/12) assert zeta(-2) == 0 assert zeta(-3).ae(mpf(1)/120) assert zeta(-4) == 0 assert zeta(-100) == 0 assert isnan(zeta(nan)) assert zeta(1e-30).ae(-0.5) assert zeta(-1e-30).ae(-0.5) # Zeros in the critical strip assert zeta(mpc(0.5, 14.1347251417346937904)).ae(0) assert zeta(mpc(0.5, 21.0220396387715549926)).ae(0) assert zeta(mpc(0.5, 25.0108575801456887632)).ae(0) assert zeta(mpc(1e-30,1e-40)).ae(-0.5) assert zeta(mpc(-1e-30,1e-40)).ae(-0.5) mp.dps = 50 im = '236.5242296658162058024755079556629786895294952121891237' assert zeta(mpc(0.5, im)).ae(0, 1e-46) mp.dps = 15 # Complex reflection formula assert (zeta(-60+3j) / 10**34).ae(8.6270183987866146+15.337398548226238j) # issue #358 assert zeta(0,0.5) == 0 assert zeta(0,0) == 0.5 assert zeta(0,0.5,1).ae(-0.34657359027997265) # see issue #390 assert zeta(-1.5,0.5j).ae(-0.13671400162512768475 + 0.11411333638426559139j) def test_altzeta(): mp.dps = 15 assert altzeta(-2) == 0 assert altzeta(-4) == 0 assert altzeta(-100) == 0 assert altzeta(0) == 0.5 assert altzeta(-1) == 0.25 assert altzeta(-3) == -0.125 assert altzeta(-5) == 0.25 assert altzeta(-21) == 1180529130.25 assert altzeta(1).ae(log(2)) assert altzeta(2).ae(pi**2/12) assert altzeta(10).ae(73*pi**10/6842880) assert altzeta(50) < 1 assert altzeta(60, rounding='d') < 1 assert altzeta(60, rounding='u') == 1 assert altzeta(10000, rounding='d') < 1 assert altzeta(10000, rounding='u') == 1 assert altzeta(3+0j) == altzeta(3) s = 3+4j assert altzeta(s).ae((1-2**(1-s))*zeta(s)) s = -3+4j assert altzeta(s).ae((1-2**(1-s))*zeta(s)) assert altzeta(-100.5).ae(4.58595480083585913e+108) assert altzeta(1.3).ae(0.73821404216623045) assert altzeta(1e-30).ae(0.5) assert altzeta(-1e-30).ae(0.5) assert altzeta(mpc(1e-30,1e-40)).ae(0.5) assert altzeta(mpc(-1e-30,1e-40)).ae(0.5) def test_zeta_huge(): mp.dps = 15 assert zeta(inf) == 1 mp.dps = 50 assert zeta(100).ae('1.0000000000000000000000000000007888609052210118073522') assert zeta(40*pi).ae('1.0000000000000000000000000000000000000148407238666182') mp.dps = 10000 v = zeta(33000) mp.dps = 15 assert str(v-1) == '1.02363019598118e-9934' assert zeta(pi*1000, rounding=round_up) > 1 assert zeta(3000, rounding=round_up) > 1 assert zeta(pi*1000) == 1 assert zeta(3000) == 1 def test_zeta_negative(): mp.dps = 150 a = -pi*10**40 mp.dps = 15 assert str(zeta(a)) == '2.55880492708712e+1233536161668617575553892558646631323374078' mp.dps = 50 assert str(zeta(a)) == '2.5588049270871154960875033337384432038436330847333e+1233536161668617575553892558646631323374078' mp.dps = 15 def test_polygamma(): mp.dps = 15 psi0 = lambda z: psi(0,z) psi1 = lambda z: psi(1,z) assert psi0(3) == psi(0,3) == digamma(3) #assert psi2(3) == psi(2,3) == tetragamma(3) #assert psi3(3) == psi(3,3) == pentagamma(3) assert psi0(pi).ae(0.97721330794200673) assert psi0(-pi).ae(7.8859523853854902) assert psi0(-pi+1).ae(7.5676424992016996) assert psi0(pi+j).ae(1.04224048313859376 + 0.35853686544063749j) assert psi0(-pi-j).ae(1.3404026194821986 - 2.8824392476809402j) assert findroot(psi0, 1).ae(1.4616321449683622) assert psi0(1e-10).ae(-10000000000.57722) assert psi0(1e-40).ae(-1.000000000000000e+40) assert psi0(1e-10+1e-10j).ae(-5000000000.577215 + 5000000000.000000j) assert psi0(1e-40+1e-40j).ae(-5.000000000000000e+39 + 5.000000000000000e+39j) assert psi0(inf) == inf assert psi1(inf) == 0 assert psi(2,inf) == 0 assert psi1(pi).ae(0.37424376965420049) assert psi1(-pi).ae(53.030438740085385) assert psi1(pi+j).ae(0.32935710377142464 - 0.12222163911221135j) assert psi1(-pi-j).ae(-0.30065008356019703 + 0.01149892486928227j) assert (10**6*psi(4,1+10*pi*j)).ae(-6.1491803479004446 - 0.3921316371664063j) assert psi0(1+10*pi*j).ae(3.4473994217222650 + 1.5548808324857071j) assert isnan(psi0(nan)) assert isnan(psi0(-inf)) assert psi0(-100.5).ae(4.615124601338064) assert psi0(3+0j).ae(psi0(3)) assert psi0(-100+3j).ae(4.6106071768714086321+3.1117510556817394626j) assert isnan(psi(2,mpc(0,inf))) assert isnan(psi(2,mpc(0,nan))) assert isnan(psi(2,mpc(0,-inf))) assert isnan(psi(2,mpc(1,inf))) assert isnan(psi(2,mpc(1,nan))) assert isnan(psi(2,mpc(1,-inf))) assert isnan(psi(2,mpc(inf,inf))) assert isnan(psi(2,mpc(nan,nan))) assert isnan(psi(2,mpc(-inf,-inf))) def test_polygamma_high_prec(): mp.dps = 100 assert str(psi(0,pi)) == "0.9772133079420067332920694864061823436408346099943256380095232865318105924777141317302075654362928734" assert str(psi(10,pi)) == "-12.98876181434889529310283769414222588307175962213707170773803550518307617769657562747174101900659238" def test_polygamma_identities(): mp.dps = 15 psi0 = lambda z: psi(0,z) psi1 = lambda z: psi(1,z) psi2 = lambda z: psi(2,z) assert psi0(0.5).ae(-euler-2*log(2)) assert psi0(1).ae(-euler) assert psi1(0.5).ae(0.5*pi**2) assert psi1(1).ae(pi**2/6) assert psi1(0.25).ae(pi**2 + 8*catalan) assert psi2(1).ae(-2*apery) mp.dps = 20 u = -182*apery+4*sqrt(3)*pi**3 mp.dps = 15 assert psi(2,5/6.).ae(u) assert psi(3,0.5).ae(pi**4) def test_foxtrot_identity(): # A test of the complex digamma function. # See http://mathworld.wolfram.com/FoxTrotSeries.html and # http://mathworld.wolfram.com/DigammaFunction.html psi0 = lambda z: psi(0,z) mp.dps = 50 a = (-1)**fraction(1,3) b = (-1)**fraction(2,3) x = -psi0(0.5*a) - psi0(-0.5*b) + psi0(0.5*(1+a)) + psi0(0.5*(1-b)) y = 2*pi*sech(0.5*sqrt(3)*pi) assert x.ae(y) mp.dps = 15 def test_polygamma_high_order(): mp.dps = 100 assert str(psi(50, pi)) == "-1344100348958402765749252447726432491812.641985273160531055707095989227897753035823152397679626136483" assert str(psi(50, pi + 14*e)) == "-0.00000000000000000189793739550804321623512073101895801993019919886375952881053090844591920308111549337295143780341396" assert str(psi(50, pi + 14*e*j)) == ("(-0.0000000000000000522516941152169248975225472155683565752375889510631513244785" "9377385233700094871256507814151956624433 - 0.00000000000000001813157041407010184" "702414110218205348527862196327980417757665282244728963891298080199341480881811613j)") mp.dps = 15 assert str(psi(50, pi)) == "-1.34410034895841e+39" assert str(psi(50, pi + 14*e)) == "-1.89793739550804e-18" assert str(psi(50, pi + 14*e*j)) == "(-5.2251694115217e-17 - 1.81315704140701e-17j)" def test_harmonic(): mp.dps = 15 assert harmonic(0) == 0 assert harmonic(1) == 1 assert harmonic(2) == 1.5 assert harmonic(3).ae(1. + 1./2 + 1./3) assert harmonic(10**10).ae(23.603066594891989701) assert harmonic(10**1000).ae(2303.162308658947) assert harmonic(0.5).ae(2-2*log(2)) assert harmonic(inf) == inf assert harmonic(2+0j) == 1.5+0j assert harmonic(1+2j).ae(1.4918071802755104+0.92080728264223022j) def test_gamma_huge_1(): mp.dps = 500 x = mpf(10**10) / 7 mp.dps = 15 assert str(gamma(x)) == "6.26075321389519e+12458010678" mp.dps = 50 assert str(gamma(x)) == "6.2607532138951929201303779291707455874010420783933e+12458010678" mp.dps = 15 def test_gamma_huge_2(): mp.dps = 500 x = mpf(10**100) / 19 mp.dps = 15 assert str(gamma(x)) == (\ "1.82341134776679e+5172997469323364168990133558175077136829182824042201886051511" "9656908623426021308685461258226190190661") mp.dps = 50 assert str(gamma(x)) == (\ "1.82341134776678875374414910350027596939980412984e+5172997469323364168990133558" "1750771368291828240422018860515119656908623426021308685461258226190190661") def test_gamma_huge_3(): mp.dps = 500 x = 10**80 // 3 + 10**70*j / 7 mp.dps = 15 y = gamma(x) assert str(y.real) == (\ "-6.82925203918106e+2636286142112569524501781477865238132302397236429627932441916" "056964386399485392600") assert str(y.imag) == (\ "8.54647143678418e+26362861421125695245017814778652381323023972364296279324419160" "56964386399485392600") mp.dps = 50 y = gamma(x) assert str(y.real) == (\ "-6.8292520391810548460682736226799637356016538421817e+26362861421125695245017814" "77865238132302397236429627932441916056964386399485392600") assert str(y.imag) == (\ "8.5464714367841748507479306948130687511711420234015e+263628614211256952450178147" "7865238132302397236429627932441916056964386399485392600") def test_gamma_huge_4(): x = 3200+11500j mp.dps = 15 assert str(gamma(x)) == \ "(8.95783268539713e+5164 - 1.94678798329735e+5164j)" mp.dps = 50 assert str(gamma(x)) == (\ "(8.9578326853971339570292952697675570822206567327092e+5164" " - 1.9467879832973509568895402139429643650329524144794e+51" "64j)") mp.dps = 15 def test_gamma_huge_5(): mp.dps = 500 x = 10**60 * j / 3 mp.dps = 15 y = gamma(x) assert str(y.real) == "-3.27753899634941e-227396058973640224580963937571892628368354580620654233316839" assert str(y.imag) == "-7.1519888950416e-227396058973640224580963937571892628368354580620654233316841" mp.dps = 50 y = gamma(x) assert str(y.real) == (\ "-3.2775389963494132168950056995974690946983219123935e-22739605897364022458096393" "7571892628368354580620654233316839") assert str(y.imag) == (\ "-7.1519888950415979749736749222530209713136588885897e-22739605897364022458096393" "7571892628368354580620654233316841") mp.dps = 15 def test_gamma_huge_7(): mp.dps = 100 a = 3 + j/mpf(10)**1000 mp.dps = 15 y = gamma(a) assert str(y.real) == "2.0" # wrong #assert str(y.imag) == "2.16735365342606e-1000" assert str(y.imag) == "1.84556867019693e-1000" mp.dps = 50 y = gamma(a) assert str(y.real) == "2.0" #assert str(y.imag) == "2.1673536534260596065418805612488708028522563689298e-1000" assert str(y.imag) == "1.8455686701969342787869758198351951379156813281202e-1000" def test_stieltjes(): mp.dps = 15 assert stieltjes(0).ae(+euler) mp.dps = 25 assert stieltjes(1).ae('-0.07281584548367672486058637587') assert stieltjes(2).ae('-0.009690363192872318484530386035') assert stieltjes(3).ae('0.002053834420303345866160046543') assert stieltjes(4).ae('0.002325370065467300057468170178') mp.dps = 15 assert stieltjes(1).ae(-0.07281584548367672486058637587) assert stieltjes(2).ae(-0.009690363192872318484530386035) assert stieltjes(3).ae(0.002053834420303345866160046543) assert stieltjes(4).ae(0.0023253700654673000574681701775) def test_barnesg(): mp.dps = 15 assert barnesg(0) == barnesg(-1) == 0 assert [superfac(i) for i in range(8)] == [1, 1, 2, 12, 288, 34560, 24883200, 125411328000] assert str(superfac(1000)) == '3.24570818422368e+1177245' assert isnan(barnesg(nan)) assert isnan(superfac(nan)) assert isnan(hyperfac(nan)) assert barnesg(inf) == inf assert superfac(inf) == inf assert hyperfac(inf) == inf assert isnan(superfac(-inf)) assert barnesg(0.7).ae(0.8068722730141471) assert barnesg(2+3j).ae(-0.17810213864082169+0.04504542715447838j) assert [hyperfac(n) for n in range(7)] == [1, 1, 4, 108, 27648, 86400000, 4031078400000] assert [hyperfac(n) for n in range(0,-7,-1)] == [1,1,-1,-4,108,27648,-86400000] a = barnesg(-3+0j) assert a == 0 and isinstance(a, mpc) a = hyperfac(-3+0j) assert a == -4 and isinstance(a, mpc) def test_polylog(): mp.dps = 15 zs = [mpmathify(z) for z in [0, 0.5, 0.99, 4, -0.5, -4, 1j, 3+4j]] for z in zs: assert polylog(1, z).ae(-log(1-z)) for z in zs: assert polylog(0, z).ae(z/(1-z)) for z in zs: assert polylog(-1, z).ae(z/(1-z)**2) for z in zs: assert polylog(-2, z).ae(z*(1+z)/(1-z)**3) for z in zs: assert polylog(-3, z).ae(z*(1+4*z+z**2)/(1-z)**4) assert polylog(3, 7).ae(5.3192579921456754382-5.9479244480803301023j) assert polylog(3, -7).ae(-4.5693548977219423182) assert polylog(2, 0.9).ae(1.2997147230049587252) assert polylog(2, -0.9).ae(-0.75216317921726162037) assert polylog(2, 0.9j).ae(-0.17177943786580149299+0.83598828572550503226j) assert polylog(2, 1.1).ae(1.9619991013055685931-0.2994257606855892575j) assert polylog(2, -1.1).ae(-0.89083809026228260587) assert polylog(2, 1.1*sqrt(j)).ae(0.58841571107611387722+1.09962542118827026011j) assert polylog(-2, 0.9).ae(1710) assert polylog(-2, -0.9).ae(-90/6859.) assert polylog(3, 0.9).ae(1.0496589501864398696) assert polylog(-3, 0.9).ae(48690) assert polylog(-3, -4).ae(-0.0064) assert polylog(0.5+j/3, 0.5+j/2).ae(0.31739144796565650535 + 0.99255390416556261437j) assert polylog(3+4j,1).ae(zeta(3+4j)) assert polylog(3+4j,-1).ae(-altzeta(3+4j)) # issue 390 assert polylog(1.5, -48.910886523731889).ae(-6.272992229311817) assert polylog(1.5, 200).ae(-8.349608319033686529 - 8.159694826434266042j) def test_bell_polyexp(): mp.dps = 15 # TODO: more tests for polyexp assert (polyexp(0,1e-10)*10**10).ae(1.00000000005) assert (polyexp(1,1e-10)*10**10).ae(1.0000000001) assert polyexp(5,3j).ae(-607.7044517476176454+519.962786482001476087j) assert polyexp(-1,3.5).ae(12.09537536175543444) # bell(0,x) = 1 assert bell(0,0) == 1 assert bell(0,1) == 1 assert bell(0,2) == 1 assert bell(0,inf) == 1 assert bell(0,-inf) == 1 assert isnan(bell(0,nan)) # bell(1,x) = x assert bell(1,4) == 4 assert bell(1,0) == 0 assert bell(1,inf) == inf assert bell(1,-inf) == -inf assert isnan(bell(1,nan)) # bell(2,x) = x*(1+x) assert bell(2,-1) == 0 assert bell(2,0) == 0 # large orders / arguments assert bell(10) == 115975 assert bell(10,1) == 115975 assert bell(10, -8) == 11054008 assert bell(5,-50) == -253087550 assert bell(50,-50).ae('3.4746902914629720259e74') mp.dps = 80 assert bell(50,-50) == 347469029146297202586097646631767227177164818163463279814268368579055777450 assert bell(40,50) == 5575520134721105844739265207408344706846955281965031698187656176321717550 assert bell(74) == 5006908024247925379707076470957722220463116781409659160159536981161298714301202 mp.dps = 15 assert bell(10,20j) == 7504528595600+15649605360020j # continuity of the generalization assert bell(0.5,0).ae(sinc(pi*0.5)) def test_primezeta(): mp.dps = 15 assert primezeta(0.9).ae(1.8388316154446882243 + 3.1415926535897932385j) assert primezeta(4).ae(0.076993139764246844943) assert primezeta(1) == inf assert primezeta(inf) == 0 assert isnan(primezeta(nan)) def test_rs_zeta(): mp.dps = 15 assert zeta(0.5+100000j).ae(1.0730320148577531321 + 5.7808485443635039843j) assert zeta(0.75+100000j).ae(1.837852337251873704 + 1.9988492668661145358j) assert zeta(0.5+1000000j, derivative=3).ae(1647.7744105852674733 - 1423.1270943036622097j) assert zeta(1+1000000j, derivative=3).ae(3.4085866124523582894 - 18.179184721525947301j) assert zeta(1+1000000j, derivative=1).ae(-0.10423479366985452134 - 0.74728992803359056244j) assert zeta(0.5-1000000j, derivative=1).ae(11.636804066002521459 + 17.127254072212996004j) # Additional sanity tests using fp arithmetic. # Some more high-precision tests are found in the docstrings def ae(x, y, tol=1e-6): return abs(x-y) < tol*abs(y) assert ae(fp.zeta(0.5-100000j), 1.0730320148577531321 - 5.7808485443635039843j) assert ae(fp.zeta(0.75-100000j), 1.837852337251873704 - 1.9988492668661145358j) assert ae(fp.zeta(0.5+1e6j), 0.076089069738227100006 + 2.8051021010192989554j) assert ae(fp.zeta(0.5+1e6j, derivative=1), 11.636804066002521459 - 17.127254072212996004j) assert ae(fp.zeta(1+1e6j), 0.94738726251047891048 + 0.59421999312091832833j) assert ae(fp.zeta(1+1e6j, derivative=1), -0.10423479366985452134 - 0.74728992803359056244j) assert ae(fp.zeta(0.5+100000j, derivative=1), 10.766962036817482375 - 30.92705282105996714j) assert ae(fp.zeta(0.5+100000j, derivative=2), -119.40515625740538429 + 217.14780631141830251j) assert ae(fp.zeta(0.5+100000j, derivative=3), 1129.7550282628460881 - 1685.4736895169690346j) assert ae(fp.zeta(0.5+100000j, derivative=4), -10407.160819314958615 + 13777.786698628045085j) assert ae(fp.zeta(0.75+100000j, derivative=1), -0.41742276699594321475 - 6.4453816275049955949j) assert ae(fp.zeta(0.75+100000j, derivative=2), -9.214314279161977266 + 35.07290795337967899j) assert ae(fp.zeta(0.75+100000j, derivative=3), 110.61331857820103469 - 236.87847130518129926j) assert ae(fp.zeta(0.75+100000j, derivative=4), -1054.334275898559401 + 1769.9177890161596383j) def test_siegelz(): mp.dps = 15 assert siegelz(100000).ae(5.87959246868176504171) assert siegelz(100000, derivative=2).ae(-54.1172711010126452832) assert siegelz(100000, derivative=3).ae(-278.930831343966552538) assert siegelz(100000+j,derivative=1).ae(678.214511857070283307-379.742160779916375413j) def test_zeta_near_1(): # Test for a former bug in mpf_zeta and mpc_zeta mp.dps = 15 s1 = fadd(1, '1e-10', exact=True) s2 = fadd(1, '-1e-10', exact=True) s3 = fadd(1, '1e-10j', exact=True) assert zeta(s1).ae(1.000000000057721566490881444e10) assert zeta(s2).ae(-9.99999999942278433510574872e9) z = zeta(s3) assert z.real.ae(0.57721566490153286060) assert z.imag.ae(-9.9999999999999999999927184e9) mp.dps = 30 s1 = fadd(1, '1e-50', exact=True) s2 = fadd(1, '-1e-50', exact=True) s3 = fadd(1, '1e-50j', exact=True) assert zeta(s1).ae('1e50') assert zeta(s2).ae('-1e50') z = zeta(s3) assert z.real.ae('0.57721566490153286060651209008240243104215933593992') assert z.imag.ae('-1e50') mpmath-1.1.0/mpmath/tests/test_hp.py000066400000000000000000000243351340375245600174670ustar00rootroot00000000000000""" Check that the output from irrational functions is accurate for high-precision input, from 5 to 200 digits. The reference values were verified with Mathematica. """ import time from mpmath import * precs = [5, 15, 28, 35, 57, 80, 100, 150, 200] # sqrt(3) + pi/2 a = \ "3.302847134363773912758768033145623809041389953497933538543279275605"\ "841220051904536395163599428307109666700184672047856353516867399774243594"\ "67433521615861420725323528325327484262075464241255915238845599752675" # e + 1/euler**2 b = \ "5.719681166601007617111261398629939965860873957353320734275716220045750"\ "31474116300529519620938123730851145473473708966080207482581266469342214"\ "824842256999042984813905047895479210702109260221361437411947323431" # sqrt(a) sqrt_a = \ "1.817373691447021556327498239690365674922395036495564333152483422755"\ "144321726165582817927383239308173567921345318453306994746434073691275094"\ "484777905906961689902608644112196725896908619756404253109722911487" # sqrt(a+b*i).real sqrt_abi_real = \ "2.225720098415113027729407777066107959851146508557282707197601407276"\ "89160998185797504198062911768240808839104987021515555650875977724230130"\ "3584116233925658621288393930286871862273400475179312570274423840384" # sqrt(a+b*i).imag sqrt_abi_imag = \ "1.2849057639084690902371581529110949983261182430040898147672052833653668"\ "0629534491275114877090834296831373498336559849050755848611854282001250"\ "1924311019152914021365263161630765255610885489295778894976075186" # log(a) log_a = \ "1.194784864491089550288313512105715261520511949410072046160598707069"\ "4336653155025770546309137440687056366757650909754708302115204338077595203"\ "83005773986664564927027147084436553262269459110211221152925732612" # log(a+b*i).real log_abi_real = \ "1.8877985921697018111624077550443297276844736840853590212962006811663"\ "04949387789489704203167470111267581371396245317618589339274243008242708"\ "014251531496104028712866224020066439049377679709216784954509456421" # log(a+b*i).imag log_abi_imag = \ "1.0471204952840802663567714297078763189256357109769672185219334169734948"\ "4265809854092437285294686651806426649541504240470168212723133326542181"\ "8300136462287639956713914482701017346851009323172531601894918640" # exp(a) exp_a = \ "27.18994224087168661137253262213293847994194869430518354305430976149"\ "382792035050358791398632888885200049857986258414049540376323785711941636"\ "100358982497583832083513086941635049329804685212200507288797531143" # exp(a+b*i).real exp_abi_real = \ "22.98606617170543596386921087657586890620262522816912505151109385026"\ "40160179326569526152851983847133513990281518417211964710397233157168852"\ "4963130831190142571659948419307628119985383887599493378056639916701" # exp(a+b*i).imag exp_abi_imag = \ "-14.523557450291489727214750571590272774669907424478129280902375851196283"\ "3377162379031724734050088565710975758824441845278120105728824497308303"\ "6065619788140201636218705414429933685889542661364184694108251449" # a**b pow_a_b = \ "928.7025342285568142947391505837660251004990092821305668257284426997"\ "361966028275685583421197860603126498884545336686124793155581311527995550"\ "580229264427202446131740932666832138634013168125809402143796691154" # (a**(a+b*i)).real pow_a_abi_real = \ "44.09156071394489511956058111704382592976814280267142206420038656267"\ "67707916510652790502399193109819563864568986234654864462095231138500505"\ "8197456514795059492120303477512711977915544927440682508821426093455" # (a**(a+b*i)).imag pow_a_abi_imag = \ "27.069371511573224750478105146737852141664955461266218367212527612279886"\ "9322304536553254659049205414427707675802193810711302947536332040474573"\ "8166261217563960235014674118610092944307893857862518964990092301" # ((a+b*i)**(a+b*i)).real pow_abi_abi_real = \ "-0.15171310677859590091001057734676423076527145052787388589334350524"\ "8084195882019497779202452975350579073716811284169068082670778986235179"\ "0813026562962084477640470612184016755250592698408112493759742219150452"\ # ((a+b*i)**(a+b*i)).imag pow_abi_abi_imag = \ "1.2697592504953448936553147870155987153192995316950583150964099070426"\ "4736837932577176947632535475040521749162383347758827307504526525647759"\ "97547638617201824468382194146854367480471892602963428122896045019902" # sin(a) sin_a = \ "-0.16055653857469062740274792907968048154164433772938156243509084009"\ "38437090841460493108570147191289893388608611542655654723437248152535114"\ "528368009465836614227575701220612124204622383149391870684288862269631" # sin(1000*a) sin_1000a = \ "-0.85897040577443833776358106803777589664322997794126153477060795801"\ "09151695416961724733492511852267067419573754315098042850381158563024337"\ "216458577140500488715469780315833217177634490142748614625281171216863" # sin(a+b*i) sin_abi_real = \ "-24.4696999681556977743346798696005278716053366404081910969773939630"\ "7149215135459794473448465734589287491880563183624997435193637389884206"\ "02151395451271809790360963144464736839412254746645151672423256977064" sin_abi_imag = \ "-150.42505378241784671801405965872972765595073690984080160750785565810981"\ "8314482499135443827055399655645954830931316357243750839088113122816583"\ "7169201254329464271121058839499197583056427233866320456505060735" # cos cos_a = \ "-0.98702664499035378399332439243967038895709261414476495730788864004"\ "05406821549361039745258003422386169330787395654908532996287293003581554"\ "257037193284199198069707141161341820684198547572456183525659969145501" cos_1000a = \ "-0.51202523570982001856195696460663971099692261342827540426136215533"\ "52686662667660613179619804463250686852463876088694806607652218586060613"\ "951310588158830695735537073667299449753951774916401887657320950496820" # tan tan_a = \ "0.162666873675188117341401059858835168007137819495998960250142156848"\ "639654718809412181543343168174807985559916643549174530459883826451064966"\ "7996119428949951351938178809444268785629011625179962457123195557310" tan_abi_real = \ "6.822696615947538488826586186310162599974827139564433912601918442911"\ "1026830824380070400102213741875804368044342309515353631134074491271890"\ "467615882710035471686578162073677173148647065131872116479947620E-6" tan_abi_imag = \ "0.9999795833048243692245661011298447587046967777739649018690797625964167"\ "1446419978852235960862841608081413169601038230073129482874832053357571"\ "62702259309150715669026865777947502665936317953101462202542168429" def test_hp(): for dps in precs: mp.dps = dps + 8 aa = mpf(a) bb = mpf(b) a1000 = 1000*mpf(a) abi = mpc(aa, bb) mp.dps = dps assert (sqrt(3) + pi/2).ae(aa) assert (e + 1/euler**2).ae(bb) assert sqrt(aa).ae(mpf(sqrt_a)) assert sqrt(abi).ae(mpc(sqrt_abi_real, sqrt_abi_imag)) assert log(aa).ae(mpf(log_a)) assert log(abi).ae(mpc(log_abi_real, log_abi_imag)) assert exp(aa).ae(mpf(exp_a)) assert exp(abi).ae(mpc(exp_abi_real, exp_abi_imag)) assert (aa**bb).ae(mpf(pow_a_b)) assert (aa**abi).ae(mpc(pow_a_abi_real, pow_a_abi_imag)) assert (abi**abi).ae(mpc(pow_abi_abi_real, pow_abi_abi_imag)) assert sin(a).ae(mpf(sin_a)) assert sin(a1000).ae(mpf(sin_1000a)) assert sin(abi).ae(mpc(sin_abi_real, sin_abi_imag)) assert cos(a).ae(mpf(cos_a)) assert cos(a1000).ae(mpf(cos_1000a)) assert tan(a).ae(mpf(tan_a)) assert tan(abi).ae(mpc(tan_abi_real, tan_abi_imag)) # check that complex cancellation is avoided so that both # real and imaginary parts have high relative accuracy. # abs_eps should be 0, but has to be set to 1e-205 to pass the # 200-digit case, probably due to slight inaccuracy in the # precomputed input assert (tan(abi).real).ae(mpf(tan_abi_real), abs_eps=1e-205) assert (tan(abi).imag).ae(mpf(tan_abi_imag), abs_eps=1e-205) mp.dps = 460 assert str(log(3))[-20:] == '02166121184001409826' mp.dps = 15 # Since str(a) can differ in the last digit from rounded a, and I want # to compare the last digits of big numbers with the results in Mathematica, # I made this hack to get the last 20 digits of rounded a def last_digits(a): r = repr(a) s = str(a) #dps = mp.dps #mp.dps += 3 m = 10 r = r.replace(s[:-m],'') r = r.replace("mpf('",'').replace("')",'') num0 = 0 for c in r: if c == '0': num0 += 1 else: break b = float(int(r))/10**(len(r) - m) if b >= 10**m - 0.5: # pragma: no cover raise NotImplementedError n = int(round(b)) sn = str(n) s = s[:-m] + '0'*num0 + sn return s[-20:] # values checked with Mathematica def test_log_hp(): mp.dps = 2000 a = mpf(10)**15000/3 r = log(a) res = last_digits(r) # Mathematica N[Log[10^15000/3], 2000] # ...7443804441768333470331 assert res == '43804441768333470331' # see issue 145 r = log(mpf(3)/2) # Mathematica N[Log[3/2], 2000] # ...69653749808140753263288 res = last_digits(r) assert res == '53749808140753263288' mp.dps = 10000 r = log(2) res = last_digits(r) # Mathematica N[Log[2], 10000] # ...695615913401856601359655561 assert res == '13401856601359655561' r = log(mpf(10)**10/3) res = last_digits(r) # Mathematica N[Log[10^10/3], 10000] # ...587087654020631943060007154 assert res == '54020631943060007154', res r = log(mpf(10)**100/3) res = last_digits(r) # Mathematica N[Log[10^100/3], 10000] # ,,,59246336539088351652334666 assert res == '36539088351652334666', res mp.dps += 10 a = 1 - mpf(1)/10**10 mp.dps -= 10 r = log(a) res = last_digits(r) # ...3310334360482956137216724048322957404 # 372167240483229574038733026370 # Mathematica N[Log[1 - 10^-10]*10^10, 10000] # ...60482956137216724048322957404 assert res == '37216724048322957404', res mp.dps = 10000 mp.dps += 100 a = 1 + mpf(1)/10**100 mp.dps -= 100 r = log(a) res = last_digits(+r) # Mathematica N[Log[1 + 10^-100]*10^10, 10030] # ...3994733877377412241546890854692521568292338268273 10^-91 assert res == '39947338773774122415', res mp.dps = 15 def test_exp_hp(): mp.dps = 4000 r = exp(mpf(1)/10) # IntegerPart[N[Exp[1/10] * 10^4000, 4000]] # ...92167105162069688129 assert int(r * 10**mp.dps) % 10**20 == 92167105162069688129 mpmath-1.1.0/mpmath/tests/test_identify.py000066400000000000000000000012641340375245600206670ustar00rootroot00000000000000from mpmath import * def test_pslq(): mp.dps = 15 assert pslq([3*pi+4*e/7, pi, e, log(2)]) == [7, -21, -4, 0] assert pslq([4.9999999999999991, 1]) == [1, -5] assert pslq([2,1]) == [1, -2] def test_identify(): mp.dps = 20 assert identify(zeta(4), ['log(2)', 'pi**4']) == '((1/90)*pi**4)' mp.dps = 15 assert identify(exp(5)) == 'exp(5)' assert identify(exp(4)) == 'exp(4)' assert identify(log(5)) == 'log(5)' assert identify(exp(3*pi), ['pi']) == 'exp((3*pi))' assert identify(3, full=True) == ['3', '3', '1/(1/3)', 'sqrt(9)', '1/sqrt((1/9))', '(sqrt(12)/2)**2', '1/(sqrt(12)/6)**2'] assert identify(pi+1, {'a':+pi}) == '(1 + 1*a)' mpmath-1.1.0/mpmath/tests/test_interval.py000066400000000000000000000413551340375245600207050ustar00rootroot00000000000000from mpmath import * def test_interval_identity(): iv.dps = 15 assert mpi(2) == mpi(2, 2) assert mpi(2) != mpi(-2, 2) assert not (mpi(2) != mpi(2, 2)) assert mpi(-1, 1) == mpi(-1, 1) assert str(mpi('0.1')) == "[0.099999999999999991673, 0.10000000000000000555]" assert repr(mpi('0.1')) == "mpi('0.099999999999999992', '0.10000000000000001')" u = mpi(-1, 3) assert -1 in u assert 2 in u assert 3 in u assert -1.1 not in u assert 3.1 not in u assert mpi(-1, 3) in u assert mpi(0, 1) in u assert mpi(-1.1, 2) not in u assert mpi(2.5, 3.1) not in u w = mpi(-inf, inf) assert mpi(-5, 5) in w assert mpi(2, inf) in w assert mpi(0, 2) in mpi(0, 10) assert not (3 in mpi(-inf, 0)) def test_interval_hash(): assert hash(mpi(3)) == hash(3) assert hash(mpi(3.25)) == hash(3.25) assert hash(mpi(3,4)) == hash(mpi(3,4)) assert hash(iv.mpc(3)) == hash(3) assert hash(iv.mpc(3,4)) == hash(3+4j) assert hash(iv.mpc((1,3),(2,4))) == hash(iv.mpc((1,3),(2,4))) def test_interval_arithmetic(): iv.dps = 15 assert mpi(2) + mpi(3,4) == mpi(5,6) assert mpi(1, 2)**2 == mpi(1, 4) assert mpi(1) + mpi(0, 1e-50) == mpi(1, mpf('1.0000000000000002')) x = 1 / (1 / mpi(3)) assert x.a < 3 < x.b x = mpi(2) ** mpi(0.5) iv.dps += 5 sq = iv.sqrt(2) iv.dps -= 5 assert x.a < sq < x.b assert mpi(1) / mpi(1, inf) assert mpi(2, 3) / inf == mpi(0, 0) assert mpi(0) / inf == 0 assert mpi(0) / 0 == mpi(-inf, inf) assert mpi(inf) / 0 == mpi(-inf, inf) assert mpi(0) * inf == mpi(-inf, inf) assert 1 / mpi(2, inf) == mpi(0, 0.5) assert str((mpi(50, 50) * mpi(-10, -10)) / 3) == \ '[-166.66666666666668561, -166.66666666666665719]' assert mpi(0, 4) ** 3 == mpi(0, 64) assert mpi(2,4).mid == 3 iv.dps = 30 a = mpi(iv.pi) iv.dps = 15 b = +a assert b.a < a.a assert b.b > a.b a = mpi(iv.pi) assert a == +a assert abs(mpi(-1,2)) == mpi(0,2) assert abs(mpi(0.5,2)) == mpi(0.5,2) assert abs(mpi(-3,2)) == mpi(0,3) assert abs(mpi(-3,-0.5)) == mpi(0.5,3) assert mpi(0) * mpi(2,3) == mpi(0) assert mpi(2,3) * mpi(0) == mpi(0) assert mpi(1,3).delta == 2 assert mpi(1,2) - mpi(3,4) == mpi(-3,-1) assert mpi(-inf,0) - mpi(0,inf) == mpi(-inf,0) assert mpi(-inf,0) - mpi(-inf,inf) == mpi(-inf,inf) assert mpi(0,inf) - mpi(-inf,1) == mpi(-1,inf) def test_interval_mul(): assert mpi(-1, 0) * inf == mpi(-inf, 0) assert mpi(-1, 0) * -inf == mpi(0, inf) assert mpi(0, 1) * inf == mpi(0, inf) assert mpi(0, 1) * mpi(0, inf) == mpi(0, inf) assert mpi(-1, 1) * inf == mpi(-inf, inf) assert mpi(-1, 1) * mpi(0, inf) == mpi(-inf, inf) assert mpi(-1, 1) * mpi(-inf, inf) == mpi(-inf, inf) assert mpi(-inf, 0) * mpi(0, 1) == mpi(-inf, 0) assert mpi(-inf, 0) * mpi(0, 0) * mpi(-inf, 0) assert mpi(-inf, 0) * mpi(-inf, inf) == mpi(-inf, inf) assert mpi(-5,0)*mpi(-32,28) == mpi(-140,160) assert mpi(2,3) * mpi(-1,2) == mpi(-3,6) # Should be undefined? assert mpi(inf, inf) * 0 == mpi(-inf, inf) assert mpi(-inf, -inf) * 0 == mpi(-inf, inf) assert mpi(0) * mpi(-inf,2) == mpi(-inf,inf) assert mpi(0) * mpi(-2,inf) == mpi(-inf,inf) assert mpi(-2,inf) * mpi(0) == mpi(-inf,inf) assert mpi(-inf,2) * mpi(0) == mpi(-inf,inf) def test_interval_pow(): assert mpi(3)**2 == mpi(9, 9) assert mpi(-3)**2 == mpi(9, 9) assert mpi(-3, 1)**2 == mpi(0, 9) assert mpi(-3, -1)**2 == mpi(1, 9) assert mpi(-3, -1)**3 == mpi(-27, -1) assert mpi(-3, 1)**3 == mpi(-27, 1) assert mpi(-2, 3)**2 == mpi(0, 9) assert mpi(-3, 2)**2 == mpi(0, 9) assert mpi(4) ** -1 == mpi(0.25, 0.25) assert mpi(-4) ** -1 == mpi(-0.25, -0.25) assert mpi(4) ** -2 == mpi(0.0625, 0.0625) assert mpi(-4) ** -2 == mpi(0.0625, 0.0625) assert mpi(0, 1) ** inf == mpi(0, 1) assert mpi(0, 1) ** -inf == mpi(1, inf) assert mpi(0, inf) ** inf == mpi(0, inf) assert mpi(0, inf) ** -inf == mpi(0, inf) assert mpi(1, inf) ** inf == mpi(1, inf) assert mpi(1, inf) ** -inf == mpi(0, 1) assert mpi(2, 3) ** 1 == mpi(2, 3) assert mpi(2, 3) ** 0 == 1 assert mpi(1,3) ** mpi(2) == mpi(1,9) def test_interval_sqrt(): assert mpi(4) ** 0.5 == mpi(2) def test_interval_div(): assert mpi(0.5, 1) / mpi(-1, 0) == mpi(-inf, -0.5) assert mpi(0, 1) / mpi(0, 1) == mpi(0, inf) assert mpi(inf, inf) / mpi(inf, inf) == mpi(0, inf) assert mpi(inf, inf) / mpi(2, inf) == mpi(0, inf) assert mpi(inf, inf) / mpi(2, 2) == mpi(inf, inf) assert mpi(0, inf) / mpi(2, inf) == mpi(0, inf) assert mpi(0, inf) / mpi(2, 2) == mpi(0, inf) assert mpi(2, inf) / mpi(2, 2) == mpi(1, inf) assert mpi(2, inf) / mpi(2, inf) == mpi(0, inf) assert mpi(-4, 8) / mpi(1, inf) == mpi(-4, 8) assert mpi(-4, 8) / mpi(0.5, inf) == mpi(-8, 16) assert mpi(-inf, 8) / mpi(0.5, inf) == mpi(-inf, 16) assert mpi(-inf, inf) / mpi(0.5, inf) == mpi(-inf, inf) assert mpi(8, inf) / mpi(0.5, inf) == mpi(0, inf) assert mpi(-8, inf) / mpi(0.5, inf) == mpi(-16, inf) assert mpi(-4, 8) / mpi(inf, inf) == mpi(0, 0) assert mpi(0, 8) / mpi(inf, inf) == mpi(0, 0) assert mpi(0, 0) / mpi(inf, inf) == mpi(0, 0) assert mpi(-inf, 0) / mpi(inf, inf) == mpi(-inf, 0) assert mpi(-inf, 8) / mpi(inf, inf) == mpi(-inf, 0) assert mpi(-inf, inf) / mpi(inf, inf) == mpi(-inf, inf) assert mpi(-8, inf) / mpi(inf, inf) == mpi(0, inf) assert mpi(0, inf) / mpi(inf, inf) == mpi(0, inf) assert mpi(8, inf) / mpi(inf, inf) == mpi(0, inf) assert mpi(inf, inf) / mpi(inf, inf) == mpi(0, inf) assert mpi(-1, 2) / mpi(0, 1) == mpi(-inf, +inf) assert mpi(0, 1) / mpi(0, 1) == mpi(0.0, +inf) assert mpi(-1, 0) / mpi(0, 1) == mpi(-inf, 0.0) assert mpi(-0.5, -0.25) / mpi(0, 1) == mpi(-inf, -0.25) assert mpi(0.5, 1) / mpi(0, 1) == mpi(0.5, +inf) assert mpi(0.5, 4) / mpi(0, 1) == mpi(0.5, +inf) assert mpi(-1, -0.5) / mpi(0, 1) == mpi(-inf, -0.5) assert mpi(-4, -0.5) / mpi(0, 1) == mpi(-inf, -0.5) assert mpi(-1, 2) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(0, 1) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(-1, 0) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(-0.5, -0.25) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(0.5, 1) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(0.5, 4) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(-1, -0.5) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(-4, -0.5) / mpi(-2, 0.5) == mpi(-inf, +inf) assert mpi(-1, 2) / mpi(-1, 0) == mpi(-inf, +inf) assert mpi(0, 1) / mpi(-1, 0) == mpi(-inf, 0.0) assert mpi(-1, 0) / mpi(-1, 0) == mpi(0.0, +inf) assert mpi(-0.5, -0.25) / mpi(-1, 0) == mpi(0.25, +inf) assert mpi(0.5, 1) / mpi(-1, 0) == mpi(-inf, -0.5) assert mpi(0.5, 4) / mpi(-1, 0) == mpi(-inf, -0.5) assert mpi(-1, -0.5) / mpi(-1, 0) == mpi(0.5, +inf) assert mpi(-4, -0.5) / mpi(-1, 0) == mpi(0.5, +inf) assert mpi(-1, 2) / mpi(0.5, 1) == mpi(-2.0, 4.0) assert mpi(0, 1) / mpi(0.5, 1) == mpi(0.0, 2.0) assert mpi(-1, 0) / mpi(0.5, 1) == mpi(-2.0, 0.0) assert mpi(-0.5, -0.25) / mpi(0.5, 1) == mpi(-1.0, -0.25) assert mpi(0.5, 1) / mpi(0.5, 1) == mpi(0.5, 2.0) assert mpi(0.5, 4) / mpi(0.5, 1) == mpi(0.5, 8.0) assert mpi(-1, -0.5) / mpi(0.5, 1) == mpi(-2.0, -0.5) assert mpi(-4, -0.5) / mpi(0.5, 1) == mpi(-8.0, -0.5) assert mpi(-1, 2) / mpi(-2, -0.5) == mpi(-4.0, 2.0) assert mpi(0, 1) / mpi(-2, -0.5) == mpi(-2.0, 0.0) assert mpi(-1, 0) / mpi(-2, -0.5) == mpi(0.0, 2.0) assert mpi(-0.5, -0.25) / mpi(-2, -0.5) == mpi(0.125, 1.0) assert mpi(0.5, 1) / mpi(-2, -0.5) == mpi(-2.0, -0.25) assert mpi(0.5, 4) / mpi(-2, -0.5) == mpi(-8.0, -0.25) assert mpi(-1, -0.5) / mpi(-2, -0.5) == mpi(0.25, 2.0) assert mpi(-4, -0.5) / mpi(-2, -0.5) == mpi(0.25, 8.0) # Should be undefined? assert mpi(0, 0) / mpi(0, 0) == mpi(-inf, inf) assert mpi(0, 0) / mpi(0, 1) == mpi(-inf, inf) def test_interval_cos_sin(): iv.dps = 15 cos = iv.cos sin = iv.sin tan = iv.tan pi = iv.pi # Around 0 assert cos(mpi(0)) == 1 assert sin(mpi(0)) == 0 assert cos(mpi(0,1)) == mpi(0.54030230586813965399, 1.0) assert sin(mpi(0,1)) == mpi(0, 0.8414709848078966159) assert cos(mpi(1,2)) == mpi(-0.4161468365471424069, 0.54030230586813976501) assert sin(mpi(1,2)) == mpi(0.84147098480789650488, 1.0) assert sin(mpi(1,2.5)) == mpi(0.59847214410395643824, 1.0) assert cos(mpi(-1, 1)) == mpi(0.54030230586813965399, 1.0) assert cos(mpi(-1, 0.5)) == mpi(0.54030230586813965399, 1.0) assert cos(mpi(-1, 1.5)) == mpi(0.070737201667702906405, 1.0) assert sin(mpi(-1,1)) == mpi(-0.8414709848078966159, 0.8414709848078966159) assert sin(mpi(-1,0.5)) == mpi(-0.8414709848078966159, 0.47942553860420300538) assert mpi(-0.8414709848078966159, 1.00000000000000002e-100) in sin(mpi(-1,1e-100)) assert mpi(-2.00000000000000004e-100, 1.00000000000000002e-100) in sin(mpi(-2e-100,1e-100)) # Same interval assert cos(mpi(2, 2.5)) assert cos(mpi(3.5, 4)) == mpi(-0.93645668729079634129, -0.65364362086361182946) assert cos(mpi(5, 5.5)) == mpi(0.28366218546322624627, 0.70866977429126010168) assert mpi(0.59847214410395654927, 0.90929742682568170942) in sin(mpi(2, 2.5)) assert sin(mpi(3.5, 4)) == mpi(-0.75680249530792831347, -0.35078322768961983646) assert sin(mpi(5, 5.5)) == mpi(-0.95892427466313856499, -0.70554032557039181306) # Higher roots iv.dps = 55 w = 4*10**50 + mpi(0.5) for p in [15, 40, 80]: iv.dps = p assert 0 in sin(4*mpi(pi)) assert 0 in sin(4*10**50*mpi(pi)) assert 0 in cos((4+0.5)*mpi(pi)) assert 0 in cos(w*mpi(pi)) assert 1 in cos(4*mpi(pi)) assert 1 in cos(4*10**50*mpi(pi)) iv.dps = 15 assert cos(mpi(2,inf)) == mpi(-1,1) assert sin(mpi(2,inf)) == mpi(-1,1) assert cos(mpi(-inf,2)) == mpi(-1,1) assert sin(mpi(-inf,2)) == mpi(-1,1) u = tan(mpi(0.5,1)) assert mpf(u.a).ae(mp.tan(0.5)) assert mpf(u.b).ae(mp.tan(1)) v = iv.cot(mpi(0.5,1)) assert mpf(v.a).ae(mp.cot(1)) assert mpf(v.b).ae(mp.cot(0.5)) # Sanity check of evaluation at n*pi and (n+1/2)*pi for n in range(-5,7,2): x = iv.cos(n*iv.pi) assert -1 in x assert x >= -1 assert x != -1 x = iv.sin((n+0.5)*iv.pi) assert -1 in x assert x >= -1 assert x != -1 for n in range(-6,8,2): x = iv.cos(n*iv.pi) assert 1 in x assert x <= 1 if n: assert x != 1 x = iv.sin((n+0.5)*iv.pi) assert 1 in x assert x <= 1 assert x != 1 for n in range(-6,7): x = iv.cos((n+0.5)*iv.pi) assert x.a < 0 < x.b x = iv.sin(n*iv.pi) if n: assert x.a < 0 < x.b def test_interval_complex(): # TODO: many more tests iv.dps = 15 mp.dps = 15 assert iv.mpc(2,3) == 2+3j assert iv.mpc(2,3) != 2+4j assert iv.mpc(2,3) != 1+3j assert 1+3j in iv.mpc([1,2],[3,4]) assert 2+5j not in iv.mpc([1,2],[3,4]) assert iv.mpc(1,2) + 1j == 1+3j assert iv.mpc([1,2],[2,3]) + 2+3j == iv.mpc([3,4],[5,6]) assert iv.mpc([2,4],[4,8]) / 2 == iv.mpc([1,2],[2,4]) assert iv.mpc([1,2],[2,4]) * 2j == iv.mpc([-8,-4],[2,4]) assert iv.mpc([2,4],[4,8]) / 2j == iv.mpc([2,4],[-2,-1]) assert iv.exp(2+3j).ae(mp.exp(2+3j)) assert iv.log(2+3j).ae(mp.log(2+3j)) assert (iv.mpc(2,3) ** iv.mpc(0.5,2)).ae(mp.mpc(2,3) ** mp.mpc(0.5,2)) assert 1j in (iv.mpf(-1) ** 0.5) assert 1j in (iv.mpc(-1) ** 0.5) assert abs(iv.mpc(0)) == 0 assert abs(iv.mpc(inf)) == inf assert abs(iv.mpc(3,4)) == 5 assert abs(iv.mpc(4)) == 4 assert abs(iv.mpc(0,4)) == 4 assert abs(iv.mpc(0,[2,3])) == iv.mpf([2,3]) assert abs(iv.mpc(0,[-3,2])) == iv.mpf([0,3]) assert abs(iv.mpc([3,5],[4,12])) == iv.mpf([5,13]) assert abs(iv.mpc([3,5],[-4,12])) == iv.mpf([3,13]) assert iv.mpc(2,3) ** 0 == 1 assert iv.mpc(2,3) ** 1 == (2+3j) assert iv.mpc(2,3) ** 2 == (2+3j)**2 assert iv.mpc(2,3) ** 3 == (2+3j)**3 assert iv.mpc(2,3) ** 4 == (2+3j)**4 assert iv.mpc(2,3) ** 5 == (2+3j)**5 assert iv.mpc(2,2) ** (-1) == (2+2j) ** (-1) assert iv.mpc(2,2) ** (-2) == (2+2j) ** (-2) assert iv.cos(2).ae(mp.cos(2)) assert iv.sin(2).ae(mp.sin(2)) assert iv.cos(2+3j).ae(mp.cos(2+3j)) assert iv.sin(2+3j).ae(mp.sin(2+3j)) def test_interval_complex_arg(): mp.dps = 15 iv.dps = 15 assert iv.arg(3) == 0 assert iv.arg(0) == 0 assert iv.arg([0,3]) == 0 assert iv.arg(-3).ae(pi) assert iv.arg(2+3j).ae(iv.arg(2+3j)) z = iv.mpc([-2,-1],[3,4]) t = iv.arg(z) assert t.a.ae(mp.arg(-1+4j)) assert t.b.ae(mp.arg(-2+3j)) z = iv.mpc([-2,1],[3,4]) t = iv.arg(z) assert t.a.ae(mp.arg(1+3j)) assert t.b.ae(mp.arg(-2+3j)) z = iv.mpc([1,2],[3,4]) t = iv.arg(z) assert t.a.ae(mp.arg(2+3j)) assert t.b.ae(mp.arg(1+4j)) z = iv.mpc([1,2],[-2,3]) t = iv.arg(z) assert t.a.ae(mp.arg(1-2j)) assert t.b.ae(mp.arg(1+3j)) z = iv.mpc([1,2],[-4,-3]) t = iv.arg(z) assert t.a.ae(mp.arg(1-4j)) assert t.b.ae(mp.arg(2-3j)) z = iv.mpc([-1,2],[-4,-3]) t = iv.arg(z) assert t.a.ae(mp.arg(-1-3j)) assert t.b.ae(mp.arg(2-3j)) z = iv.mpc([-2,-1],[-4,-3]) t = iv.arg(z) assert t.a.ae(mp.arg(-2-3j)) assert t.b.ae(mp.arg(-1-4j)) z = iv.mpc([-2,-1],[-3,3]) t = iv.arg(z) assert t.a.ae(-mp.pi) assert t.b.ae(mp.pi) z = iv.mpc([-2,2],[-3,3]) t = iv.arg(z) assert t.a.ae(-mp.pi) assert t.b.ae(mp.pi) def test_interval_ae(): iv.dps = 15 x = iv.mpf([1,2]) assert x.ae(1) is None assert x.ae(1.5) is None assert x.ae(2) is None assert x.ae(2.01) is False assert x.ae(0.99) is False x = iv.mpf(3.5) assert x.ae(3.5) is True assert x.ae(3.5+1e-15) is True assert x.ae(3.5-1e-15) is True assert x.ae(3.501) is False assert x.ae(3.499) is False assert x.ae(iv.mpf([3.5,3.501])) is None assert x.ae(iv.mpf([3.5,4.5+1e-15])) is None def test_interval_nstr(): iv.dps = n = 30 x = mpi(1, 2) # FIXME: error_dps should not be necessary assert iv.nstr(x, n, mode='plusminus', error_dps=6) == '1.5 +- 0.5' assert iv.nstr(x, n, mode='plusminus', use_spaces=False, error_dps=6) == '1.5+-0.5' assert iv.nstr(x, n, mode='percent') == '1.5 (33.33%)' assert iv.nstr(x, n, mode='brackets', use_spaces=False) == '[1.0,2.0]' assert iv.nstr(x, n, mode='brackets' , brackets=('<', '>')) == '<1.0, 2.0>' x = mpi('5.2582327113062393041', '5.2582327113062749951') assert iv.nstr(x, n, mode='diff') == '5.2582327113062[393041, 749951]' assert iv.nstr(iv.cos(mpi(1)), n, mode='diff', use_spaces=False) == '0.54030230586813971740093660744[2955,3053]' assert iv.nstr(mpi('1e123', '1e129'), n, mode='diff') == '[1.0e+123, 1.0e+129]' exp = iv.exp assert iv.nstr(iv.exp(mpi('5000.1')), n, mode='diff') == '3.2797365856787867069110487[0926, 1191]e+2171' iv.dps = 15 def test_mpi_from_str(): iv.dps = 15 assert iv.convert('1.5 +- 0.5') == mpi(mpf('1.0'), mpf('2.0')) assert mpi(1, 2) in iv.convert('1.5 (33.33333333333333333333333333333%)') assert iv.convert('[1, 2]') == mpi(1, 2) assert iv.convert('1[2, 3]') == mpi(12, 13) assert iv.convert('1.[23,46]e-8') == mpi('1.23e-8', '1.46e-8') assert iv.convert('12[3.4,5.9]e4') == mpi('123.4e+4', '125.9e4') def test_interval_gamma(): mp.dps = 15 iv.dps = 15 # TODO: need many more tests assert iv.rgamma(0) == 0 assert iv.fac(0) == 1 assert iv.fac(1) == 1 assert iv.fac(2) == 2 assert iv.fac(3) == 6 assert iv.gamma(0) == [-inf,inf] assert iv.gamma(1) == 1 assert iv.gamma(2) == 1 assert iv.gamma(3) == 2 assert -3.5449077018110320546 in iv.gamma(-0.5) assert iv.loggamma(1) == 0 assert iv.loggamma(2) == 0 assert 0.69314718055994530942 in iv.loggamma(3) # Test tight log-gamma endpoints based on monotonicity xs = [iv.mpc([2,3],[1,4]), iv.mpc([2,3],[-4,-1]), iv.mpc([2,3],[-1,4]), iv.mpc([2,3],[-4,1]), iv.mpc([2,3],[-4,4]), iv.mpc([-3,-2],[2,4]), iv.mpc([-3,-2],[-4,-2])] for x in xs: ys = [mp.loggamma(mp.mpc(x.a,x.c)), mp.loggamma(mp.mpc(x.b,x.c)), mp.loggamma(mp.mpc(x.a,x.d)), mp.loggamma(mp.mpc(x.b,x.d))] if 0 in x.imag: ys += [mp.loggamma(x.a), mp.loggamma(x.b)] min_real = min([y.real for y in ys]) max_real = max([y.real for y in ys]) min_imag = min([y.imag for y in ys]) max_imag = max([y.imag for y in ys]) z = iv.loggamma(x) assert z.a.ae(min_real) assert z.b.ae(max_real) assert z.c.ae(min_imag) assert z.d.ae(max_imag) mpmath-1.1.0/mpmath/tests/test_levin.py000066400000000000000000000117421340375245600201730ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- from mpmath import mp from mpmath import libmp xrange = libmp.backend.xrange # Attention: # These tests run with 15-20 decimal digits precision. For higher precision the # working precision must be raised. def test_levin_0(): mp.dps = 17 eps = mp.mpf(mp.eps) with mp.extraprec(2 * mp.prec): L = mp.levin(method = "levin", variant = "u") S, s, n = [], 0, 1 while 1: s += mp.one / (n * n) n += 1 S.append(s) v, e = L.update_psum(S) if e < eps: break if n > 1000: raise RuntimeError("iteration limit exceeded") eps = mp.exp(0.9 * mp.log(eps)) err = abs(v - mp.pi ** 2 / 6) assert err < eps w = mp.nsum(lambda n: 1/(n * n), [1, mp.inf], method = "levin", levin_variant = "u") err = abs(v - w) assert err < eps def test_levin_1(): mp.dps = 17 eps = mp.mpf(mp.eps) with mp.extraprec(2 * mp.prec): L = mp.levin(method = "levin", variant = "v") A, n = [], 1 while 1: s = mp.mpf(n) ** (2 + 3j) n += 1 A.append(s) v, e = L.update(A) if e < eps: break if n > 1000: raise RuntimeError("iteration limit exceeded") eps = mp.exp(0.9 * mp.log(eps)) err = abs(v - mp.zeta(-2-3j)) assert err < eps w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = "levin", levin_variant = "v") err = abs(v - w) assert err < eps def test_levin_2(): # [2] A. Sidi - "Pratical Extrapolation Methods" p.373 mp.dps = 17 z=mp.mpf(10) eps = mp.mpf(mp.eps) with mp.extraprec(2 * mp.prec): L = mp.levin(method = "sidi", variant = "t") n = 0 while 1: s = (-1)**n * mp.fac(n) * z ** (-n) v, e = L.step(s) n += 1 if e < eps: break if n > 1000: raise RuntimeError("iteration limit exceeded") eps = mp.exp(0.9 * mp.log(eps)) exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf]) # there is also a symbolic expression for the integral: # exact = z * mp.exp(z) * mp.expint(1,z) err = abs(v - exact) assert err < eps w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = "sidi", levin_variant = "t") assert err < eps def test_levin_3(): mp.dps = 17 z=mp.mpf(2) eps = mp.mpf(mp.eps) with mp.extraprec(7*mp.prec): # we need copious amount of precision to sum this highly divergent series L = mp.levin(method = "levin", variant = "t") n, s = 0, 0 while 1: s += (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)) n += 1 v, e = L.step_psum(s) if e < eps: break if n > 1000: raise RuntimeError("iteration limit exceeded") eps = mp.exp(0.8 * mp.log(eps)) exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 * mp.pi) # there is also a symbolic expression for the integral: # exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt(z * mp.pi)) err = abs(v - exact) assert err < eps w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)), [0, mp.inf], method = "levin", levin_variant = "t", workprec = 8*mp.prec, steps = [2] + [1 for x in xrange(1000)]) err = abs(v - w) assert err < eps def test_levin_nsum(): mp.dps = 17 with mp.extraprec(mp.prec): z = mp.mpf(10) ** (-10) a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = "l") - 1 / z assert abs(a - mp.euler) < 1e-10 eps = mp.exp(0.8 * mp.log(mp.eps)) a = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "sidi") assert abs(a - mp.log(2)) < eps z = 2 + 1j f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3), n) * mp.fac(n)) v = mp.nsum(f, [0, mp.inf], method = "levin", steps = [10 for x in xrange(1000)]) exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z) assert abs(exact - v) < eps def test_cohen_alt_0(): mp.dps = 17 AC = mp.cohen_alt() S, s, n = [], 0, 1 while 1: s += -((-1) ** n) * mp.one / (n * n) n += 1 S.append(s) v, e = AC.update_psum(S) if e < mp.eps: break if n > 1000: raise RuntimeError("iteration limit exceeded") eps = mp.exp(0.9 * mp.log(mp.eps)) err = abs(v - mp.pi ** 2 / 12) assert err < eps def test_cohen_alt_1(): mp.dps = 17 A = [] AC = mp.cohen_alt() n = 1 while 1: A.append( mp.loggamma(1 + mp.one / (2 * n - 1))) A.append(-mp.loggamma(1 + mp.one / (2 * n))) n += 1 v, e = AC.update(A) if e < mp.eps: break if n > 1000: raise RuntimeError("iteration limit exceeded") v = mp.exp(v) err = abs(v - 1.06215090557106) assert err < 1e-12 mpmath-1.1.0/mpmath/tests/test_linalg.py000066400000000000000000000243301340375245600203210ustar00rootroot00000000000000# TODO: don't use round from __future__ import division import pytest from mpmath import * xrange = libmp.backend.xrange # XXX: these shouldn't be visible(?) LU_decomp = mp.LU_decomp L_solve = mp.L_solve U_solve = mp.U_solve householder = mp.householder improve_solution = mp.improve_solution A1 = matrix([[3, 1, 6], [2, 1, 3], [1, 1, 1]]) b1 = [2, 7, 4] A2 = matrix([[ 2, -1, -1, 2], [ 6, -2, 3, -1], [-4, 2, 3, -2], [ 2, 0, 4, -3]]) b2 = [3, -3, -2, -1] A3 = matrix([[ 1, 0, -1, -1, 0], [ 0, 1, 1, 0, -1], [ 4, -5, 2, 0, 0], [ 0, 0, -2, 9,-12], [ 0, 5, 0, 0, 12]]) b3 = [0, 0, 0, 0, 50] A4 = matrix([[10.235, -4.56, 0., -0.035, 5.67], [-2.463, 1.27, 3.97, -8.63, 1.08], [-6.58, 0.86, -0.257, 9.32, -43.6 ], [ 9.83, 7.39, -17.25, 0.036, 24.86], [-9.31, 34.9, 78.56, 1.07, 65.8 ]]) b4 = [8.95, 20.54, 7.42, 5.60, 58.43] A5 = matrix([[ 1, 2, -4], [-2, -3, 5], [ 3, 5, -8]]) A6 = matrix([[ 1.377360, 2.481400, 5.359190], [ 2.679280, -1.229560, 25.560210], [-1.225280+1.e6, 9.910180, -35.049900-1.e6]]) b6 = [23.500000, -15.760000, 2.340000] A7 = matrix([[1, -0.5], [2, 1], [-2, 6]]) b7 = [3, 2, -4] A8 = matrix([[1, 2, 3], [-1, 0, 1], [-1, -2, -1], [1, 0, -1]]) b8 = [1, 2, 3, 4] A9 = matrix([[ 4, 2, -2], [ 2, 5, -4], [-2, -4, 5.5]]) b9 = [10, 16, -15.5] A10 = matrix([[1.0 + 1.0j, 2.0, 2.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) b10 = [1.0, 1.0 + 1.0j, 1.0] def test_LU_decomp(): A = A3.copy() b = b3 A, p = LU_decomp(A) y = L_solve(A, b, p) x = U_solve(A, y) assert p == [2, 1, 2, 3] assert [round(i, 14) for i in x] == [3.78953107960742, 2.9989094874591098, -0.081788440567070006, 3.8713195201744801, 2.9171210468920399] A = A4.copy() b = b4 A, p = LU_decomp(A) y = L_solve(A, b, p) x = U_solve(A, y) assert p == [0, 3, 4, 3] assert [round(i, 14) for i in x] == [2.6383625899619201, 2.6643834462368399, 0.79208015947958998, -2.5088376454101899, -1.0567657691375001] A = randmatrix(3) bak = A.copy() LU_decomp(A, overwrite=1) assert A != bak def test_inverse(): for A in [A1, A2, A5]: inv = inverse(A) assert mnorm(A*inv - eye(A.rows), 1) < 1.e-14 def test_householder(): mp.dps = 15 A, b = A8, b8 H, p, x, r = householder(extend(A, b)) assert H == matrix( [[mpf('3.0'), mpf('-2.0'), mpf('-1.0'), 0], [-1.0,mpf('3.333333333333333'),mpf('-2.9999999999999991'),mpf('2.0')], [-1.0, mpf('-0.66666666666666674'),mpf('2.8142135623730948'), mpf('-2.8284271247461898')], [1.0, mpf('-1.3333333333333333'),mpf('-0.20000000000000018'), mpf('4.2426406871192857')]]) assert p == [-2, -2, mpf('-1.4142135623730949')] assert round(norm(r, 2), 10) == 4.2426406870999998 y = [102.102, 58.344, 36.463, 24.310, 17.017, 12.376, 9.282, 7.140, 5.610, 4.488, 3.6465, 3.003] def coeff(n): # similiar to Hilbert matrix A = [] for i in range(1, 13): A.append([1. / (i + j - 1) for j in range(1, n + 1)]) return matrix(A) residuals = [] refres = [] for n in range(2, 7): A = coeff(n) H, p, x, r = householder(extend(A, y)) x = matrix(x) y = matrix(y) residuals.append(norm(r, 2)) refres.append(norm(residual(A, x, y), 2)) assert [round(res, 10) for res in residuals] == [15.1733888877, 0.82378073210000002, 0.302645887, 0.0260109244, 0.00058653999999999998] assert norm(matrix(residuals) - matrix(refres), inf) < 1.e-13 def hilbert_cmplx(n): # Complexified Hilbert matrix A = hilbert(2*n,n) v = randmatrix(2*n, 2, min=-1, max=1) v = v.apply(lambda x: exp(1J*pi()*x)) A = diag(v[:,0])*A*diag(v[:n,1]) return A residuals_cmplx = [] refres_cmplx = [] for n in range(2, 10): A = hilbert_cmplx(n) H, p, x, r = householder(A.copy()) residuals_cmplx.append(norm(r, 2)) refres_cmplx.append(norm(residual(A[:,:n-1], x, A[:,n-1]), 2)) assert norm(matrix(residuals_cmplx) - matrix(refres_cmplx), inf) < 1.e-13 def test_factorization(): A = randmatrix(5) P, L, U = lu(A) assert mnorm(P*A - L*U, 1) < 1.e-15 def test_solve(): assert norm(residual(A6, lu_solve(A6, b6), b6), inf) < 1.e-10 assert norm(residual(A7, lu_solve(A7, b7), b7), inf) < 1.5 assert norm(residual(A8, lu_solve(A8, b8), b8), inf) <= 3 + 1.e-10 assert norm(residual(A6, qr_solve(A6, b6)[0], b6), inf) < 1.e-10 assert norm(residual(A7, qr_solve(A7, b7)[0], b7), inf) < 1.5 assert norm(residual(A8, qr_solve(A8, b8)[0], b8), 2) <= 4.3 assert norm(residual(A10, lu_solve(A10, b10), b10), 2) < 1.e-10 assert norm(residual(A10, qr_solve(A10, b10)[0], b10), 2) < 1.e-10 def test_solve_overdet_complex(): A = matrix([[1, 2j], [3, 4j], [5, 6]]) b = matrix([1 + j, 2, -j]) assert norm(residual(A, lu_solve(A, b), b)) < 1.0208 def test_singular(): mp.dps = 15 A = [[5.6, 1.2], [7./15, .1]] B = repr(zeros(2)) b = [1, 2] for i in ['lu_solve(%s, %s)' % (A, b), 'lu_solve(%s, %s)' % (B, b), 'qr_solve(%s, %s)' % (A, b), 'qr_solve(%s, %s)' % (B, b)]: pytest.raises((ZeroDivisionError, ValueError), lambda: eval(i)) def test_cholesky(): assert fp.cholesky(fp.matrix(A9)) == fp.matrix([[2, 0, 0], [1, 2, 0], [-1, -3/2, 3/2]]) x = fp.cholesky_solve(A9, b9) assert fp.norm(fp.residual(A9, x, b9), fp.inf) == 0 def test_det(): assert det(A1) == 1 assert round(det(A2), 14) == 8 assert round(det(A3)) == 1834 assert round(det(A4)) == 4443376 assert det(A5) == 1 assert round(det(A6)) == 78356463 assert det(zeros(3)) == 0 def test_cond(): mp.dps = 15 A = matrix([[1.2969, 0.8648], [0.2161, 0.1441]]) assert cond(A, lambda x: mnorm(x,1)) == mpf('327065209.73817754') assert cond(A, lambda x: mnorm(x,inf)) == mpf('327065209.73817754') assert cond(A, lambda x: mnorm(x,'F')) == mpf('249729266.80008656') @extradps(50) def test_precision(): A = randmatrix(10, 10) assert mnorm(inverse(inverse(A)) - A, 1) < 1.e-45 def test_interval_matrix(): mp.dps = 15 iv.dps = 15 a = iv.matrix([['0.1','0.3','1.0'],['7.1','5.5','4.8'],['3.2','4.4','5.6']]) b = iv.matrix(['4','0.6','0.5']) c = iv.lu_solve(a, b) assert c[0].delta < 1e-13 assert c[1].delta < 1e-13 assert c[2].delta < 1e-13 assert 5.25823271130625686059275 in c[0] assert -13.155049396267837541163 in c[1] assert 7.42069154774972557628979 in c[2] def test_LU_cache(): A = randmatrix(3) LU = LU_decomp(A) assert A._LU == LU_decomp(A) A[0,0] = -1000 assert A._LU is None def test_improve_solution(): A = randmatrix(5, min=1e-20, max=1e20) b = randmatrix(5, 1, min=-1000, max=1000) x1 = lu_solve(A, b) + randmatrix(5, 1, min=-1e-5, max=1.e-5) x2 = improve_solution(A, x1, b) assert norm(residual(A, x2, b), 2) < norm(residual(A, x1, b), 2) def test_exp_pade(): for i in range(3): dps = 15 extra = 15 mp.dps = dps + extra dm = 0 N = 3 dg = range(1,N+1) a = diag(dg) expa = diag([exp(x) for x in dg]) # choose a random matrix not close to be singular # to avoid adding too much extra precision in computing # m**-1 * M * m while abs(dm) < 0.01: m = randmatrix(N) dm = det(m) m = m/dm a1 = m**-1 * a * m e2 = m**-1 * expa * m mp.dps = dps e1 = expm(a1, method='pade') mp.dps = dps + extra d = e2 - e1 #print d mp.dps = dps assert norm(d, inf).ae(0) mp.dps = 15 def test_qr(): mp.dps = 15 # used default value for dps lowlimit = -9 # lower limit of matrix element value uplimit = 9 # uppter limit of matrix element value maxm = 4 # max matrix size flg = False # toggle to create real vs complex matrix zero = mpf('0.0') for k in xrange(0,10): exdps = 0 mode = 'full' flg = bool(k % 2) # generate arbitrary matrix size (2 to maxm) num1 = nint(2 + (maxm-2)*rand()) num2 = nint(2 + (maxm-2)*rand()) m = int(max(num1, num2)) n = int(min(num1, num2)) # create matrix A = mp.matrix(m,n) # populate matrix values with arbitrary integers if flg: flg = False dtype = 'complex' for j in xrange(0,n): for i in xrange(0,m): val = nint(lowlimit + (uplimit-lowlimit)*rand()) val2 = nint(lowlimit + (uplimit-lowlimit)*rand()) A[i,j] = mpc(val, val2) else: flg = True dtype = 'real' for j in xrange(0,n): for i in xrange(0,m): val = nint(lowlimit + (uplimit-lowlimit)*rand()) A[i,j] = mpf(val) # perform A -> QR decomposition Q, R = qr(A, mode, edps = exdps) #print('\n\n A = \n', nstr(A, 4)) #print('\n Q = \n', nstr(Q, 4)) #print('\n R = \n', nstr(R, 4)) #print('\n Q*R = \n', nstr(Q*R, 4)) maxnorm = mpf('1.0E-11') n1 = norm(A - Q * R) #print '\n Norm of A - Q * R = ', n1 assert n1 <= maxnorm if dtype == 'real': n1 = norm(eye(m) - Q.T * Q) #print ' Norm of I - Q.T * Q = ', n1 assert n1 <= maxnorm n1 = norm(eye(m) - Q * Q.T) #print ' Norm of I - Q * Q.T = ', n1 assert n1 <= maxnorm if dtype == 'complex': n1 = norm(eye(m) - Q.T * Q.conjugate()) #print ' Norm of I - Q.T * Q.conjugate() = ', n1 assert n1 <= maxnorm n1 = norm(eye(m) - Q.conjugate() * Q.T) #print ' Norm of I - Q.conjugate() * Q.T = ', n1 assert n1 <= maxnorm mpmath-1.1.0/mpmath/tests/test_matrices.py000066400000000000000000000124521340375245600206640ustar00rootroot00000000000000import pytest from mpmath import * def test_matrix_basic(): A1 = matrix(3) for i in range(3): A1[i,i] = 1 assert A1 == eye(3) assert A1 == matrix(A1) A2 = matrix(3, 2) assert not A2._matrix__data A3 = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) assert list(A3) == list(range(1, 10)) A3[1,1] = 0 assert not (1, 1) in A3._matrix__data A4 = matrix([[1, 2, 3], [4, 5, 6]]) A5 = matrix([[6, -1], [3, 2], [0, -3]]) assert A4 * A5 == matrix([[12, -6], [39, -12]]) assert A1 * A3 == A3 * A1 == A3 pytest.raises(ValueError, lambda: A2*A2) l = [[10, 20, 30], [40, 0, 60], [70, 80, 90]] A6 = matrix(l) assert A6.tolist() == l assert A6 == eval(repr(A6)) A6 = matrix(A6, force_type=float) assert A6 == eval(repr(A6)) assert A6*1j == eval(repr(A6*1j)) assert A3 * 10 == 10 * A3 == A6 assert A2.rows == 3 assert A2.cols == 2 A3.rows = 2 A3.cols = 2 assert len(A3._matrix__data) == 3 assert A4 + A4 == 2*A4 pytest.raises(ValueError, lambda: A4 + A2) assert sum(A1 - A1) == 0 A7 = matrix([[1, 2], [3, 4], [5, 6], [7, 8]]) x = matrix([10, -10]) assert A7*x == matrix([-10, -10, -10, -10]) A8 = ones(5) assert sum((A8 + 1) - (2 - zeros(5))) == 0 assert (1 + ones(4)) / 2 - 1 == zeros(4) assert eye(3)**10 == eye(3) pytest.raises(ValueError, lambda: A7**2) A9 = randmatrix(3) A10 = matrix(A9) A9[0,0] = -100 assert A9 != A10 assert nstr(A9) def test_matrix_slices(): A = matrix([ [1, 2, 3], [4, 5 ,6], [7, 8 ,9]]) V = matrix([1,2,3,4,5]) # Get slice assert A[:,:] == A assert A[:,1] == matrix([[2],[5],[8]]) assert A[2,:] == matrix([[7, 8 ,9]]) assert A[1:3,1:3] == matrix([[5,6],[8,9]]) assert V[2:4] == matrix([3,4]) pytest.raises(IndexError, lambda: A[:,1:6]) # Assign slice with matrix A1 = matrix(3) A1[:,:] = A assert A1[:,:] == matrix([[1, 2, 3], [4, 5 ,6], [7, 8 ,9]]) A1[0,:] = matrix([[10, 11, 12]]) assert A1 == matrix([ [10, 11, 12], [4, 5 ,6], [7, 8 ,9]]) A1[:,2] = matrix([[13], [14], [15]]) assert A1 == matrix([ [10, 11, 13], [4, 5 ,14], [7, 8 ,15]]) A1[:2,:2] = matrix([[16, 17], [18 , 19]]) assert A1 == matrix([ [16, 17, 13], [18, 19 ,14], [7, 8 ,15]]) V[1:3] = 10 assert V == matrix([1,10,10,4,5]) with pytest.raises(ValueError): A1[2,:] = A[:,1] with pytest.raises(IndexError): A1[2,1:20] = A[:,:] # Assign slice with scalar A1[:,2] = 10 assert A1 == matrix([ [16, 17, 10], [18, 19 ,10], [7, 8 ,10]]) A1[:,:] = 40 for x in A1: assert x == 40 def test_matrix_power(): A = matrix([[1, 2], [3, 4]]) assert A**2 == A*A assert A**3 == A*A*A assert A**-1 == inverse(A) assert A**-2 == inverse(A*A) def test_matrix_transform(): A = matrix([[1, 2], [3, 4], [5, 6]]) assert A.T == A.transpose() == matrix([[1, 3, 5], [2, 4, 6]]) swap_row(A, 1, 2) assert A == matrix([[1, 2], [5, 6], [3, 4]]) l = [1, 2] swap_row(l, 0, 1) assert l == [2, 1] assert extend(eye(3), [1,2,3]) == matrix([[1,0,0,1],[0,1,0,2],[0,0,1,3]]) def test_matrix_conjugate(): A = matrix([[1 + j, 0], [2, j]]) assert A.conjugate() == matrix([[mpc(1, -1), 0], [2, mpc(0, -1)]]) assert A.transpose_conj() == A.H == matrix([[mpc(1, -1), 2], [0, mpc(0, -1)]]) def test_matrix_creation(): assert diag([1, 2, 3]) == matrix([[1, 0, 0], [0, 2, 0], [0, 0, 3]]) A1 = ones(2, 3) assert A1.rows == 2 and A1.cols == 3 for a in A1: assert a == 1 A2 = zeros(3, 2) assert A2.rows == 3 and A2.cols == 2 for a in A2: assert a == 0 assert randmatrix(10) != randmatrix(10) one = mpf(1) assert hilbert(3) == matrix([[one, one/2, one/3], [one/2, one/3, one/4], [one/3, one/4, one/5]]) def test_norms(): # matrix norms A = matrix([[1, -2], [-3, -1], [2, 1]]) assert mnorm(A,1) == 6 assert mnorm(A,inf) == 4 assert mnorm(A,'F') == sqrt(20) # vector norms assert norm(-3) == 3 x = [1, -2, 7, -12] assert norm(x, 1) == 22 assert round(norm(x, 2), 10) == 14.0712472795 assert round(norm(x, 10), 10) == 12.0054633727 assert norm(x, inf) == 12 def test_vector(): x = matrix([0, 1, 2, 3, 4]) assert x == matrix([[0], [1], [2], [3], [4]]) assert x[3] == 3 assert len(x._matrix__data) == 4 assert list(x) == list(range(5)) x[0] = -10 x[4] = 0 assert x[0] == -10 assert len(x) == len(x.T) == 5 assert x.T*x == matrix([[114]]) def test_matrix_copy(): A = ones(6) B = A.copy() assert A == B B[0,0] = 0 assert A != B def test_matrix_numpy(): try: import numpy except ImportError: return l = [[1, 2], [3, 4], [5, 6]] a = numpy.array(l) assert matrix(l) == matrix(a) mpmath-1.1.0/mpmath/tests/test_mpmath.py000066400000000000000000000003041340375245600203340ustar00rootroot00000000000000from mpmath.libmp import * from mpmath import * def test_newstyle_classes(): for cls in [mp, fp, iv, mpf, mpc]: for s in cls.__class__.__mro__: assert isinstance(s, type) mpmath-1.1.0/mpmath/tests/test_ode.py000066400000000000000000000034361340375245600176260ustar00rootroot00000000000000#from mpmath.calculus import ODE_step_euler, ODE_step_rk4, odeint, arange from mpmath import odefun, cos, sin, mpf, sinc, mp ''' solvers = [ODE_step_euler, ODE_step_rk4] def test_ode1(): """ Let's solve: x'' + w**2 * x = 0 i.e. x1 = x, x2 = x1': x1' = x2 x2' = -x1 """ def derivs((x1, x2), t): return x2, -x1 for solver in solvers: t = arange(0, 3.1415926, 0.005) sol = odeint(derivs, (0., 1.), t, solver) x1 = [a[0] for a in sol] x2 = [a[1] for a in sol] # the result is x1 = sin(t), x2 = cos(t) # let's just check the end points for t = pi assert abs(x1[-1]) < 1e-2 assert abs(x2[-1] - (-1)) < 1e-2 def test_ode2(): """ Let's solve: x' - x = 0 i.e. x = exp(x) """ def derivs((x), t): return x for solver in solvers: t = arange(0, 1, 1e-3) sol = odeint(derivs, (1.,), t, solver) x = [a[0] for a in sol] # the result is x = exp(t) # let's just check the end point for t = 1, i.e. x = e assert abs(x[-1] - 2.718281828) < 1e-2 ''' def test_odefun_rational(): mp.dps = 15 # A rational function f = lambda t: 1/(1+mpf(t)**2) g = odefun(lambda x, y: [-2*x*y[0]**2], 0, [f(0)]) assert f(2).ae(g(2)[0]) def test_odefun_sinc_large(): mp.dps = 15 # Sinc function; test for large x f = sinc g = odefun(lambda x, y: [(cos(x)-y[0])/x], 1, [f(1)], tol=0.01, degree=5) assert abs(f(100) - g(100)[0])/f(100) < 0.01 def test_odefun_harmonic(): mp.dps = 15 # Harmonic oscillator f = odefun(lambda x, y: [-y[1], y[0]], 0, [1, 0]) for x in [0, 1, 2.5, 8, 3.7]: # we go back to 3.7 to check caching c, s = f(x) assert c.ae(cos(x)) assert s.ae(sin(x)) mpmath-1.1.0/mpmath/tests/test_pickle.py000066400000000000000000000006211340375245600203170ustar00rootroot00000000000000import os import tempfile import pickle from mpmath import * def pickler(obj): fn = tempfile.mktemp() f = open(fn, 'wb') pickle.dump(obj, f) f.close() f = open(fn, 'rb') obj2 = pickle.load(f) f.close() os.remove(fn) return obj2 def test_pickle(): obj = mpf('0.5') assert obj == pickler(obj) obj = mpc('0.5','0.2') assert obj == pickler(obj) mpmath-1.1.0/mpmath/tests/test_power.py000066400000000000000000000121531340375245600202070ustar00rootroot00000000000000from mpmath import * from mpmath.libmp import * import random def test_fractional_pow(): mp.dps = 15 assert mpf(16) ** 2.5 == 1024 assert mpf(64) ** 0.5 == 8 assert mpf(64) ** -0.5 == 0.125 assert mpf(16) ** -2.5 == 0.0009765625 assert (mpf(10) ** 0.5).ae(3.1622776601683791) assert (mpf(10) ** 2.5).ae(316.2277660168379) assert (mpf(10) ** -0.5).ae(0.31622776601683794) assert (mpf(10) ** -2.5).ae(0.0031622776601683794) assert (mpf(10) ** 0.3).ae(1.9952623149688795) assert (mpf(10) ** -0.3).ae(0.50118723362727224) def test_pow_integer_direction(): """ Test that inexact integer powers are rounded in the right direction. """ random.seed(1234) for prec in [10, 53, 200]: for i in range(50): a = random.randint(1<<(prec-1), 1< ab def test_pow_epsilon_rounding(): """ Stress test directed rounding for powers with integer exponents. Basically, we look at the following cases: >>> 1.0001 ** -5 # doctest: +SKIP 0.99950014996500702 >>> 0.9999 ** -5 # doctest: +SKIP 1.000500150035007 >>> (-1.0001) ** -5 # doctest: +SKIP -0.99950014996500702 >>> (-0.9999) ** -5 # doctest: +SKIP -1.000500150035007 >>> 1.0001 ** -6 # doctest: +SKIP 0.99940020994401269 >>> 0.9999 ** -6 # doctest: +SKIP 1.0006002100560125 >>> (-1.0001) ** -6 # doctest: +SKIP 0.99940020994401269 >>> (-0.9999) ** -6 # doctest: +SKIP 1.0006002100560125 etc. We run the tests with values a very small epsilon away from 1: small enough that the result is indistinguishable from 1 when rounded to nearest at the output precision. We check that the result is not erroneously rounded to 1 in cases where the rounding should be done strictly away from 1. """ def powr(x, n, r): return make_mpf(mpf_pow_int(x._mpf_, n, mp.prec, r)) for (inprec, outprec) in [(100, 20), (5000, 3000)]: mp.prec = inprec pos10001 = mpf(1) + mpf(2)**(-inprec+5) pos09999 = mpf(1) - mpf(2)**(-inprec+5) neg10001 = -pos10001 neg09999 = -pos09999 mp.prec = outprec r = round_up assert powr(pos10001, 5, r) > 1 assert powr(pos09999, 5, r) == 1 assert powr(neg10001, 5, r) < -1 assert powr(neg09999, 5, r) == -1 assert powr(pos10001, 6, r) > 1 assert powr(pos09999, 6, r) == 1 assert powr(neg10001, 6, r) > 1 assert powr(neg09999, 6, r) == 1 assert powr(pos10001, -5, r) == 1 assert powr(pos09999, -5, r) > 1 assert powr(neg10001, -5, r) == -1 assert powr(neg09999, -5, r) < -1 assert powr(pos10001, -6, r) == 1 assert powr(pos09999, -6, r) > 1 assert powr(neg10001, -6, r) == 1 assert powr(neg09999, -6, r) > 1 r = round_down assert powr(pos10001, 5, r) == 1 assert powr(pos09999, 5, r) < 1 assert powr(neg10001, 5, r) == -1 assert powr(neg09999, 5, r) > -1 assert powr(pos10001, 6, r) == 1 assert powr(pos09999, 6, r) < 1 assert powr(neg10001, 6, r) == 1 assert powr(neg09999, 6, r) < 1 assert powr(pos10001, -5, r) < 1 assert powr(pos09999, -5, r) == 1 assert powr(neg10001, -5, r) > -1 assert powr(neg09999, -5, r) == -1 assert powr(pos10001, -6, r) < 1 assert powr(pos09999, -6, r) == 1 assert powr(neg10001, -6, r) < 1 assert powr(neg09999, -6, r) == 1 r = round_ceiling assert powr(pos10001, 5, r) > 1 assert powr(pos09999, 5, r) == 1 assert powr(neg10001, 5, r) == -1 assert powr(neg09999, 5, r) > -1 assert powr(pos10001, 6, r) > 1 assert powr(pos09999, 6, r) == 1 assert powr(neg10001, 6, r) > 1 assert powr(neg09999, 6, r) == 1 assert powr(pos10001, -5, r) == 1 assert powr(pos09999, -5, r) > 1 assert powr(neg10001, -5, r) > -1 assert powr(neg09999, -5, r) == -1 assert powr(pos10001, -6, r) == 1 assert powr(pos09999, -6, r) > 1 assert powr(neg10001, -6, r) == 1 assert powr(neg09999, -6, r) > 1 r = round_floor assert powr(pos10001, 5, r) == 1 assert powr(pos09999, 5, r) < 1 assert powr(neg10001, 5, r) < -1 assert powr(neg09999, 5, r) == -1 assert powr(pos10001, 6, r) == 1 assert powr(pos09999, 6, r) < 1 assert powr(neg10001, 6, r) == 1 assert powr(neg09999, 6, r) < 1 assert powr(pos10001, -5, r) < 1 assert powr(pos09999, -5, r) == 1 assert powr(neg10001, -5, r) == -1 assert powr(neg09999, -5, r) < -1 assert powr(pos10001, -6, r) < 1 assert powr(pos09999, -6, r) == 1 assert powr(neg10001, -6, r) < 1 assert powr(neg09999, -6, r) == 1 mp.dps = 15 mpmath-1.1.0/mpmath/tests/test_quad.py000066400000000000000000000072521340375245600200110ustar00rootroot00000000000000import pytest from mpmath import * def ae(a, b): return abs(a-b) < 10**(-mp.dps+5) def test_basic_integrals(): for prec in [15, 30, 100]: mp.dps = prec assert ae(quadts(lambda x: x**3 - 3*x**2, [-2, 4]), -12) assert ae(quadgl(lambda x: x**3 - 3*x**2, [-2, 4]), -12) assert ae(quadts(sin, [0, pi]), 2) assert ae(quadts(sin, [0, 2*pi]), 0) assert ae(quadts(exp, [-inf, -1]), 1/e) assert ae(quadts(lambda x: exp(-x), [0, inf]), 1) assert ae(quadts(lambda x: exp(-x*x), [-inf, inf]), sqrt(pi)) assert ae(quadts(lambda x: 1/(1+x*x), [-1, 1]), pi/2) assert ae(quadts(lambda x: 1/(1+x*x), [-inf, inf]), pi) assert ae(quadts(lambda x: 2*sqrt(1-x*x), [-1, 1]), pi) mp.dps = 15 def test_quad_symmetry(): assert quadts(sin, [-1, 1]) == 0 assert quadgl(sin, [-1, 1]) == 0 def test_quad_infinite_mirror(): # Check mirrored infinite interval assert ae(quad(lambda x: exp(-x*x), [inf,-inf]), -sqrt(pi)) assert ae(quad(lambda x: exp(x), [0,-inf]), -1) def test_quadgl_linear(): assert quadgl(lambda x: x, [0, 1], maxdegree=1).ae(0.5) def test_complex_integration(): assert quadts(lambda x: x, [0, 1+j]).ae(j) def test_quadosc(): mp.dps = 15 assert quadosc(lambda x: sin(x)/x, [0, inf], period=2*pi).ae(pi/2) # Double integrals def test_double_trivial(): assert ae(quadts(lambda x, y: x, [0, 1], [0, 1]), 0.5) assert ae(quadts(lambda x, y: x, [-1, 1], [-1, 1]), 0.0) def test_double_1(): assert ae(quadts(lambda x, y: cos(x+y/2), [-pi/2, pi/2], [0, pi]), 4) def test_double_2(): assert ae(quadts(lambda x, y: (x-1)/((1-x*y)*log(x*y)), [0, 1], [0, 1]), euler) def test_double_3(): assert ae(quadts(lambda x, y: 1/sqrt(1+x*x+y*y), [-1, 1], [-1, 1]), 4*log(2+sqrt(3))-2*pi/3) def test_double_4(): assert ae(quadts(lambda x, y: 1/(1-x*x * y*y), [0, 1], [0, 1]), pi**2 / 8) def test_double_5(): assert ae(quadts(lambda x, y: 1/(1-x*y), [0, 1], [0, 1]), pi**2 / 6) def test_double_6(): assert ae(quadts(lambda x, y: exp(-(x+y)), [0, inf], [0, inf]), 1) def test_double_7(): assert ae(quadts(lambda x, y: exp(-x*x-y*y), [-inf, inf], [-inf, inf]), pi) # Test integrals from "Experimentation in Mathematics" by Borwein, # Bailey & Girgensohn def test_expmath_integrals(): for prec in [15, 30, 50]: mp.dps = prec assert ae(quadts(lambda x: x/sinh(x), [0, inf]), pi**2 / 4) assert ae(quadts(lambda x: log(x)**2 / (1+x**2), [0, inf]), pi**3 / 8) assert ae(quadts(lambda x: (1+x**2)/(1+x**4), [0, inf]), pi/sqrt(2)) assert ae(quadts(lambda x: log(x)/cosh(x)**2, [0, inf]), log(pi)-2*log(2)-euler) assert ae(quadts(lambda x: log(1+x**3)/(1-x+x**2), [0, inf]), 2*pi*log(3)/sqrt(3)) assert ae(quadts(lambda x: log(x)**2 / (x**2+x+1), [0, 1]), 8*pi**3 / (81*sqrt(3))) assert ae(quadts(lambda x: log(cos(x))**2, [0, pi/2]), pi/2 * (log(2)**2+pi**2/12)) assert ae(quadts(lambda x: x**2 / sin(x)**2, [0, pi/2]), pi*log(2)) assert ae(quadts(lambda x: x**2/sqrt(exp(x)-1), [0, inf]), 4*pi*(log(2)**2 + pi**2/12)) assert ae(quadts(lambda x: x*exp(-x)*sqrt(1-exp(-2*x)), [0, inf]), pi*(1+2*log(2))/8) mp.dps = 15 # Do not reach full accuracy @pytest.mark.xfail def test_expmath_fail(): assert ae(quadts(lambda x: sqrt(tan(x)), [0, pi/2]), pi*sqrt(2)/2) assert ae(quadts(lambda x: atan(x)/(x*sqrt(1-x**2)), [0, 1]), pi*log(1+sqrt(2))/2) assert ae(quadts(lambda x: log(1+x**2)/x**2, [0, 1]), pi/2-log(2)) assert ae(quadts(lambda x: x**2/((1+x**4)*sqrt(1-x**4)), [0, 1]), pi/8) mpmath-1.1.0/mpmath/tests/test_rootfinding.py000066400000000000000000000062521340375245600214000ustar00rootroot00000000000000import pytest from mpmath import * from mpmath.calculus.optimization import Secant, Muller, Bisection, Illinois, \ Pegasus, Anderson, Ridder, ANewton, Newton, MNewton, MDNewton def test_findroot(): # old tests, assuming secant mp.dps = 15 assert findroot(lambda x: 4*x-3, mpf(5)).ae(0.75) assert findroot(sin, mpf(3)).ae(pi) assert findroot(sin, (mpf(3), mpf(3.14))).ae(pi) assert findroot(lambda x: x*x+1, mpc(2+2j)).ae(1j) # test all solvers with 1 starting point f = lambda x: cos(x) for solver in [Newton, Secant, MNewton, Muller, ANewton]: x = findroot(f, 2., solver=solver) assert abs(f(x)) < eps # test all solvers with interval of 2 points for solver in [Secant, Muller, Bisection, Illinois, Pegasus, Anderson, Ridder]: x = findroot(f, (1., 2.), solver=solver) assert abs(f(x)) < eps # test types f = lambda x: (x - 2)**2 #assert isinstance(findroot(f, 1, force_type=mpf, tol=1e-10), mpf) #assert isinstance(findroot(f, 1., force_type=None, tol=1e-10), float) #assert isinstance(findroot(f, 1, force_type=complex, tol=1e-10), complex) assert isinstance(fp.findroot(f, 1, tol=1e-10), float) assert isinstance(fp.findroot(f, 1+0j, tol=1e-10), complex) # issue 401 with pytest.raises(ValueError): with workprec(2): findroot(lambda x: x**2 - 4456178*x + 60372201703370, mpc(real='5.278e+13', imag='-5.278e+13')) # issue 192 with pytest.raises(ValueError): findroot(lambda x: -1, 0) # issue 387 with pytest.raises(ValueError): findroot(lambda p: (1 - p)**30 - 1, 0.9) def test_bisection(): # issue 273 assert findroot(lambda x: x**2-1,(0,2),solver='bisect') == 1 def test_mnewton(): f = lambda x: polyval([1,3,3,1],x) x = findroot(f, -0.9, solver='mnewton') assert abs(f(x)) < eps def test_anewton(): f = lambda x: (x - 2)**100 x = findroot(f, 1., solver=ANewton) assert abs(f(x)) < eps def test_muller(): f = lambda x: (2 + x)**3 + 2 x = findroot(f, 1., solver=Muller) assert abs(f(x)) < eps def test_multiplicity(): for i in range(1, 5): assert multiplicity(lambda x: (x - 1)**i, 1) == i assert multiplicity(lambda x: x**2, 1) == 0 def test_multidimensional(): def f(*x): return [3*x[0]**2-2*x[1]**2-1, x[0]**2-2*x[0]+x[1]**2+2*x[1]-8] assert mnorm(jacobian(f, (1,-2)) - matrix([[6,8],[0,-2]]),1) < 1.e-7 for x, error in MDNewton(mp, f, (1,-2), verbose=0, norm=lambda x: norm(x, inf)): pass assert norm(f(*x), 2) < 1e-14 # The Chinese mathematician Zhu Shijie was the very first to solve this # nonlinear system 700 years ago f1 = lambda x, y: -x + 2*y f2 = lambda x, y: (x**2 + x*(y**2 - 2) - 4*y) / (x + 4) f3 = lambda x, y: sqrt(x**2 + y**2) def f(x, y): f1x = f1(x, y) return (f2(x, y) - f1x, f3(x, y) - f1x) x = findroot(f, (10, 10)) assert [int(round(i)) for i in x] == [3, 4] def test_trivial(): assert findroot(lambda x: 0, 1) == 1 assert findroot(lambda x: x, 0) == 0 #assert findroot(lambda x, y: x + y, (1, -1)) == (1, -1) mpmath-1.1.0/mpmath/tests/test_special.py000066400000000000000000000054401340375245600204740ustar00rootroot00000000000000from mpmath import * def test_special(): assert inf == inf assert inf != -inf assert -inf == -inf assert inf != nan assert nan != nan assert isnan(nan) assert --inf == inf assert abs(inf) == inf assert abs(-inf) == inf assert abs(nan) != abs(nan) assert isnan(inf - inf) assert isnan(inf + (-inf)) assert isnan(-inf - (-inf)) assert isnan(inf + nan) assert isnan(-inf + nan) assert mpf(2) + inf == inf assert 2 + inf == inf assert mpf(2) - inf == -inf assert 2 - inf == -inf assert inf > 3 assert 3 < inf assert 3 > -inf assert -inf < 3 assert inf > mpf(3) assert mpf(3) < inf assert mpf(3) > -inf assert -inf < mpf(3) assert not (nan < 3) assert not (nan > 3) assert isnan(inf * 0) assert isnan(-inf * 0) assert inf * 3 == inf assert inf * -3 == -inf assert -inf * 3 == -inf assert -inf * -3 == inf assert inf * inf == inf assert -inf * -inf == inf assert isnan(nan / 3) assert inf / -3 == -inf assert inf / 3 == inf assert 3 / inf == 0 assert -3 / inf == 0 assert 0 / inf == 0 assert isnan(inf / inf) assert isnan(inf / -inf) assert isnan(inf / nan) assert mpf('inf') == mpf('+inf') == inf assert mpf('-inf') == -inf assert isnan(mpf('nan')) assert isinf(inf) assert isinf(-inf) assert not isinf(mpf(0)) assert not isinf(nan) def test_special_powers(): assert inf**3 == inf assert isnan(inf**0) assert inf**-3 == 0 assert (-inf)**2 == inf assert (-inf)**3 == -inf assert isnan((-inf)**0) assert (-inf)**-2 == 0 assert (-inf)**-3 == 0 assert isnan(nan**5) assert isnan(nan**0) def test_functions_special(): assert exp(inf) == inf assert exp(-inf) == 0 assert isnan(exp(nan)) assert log(inf) == inf assert isnan(log(nan)) assert isnan(sin(inf)) assert isnan(sin(nan)) assert atan(inf).ae(pi/2) assert atan(-inf).ae(-pi/2) assert isnan(sqrt(nan)) assert sqrt(inf) == inf def test_convert_special(): float_inf = 1e300 * 1e300 float_ninf = -float_inf float_nan = float_inf/float_ninf assert mpf(3) * float_inf == inf assert mpf(3) * float_ninf == -inf assert isnan(mpf(3) * float_nan) assert not (mpf(3) < float_nan) assert not (mpf(3) > float_nan) assert not (mpf(3) <= float_nan) assert not (mpf(3) >= float_nan) assert float(mpf('1e1000')) == float_inf assert float(mpf('-1e1000')) == float_ninf assert float(mpf('1e100000000000000000')) == float_inf assert float(mpf('-1e100000000000000000')) == float_ninf assert float(mpf('1e-100000000000000000')) == 0.0 def test_div_bug(): assert isnan(nan/1) assert isnan(nan/2) assert inf/2 == inf assert (-inf)/2 == -inf mpmath-1.1.0/mpmath/tests/test_str.py000066400000000000000000000010401340375245600176540ustar00rootroot00000000000000from mpmath import nstr, matrix, inf def test_nstr(): m = matrix([[0.75, 0.190940654, -0.0299195971], [0.190940654, 0.65625, 0.205663228], [-0.0299195971, 0.205663228, 0.64453125e-20]]) assert nstr(m, 4, min_fixed=-inf) == \ '''[ 0.75 0.1909 -0.02992] [ 0.1909 0.6563 0.2057] [-0.02992 0.2057 0.000000000000000000006445]''' assert nstr(m, 4) == \ '''[ 0.75 0.1909 -0.02992] [ 0.1909 0.6563 0.2057] [-0.02992 0.2057 6.445e-21]''' mpmath-1.1.0/mpmath/tests/test_summation.py000066400000000000000000000035031340375245600210660ustar00rootroot00000000000000from mpmath import * def test_sumem(): mp.dps = 15 assert sumem(lambda k: 1/k**2.5, [50, 100]).ae(0.0012524505324784962) assert sumem(lambda k: k**4 + 3*k + 1, [10, 100]).ae(2050333103) def test_nsum(): mp.dps = 15 assert nsum(lambda x: x**2, [1, 3]) == 14 assert nsum(lambda k: 1/factorial(k), [0, inf]).ae(e) assert nsum(lambda k: (-1)**(k+1) / k, [1, inf]).ae(log(2)) assert nsum(lambda k: (-1)**(k+1) / k**2, [1, inf]).ae(pi**2 / 12) assert nsum(lambda k: (-1)**k / log(k), [2, inf]).ae(0.9242998972229388) assert nsum(lambda k: 1/k**2, [1, inf]).ae(pi**2 / 6) assert nsum(lambda k: 2**k/fac(k), [0, inf]).ae(exp(2)) assert nsum(lambda k: 1/k**2, [4, inf], method='e').ae(0.2838229557371153) def test_nprod(): mp.dps = 15 assert nprod(lambda k: exp(1/k**2), [1,inf], method='r').ae(exp(pi**2/6)) assert nprod(lambda x: x**2, [1, 3]) == 36 def test_fsum(): mp.dps = 15 assert fsum([]) == 0 assert fsum([-4]) == -4 assert fsum([2,3]) == 5 assert fsum([1e-100,1]) == 1 assert fsum([1,1e-100]) == 1 assert fsum([1e100,1]) == 1e100 assert fsum([1,1e100]) == 1e100 assert fsum([1e-100,0]) == 1e-100 assert fsum([1e-100,1e100,1e-100]) == 1e100 assert fsum([2,1+1j,1]) == 4+1j assert fsum([2,inf,3]) == inf assert fsum([2,-1], absolute=1) == 3 assert fsum([2,-1], squared=1) == 5 assert fsum([1,1+j], squared=1) == 1+2j assert fsum([1,3+4j], absolute=1) == 6 assert fsum([1,2+3j], absolute=1, squared=1) == 14 assert isnan(fsum([inf,-inf])) assert fsum([inf,-inf], absolute=1) == inf assert fsum([inf,-inf], squared=1) == inf assert fsum([inf,-inf], absolute=1, squared=1) == inf assert iv.fsum([1,mpi(2,3)]) == mpi(3,4) def test_fprod(): mp.dps = 15 assert fprod([]) == 1 assert fprod([2,3]) == 6 mpmath-1.1.0/mpmath/tests/test_trig.py000066400000000000000000000112771340375245600200260ustar00rootroot00000000000000from mpmath import * from mpmath.libmp import * def test_trig_misc_hard(): mp.prec = 53 # Worst-case input for an IEEE double, from a paper by Kahan x = ldexp(6381956970095103,797) assert cos(x) == mpf('-4.6871659242546277e-19') assert sin(x) == 1 mp.prec = 150 a = mpf(10**50) mp.prec = 53 assert sin(a).ae(-0.7896724934293100827) assert cos(a).ae(-0.6135286082336635622) # Check relative accuracy close to x = zero assert sin(1e-100) == 1e-100 # when rounding to nearest assert sin(1e-6).ae(9.999999999998333e-007, rel_eps=2e-15, abs_eps=0) assert sin(1e-6j).ae(1.0000000000001666e-006j, rel_eps=2e-15, abs_eps=0) assert sin(-1e-6j).ae(-1.0000000000001666e-006j, rel_eps=2e-15, abs_eps=0) assert cos(1e-100) == 1 assert cos(1e-6).ae(0.9999999999995) assert cos(-1e-6j).ae(1.0000000000005) assert tan(1e-100) == 1e-100 assert tan(1e-6).ae(1.0000000000003335e-006, rel_eps=2e-15, abs_eps=0) assert tan(1e-6j).ae(9.9999999999966644e-007j, rel_eps=2e-15, abs_eps=0) assert tan(-1e-6j).ae(-9.9999999999966644e-007j, rel_eps=2e-15, abs_eps=0) def test_trig_near_zero(): mp.dps = 15 for r in [round_nearest, round_down, round_up, round_floor, round_ceiling]: assert sin(0, rounding=r) == 0 assert cos(0, rounding=r) == 1 a = mpf('1e-100') b = mpf('-1e-100') assert sin(a, rounding=round_nearest) == a assert sin(a, rounding=round_down) < a assert sin(a, rounding=round_floor) < a assert sin(a, rounding=round_up) >= a assert sin(a, rounding=round_ceiling) >= a assert sin(b, rounding=round_nearest) == b assert sin(b, rounding=round_down) > b assert sin(b, rounding=round_floor) <= b assert sin(b, rounding=round_up) <= b assert sin(b, rounding=round_ceiling) > b assert cos(a, rounding=round_nearest) == 1 assert cos(a, rounding=round_down) < 1 assert cos(a, rounding=round_floor) < 1 assert cos(a, rounding=round_up) == 1 assert cos(a, rounding=round_ceiling) == 1 assert cos(b, rounding=round_nearest) == 1 assert cos(b, rounding=round_down) < 1 assert cos(b, rounding=round_floor) < 1 assert cos(b, rounding=round_up) == 1 assert cos(b, rounding=round_ceiling) == 1 def test_trig_near_n_pi(): mp.dps = 15 a = [n*pi for n in [1, 2, 6, 11, 100, 1001, 10000, 100001]] mp.dps = 135 a.append(10**100 * pi) mp.dps = 15 assert sin(a[0]) == mpf('1.2246467991473531772e-16') assert sin(a[1]) == mpf('-2.4492935982947063545e-16') assert sin(a[2]) == mpf('-7.3478807948841190634e-16') assert sin(a[3]) == mpf('4.8998251578625894243e-15') assert sin(a[4]) == mpf('1.9643867237284719452e-15') assert sin(a[5]) == mpf('-8.8632615209684813458e-15') assert sin(a[6]) == mpf('-4.8568235395684898392e-13') assert sin(a[7]) == mpf('3.9087342299491231029e-11') assert sin(a[8]) == mpf('-1.369235466754566993528e-36') r = round_nearest assert cos(a[0], rounding=r) == -1 assert cos(a[1], rounding=r) == 1 assert cos(a[2], rounding=r) == 1 assert cos(a[3], rounding=r) == -1 assert cos(a[4], rounding=r) == 1 assert cos(a[5], rounding=r) == -1 assert cos(a[6], rounding=r) == 1 assert cos(a[7], rounding=r) == -1 assert cos(a[8], rounding=r) == 1 r = round_up assert cos(a[0], rounding=r) == -1 assert cos(a[1], rounding=r) == 1 assert cos(a[2], rounding=r) == 1 assert cos(a[3], rounding=r) == -1 assert cos(a[4], rounding=r) == 1 assert cos(a[5], rounding=r) == -1 assert cos(a[6], rounding=r) == 1 assert cos(a[7], rounding=r) == -1 assert cos(a[8], rounding=r) == 1 r = round_down assert cos(a[0], rounding=r) > -1 assert cos(a[1], rounding=r) < 1 assert cos(a[2], rounding=r) < 1 assert cos(a[3], rounding=r) > -1 assert cos(a[4], rounding=r) < 1 assert cos(a[5], rounding=r) > -1 assert cos(a[6], rounding=r) < 1 assert cos(a[7], rounding=r) > -1 assert cos(a[8], rounding=r) < 1 r = round_floor assert cos(a[0], rounding=r) == -1 assert cos(a[1], rounding=r) < 1 assert cos(a[2], rounding=r) < 1 assert cos(a[3], rounding=r) == -1 assert cos(a[4], rounding=r) < 1 assert cos(a[5], rounding=r) == -1 assert cos(a[6], rounding=r) < 1 assert cos(a[7], rounding=r) == -1 assert cos(a[8], rounding=r) < 1 r = round_ceiling assert cos(a[0], rounding=r) > -1 assert cos(a[1], rounding=r) == 1 assert cos(a[2], rounding=r) == 1 assert cos(a[3], rounding=r) > -1 assert cos(a[4], rounding=r) == 1 assert cos(a[5], rounding=r) > -1 assert cos(a[6], rounding=r) == 1 assert cos(a[7], rounding=r) > -1 assert cos(a[8], rounding=r) == 1 mp.dps = 15 mpmath-1.1.0/mpmath/tests/test_visualization.py000066400000000000000000000016601340375245600217550ustar00rootroot00000000000000""" Limited tests of the visualization module. Right now it just makes sure that passing custom Axes works. """ from mpmath import mp, fp def test_axes(): try: import matplotlib version = matplotlib.__version__.split("-")[0] version = version.split(".")[:2] if [int(_) for _ in version] < [0,99]: raise ImportError import pylab except ImportError: print("\nSkipping test (pylab not available or too old version)\n") return fig = pylab.figure() axes = fig.add_subplot(111) for ctx in [mp, fp]: ctx.plot(lambda x: x**2, [0, 3], axes=axes) assert axes.get_xlabel() == 'x' assert axes.get_ylabel() == 'f(x)' fig = pylab.figure() axes = fig.add_subplot(111) for ctx in [mp, fp]: ctx.cplot(lambda z: z, [-2, 2], [-10, 10], axes=axes) assert axes.get_xlabel() == 'Re(z)' assert axes.get_ylabel() == 'Im(z)' mpmath-1.1.0/mpmath/tests/torture.py000066400000000000000000000172741340375245600175310ustar00rootroot00000000000000""" Torture tests for asymptotics and high precision evaluation of special functions. (Other torture tests may also be placed here.) Running this file (gmpy recommended!) takes several CPU minutes. With Python 2.6+, multiprocessing is used automatically to run tests in parallel if many cores are available. (A single test may take between a second and several minutes; possibly more.) The idea: * We evaluate functions at positive, negative, imaginary, 45- and 135-degree complex values with magnitudes between 10^-20 to 10^20, at precisions between 5 and 150 digits (we can go even higher for fast functions). * Comparing the result from two different precision levels provides a strong consistency check (particularly for functions that use different algorithms at different precision levels). * That the computation finishes at all (without failure), within reasonable time, provides a check that evaluation works at all: that the code runs, that it doesn't get stuck in an infinite loop, and that it doesn't use some extremely slowly algorithm where it could use a faster one. TODO: * Speed up those functions that take long to finish! * Generalize to test more cases; more options. * Implement a timeout mechanism. * Some functions are notably absent, including the following: * inverse trigonometric functions (some become inaccurate for complex arguments) * ci, si (not implemented properly for large complex arguments) * zeta functions (need to modify test not to try too large imaginary values) * and others... """ import sys, os from timeit import default_timer as clock if "-nogmpy" in sys.argv: sys.argv.remove('-nogmpy') os.environ['MPMATH_NOGMPY'] = 'Y' filt = '' if not sys.argv[-1].endswith(".py"): filt = sys.argv[-1] from mpmath import * from mpmath.libmp.backend import exec_ def test_asymp(f, maxdps=150, verbose=False, huge_range=False): dps = [5,15,25,50,90,150,500,1500,5000,10000] dps = [p for p in dps if p <= maxdps] def check(x,y,p,inpt): if abs(x-y)/abs(y) < workprec(20)(power)(10, -p+1): return print() print("Error!") print("Input:", inpt) print("dps =", p) print("Result 1:", x) print("Result 2:", y) print("Absolute error:", abs(x-y)) print("Relative error:", abs(x-y)/abs(y)) raise AssertionError exponents = range(-20,20) if huge_range: exponents += [-1000, -100, -50, 50, 100, 1000] for n in exponents: if verbose: sys.stdout.write(". ") mp.dps = 25 xpos = mpf(10)**n / 1.1287 xneg = -xpos ximag = xpos*j xcomplex1 = xpos*(1+j) xcomplex2 = xpos*(-1+j) for i in range(len(dps)): if verbose: print("Testing dps = %s" % dps[i]) mp.dps = dps[i] new = f(xpos), f(xneg), f(ximag), f(xcomplex1), f(xcomplex2) if i != 0: p = dps[i-1] check(prev[0], new[0], p, xpos) check(prev[1], new[1], p, xneg) check(prev[2], new[2], p, ximag) check(prev[3], new[3], p, xcomplex1) check(prev[4], new[4], p, xcomplex2) prev = new if verbose: print() a1, a2, a3, a4, a5 = 1.5, -2.25, 3.125, 4, 2 def test_bernoulli_huge(): p, q = bernfrac(9000) assert p % 10**10 == 9636701091 assert q == 4091851784687571609141381951327092757255270 mp.dps = 15 assert str(bernoulli(10**100)) == '-2.58183325604736e+987675256497386331227838638980680030172857347883537824464410652557820800494271520411283004120790908623' mp.dps = 50 assert str(bernoulli(10**100)) == '-2.5818332560473632073252488656039475548106223822913e+987675256497386331227838638980680030172857347883537824464410652557820800494271520411283004120790908623' mp.dps = 15 cases = """\ test_bernoulli_huge() test_asymp(lambda z: +pi, maxdps=10000) test_asymp(lambda z: +e, maxdps=10000) test_asymp(lambda z: +ln2, maxdps=10000) test_asymp(lambda z: +ln10, maxdps=10000) test_asymp(lambda z: +phi, maxdps=10000) test_asymp(lambda z: +catalan, maxdps=5000) test_asymp(lambda z: +euler, maxdps=5000) test_asymp(lambda z: +glaisher, maxdps=1000) test_asymp(lambda z: +khinchin, maxdps=1000) test_asymp(lambda z: +twinprime, maxdps=150) test_asymp(lambda z: stieltjes(2), maxdps=150) test_asymp(lambda z: +mertens, maxdps=150) test_asymp(lambda z: +apery, maxdps=5000) test_asymp(sqrt, maxdps=10000, huge_range=True) test_asymp(cbrt, maxdps=5000, huge_range=True) test_asymp(lambda z: root(z,4), maxdps=5000, huge_range=True) test_asymp(lambda z: root(z,-5), maxdps=5000, huge_range=True) test_asymp(exp, maxdps=5000, huge_range=True) test_asymp(expm1, maxdps=1500) test_asymp(ln, maxdps=5000, huge_range=True) test_asymp(cosh, maxdps=5000) test_asymp(sinh, maxdps=5000) test_asymp(tanh, maxdps=1500) test_asymp(sin, maxdps=5000, huge_range=True) test_asymp(cos, maxdps=5000, huge_range=True) test_asymp(tan, maxdps=1500) test_asymp(agm, maxdps=1500, huge_range=True) test_asymp(ellipk, maxdps=1500) test_asymp(ellipe, maxdps=1500) test_asymp(lambertw, huge_range=True) test_asymp(lambda z: lambertw(z,-1)) test_asymp(lambda z: lambertw(z,1)) test_asymp(lambda z: lambertw(z,4)) test_asymp(gamma) test_asymp(loggamma) # huge_range=True ? test_asymp(ei) test_asymp(e1) test_asymp(li, huge_range=True) test_asymp(ci) test_asymp(si) test_asymp(chi) test_asymp(shi) test_asymp(erf) test_asymp(erfc) test_asymp(erfi) test_asymp(lambda z: besselj(2, z)) test_asymp(lambda z: bessely(2, z)) test_asymp(lambda z: besseli(2, z)) test_asymp(lambda z: besselk(2, z)) test_asymp(lambda z: besselj(-2.25, z)) test_asymp(lambda z: bessely(-2.25, z)) test_asymp(lambda z: besseli(-2.25, z)) test_asymp(lambda z: besselk(-2.25, z)) test_asymp(airyai) test_asymp(airybi) test_asymp(lambda z: hyp0f1(a1, z)) test_asymp(lambda z: hyp1f1(a1, a2, z)) test_asymp(lambda z: hyp1f2(a1, a2, a3, z)) test_asymp(lambda z: hyp2f0(a1, a2, z)) test_asymp(lambda z: hyperu(a1, a2, z)) test_asymp(lambda z: hyp2f1(a1, a2, a3, z)) test_asymp(lambda z: hyp2f2(a1, a2, a3, a4, z)) test_asymp(lambda z: hyp2f3(a1, a2, a3, a4, a5, z)) test_asymp(lambda z: coulombf(a1, a2, z)) test_asymp(lambda z: coulombg(a1, a2, z)) test_asymp(lambda z: polylog(2,z)) test_asymp(lambda z: polylog(3,z)) test_asymp(lambda z: polylog(-2,z)) test_asymp(lambda z: expint(4, z)) test_asymp(lambda z: expint(-4, z)) test_asymp(lambda z: expint(2.25, z)) test_asymp(lambda z: gammainc(2.5, z, 5)) test_asymp(lambda z: gammainc(2.5, 5, z)) test_asymp(lambda z: hermite(3, z)) test_asymp(lambda z: hermite(2.5, z)) test_asymp(lambda z: legendre(3, z)) test_asymp(lambda z: legendre(4, z)) test_asymp(lambda z: legendre(2.5, z)) test_asymp(lambda z: legenp(a1, a2, z)) test_asymp(lambda z: legenq(a1, a2, z), maxdps=90) # abnormally slow test_asymp(lambda z: jtheta(1, z, 0.5)) test_asymp(lambda z: jtheta(2, z, 0.5)) test_asymp(lambda z: jtheta(3, z, 0.5)) test_asymp(lambda z: jtheta(4, z, 0.5)) test_asymp(lambda z: jtheta(1, z, 0.5, 1)) test_asymp(lambda z: jtheta(2, z, 0.5, 1)) test_asymp(lambda z: jtheta(3, z, 0.5, 1)) test_asymp(lambda z: jtheta(4, z, 0.5, 1)) test_asymp(barnesg, maxdps=90) """ def testit(line): if filt in line: print(line) t1 = clock() exec_(line, globals(), locals()) t2 = clock() elapsed = t2-t1 print("Time:", elapsed, "for", line, "(OK)") if __name__ == '__main__': try: from multiprocessing import Pool mapf = Pool(None).map print("Running tests with multiprocessing") except ImportError: print("Not using multiprocessing") mapf = map t1 = clock() tasks = cases.splitlines() mapf(testit, tasks) t2 = clock() print("Cumulative wall time:", t2-t1) mpmath-1.1.0/mpmath/usertools.py000066400000000000000000000057251340375245600167200ustar00rootroot00000000000000 def monitor(f, input='print', output='print'): """ Returns a wrapped copy of *f* that monitors evaluation by calling *input* with every input (*args*, *kwargs*) passed to *f* and *output* with every value returned from *f*. The default action (specify using the special string value ``'print'``) is to print inputs and outputs to stdout, along with the total evaluation count:: >>> from mpmath import * >>> mp.dps = 5; mp.pretty = False >>> diff(monitor(exp), 1) # diff will eval f(x-h) and f(x+h) in 0 (mpf('0.99999999906867742538452148'),) {} out 0 mpf('2.7182818259274480055282064') in 1 (mpf('1.0000000009313225746154785'),) {} out 1 mpf('2.7182818309906424675501024') mpf('2.7182808') To disable either the input or the output handler, you may pass *None* as argument. Custom input and output handlers may be used e.g. to store results for later analysis:: >>> mp.dps = 15 >>> input = [] >>> output = [] >>> findroot(monitor(sin, input.append, output.append), 3.0) mpf('3.1415926535897932') >>> len(input) # Count number of evaluations 9 >>> print(input[3]); print(output[3]) ((mpf('3.1415076583334066'),), {}) 8.49952562843408e-5 >>> print(input[4]); print(output[4]) ((mpf('3.1415928201669122'),), {}) -1.66577118985331e-7 """ if not input: input = lambda v: None elif input == 'print': incount = [0] def input(value): args, kwargs = value print("in %s %r %r" % (incount[0], args, kwargs)) incount[0] += 1 if not output: output = lambda v: None elif output == 'print': outcount = [0] def output(value): print("out %s %r" % (outcount[0], value)) outcount[0] += 1 def f_monitored(*args, **kwargs): input((args, kwargs)) v = f(*args, **kwargs) output(v) return v return f_monitored def timing(f, *args, **kwargs): """ Returns time elapsed for evaluating ``f()``. Optionally arguments may be passed to time the execution of ``f(*args, **kwargs)``. If the first call is very quick, ``f`` is called repeatedly and the best time is returned. """ once = kwargs.get('once') if 'once' in kwargs: del kwargs['once'] if args or kwargs: if len(args) == 1 and not kwargs: arg = args[0] g = lambda: f(arg) else: g = lambda: f(*args, **kwargs) else: g = f from timeit import default_timer as clock t1=clock(); v=g(); t2=clock(); t=t2-t1 if t > 0.05 or once: return t for i in range(3): t1=clock(); # Evaluate multiple times because the timer function # has a significant overhead g();g();g();g();g();g();g();g();g();g() t2=clock() t=min(t,(t2-t1)/10) return t mpmath-1.1.0/mpmath/visualization.py000066400000000000000000000246031340375245600175560ustar00rootroot00000000000000""" Plotting (requires matplotlib) """ from colorsys import hsv_to_rgb, hls_to_rgb from .libmp import NoConvergence from .libmp.backend import xrange class VisualizationMethods(object): plot_ignore = (ValueError, ArithmeticError, ZeroDivisionError, NoConvergence) def plot(ctx, f, xlim=[-5,5], ylim=None, points=200, file=None, dpi=None, singularities=[], axes=None): r""" Shows a simple 2D plot of a function `f(x)` or list of functions `[f_0(x), f_1(x), \ldots, f_n(x)]` over a given interval specified by *xlim*. Some examples:: plot(lambda x: exp(x)*li(x), [1, 4]) plot([cos, sin], [-4, 4]) plot([fresnels, fresnelc], [-4, 4]) plot([sqrt, cbrt], [-4, 4]) plot(lambda t: zeta(0.5+t*j), [-20, 20]) plot([floor, ceil, abs, sign], [-5, 5]) Points where the function raises a numerical exception or returns an infinite value are removed from the graph. Singularities can also be excluded explicitly as follows (useful for removing erroneous vertical lines):: plot(cot, ylim=[-5, 5]) # bad plot(cot, ylim=[-5, 5], singularities=[-pi, 0, pi]) # good For parts where the function assumes complex values, the real part is plotted with dashes and the imaginary part is plotted with dots. .. note :: This function requires matplotlib (pylab). """ if file: axes = None fig = None if not axes: import pylab fig = pylab.figure() axes = fig.add_subplot(111) if not isinstance(f, (tuple, list)): f = [f] a, b = xlim colors = ['b', 'r', 'g', 'm', 'k'] for n, func in enumerate(f): x = ctx.arange(a, b, (b-a)/float(points)) segments = [] segment = [] in_complex = False for i in xrange(len(x)): try: if i != 0: for sing in singularities: if x[i-1] <= sing and x[i] >= sing: raise ValueError v = func(x[i]) if ctx.isnan(v) or abs(v) > 1e300: raise ValueError if hasattr(v, "imag") and v.imag: re = float(v.real) im = float(v.imag) if not in_complex: in_complex = True segments.append(segment) segment = [] segment.append((float(x[i]), re, im)) else: if in_complex: in_complex = False segments.append(segment) segment = [] if hasattr(v, "real"): v = v.real segment.append((float(x[i]), v)) except ctx.plot_ignore: if segment: segments.append(segment) segment = [] if segment: segments.append(segment) for segment in segments: x = [s[0] for s in segment] y = [s[1] for s in segment] if not x: continue c = colors[n % len(colors)] if len(segment[0]) == 3: z = [s[2] for s in segment] axes.plot(x, y, '--'+c, linewidth=3) axes.plot(x, z, ':'+c, linewidth=3) else: axes.plot(x, y, c, linewidth=3) axes.set_xlim([float(_) for _ in xlim]) if ylim: axes.set_ylim([float(_) for _ in ylim]) axes.set_xlabel('x') axes.set_ylabel('f(x)') axes.grid(True) if fig: if file: pylab.savefig(file, dpi=dpi) else: pylab.show() def default_color_function(ctx, z): if ctx.isinf(z): return (1.0, 1.0, 1.0) if ctx.isnan(z): return (0.5, 0.5, 0.5) pi = 3.1415926535898 a = (float(ctx.arg(z)) + ctx.pi) / (2*ctx.pi) a = (a + 0.5) % 1.0 b = 1.0 - float(1/(1.0+abs(z)**0.3)) return hls_to_rgb(a, b, 0.8) blue_orange_colors = [ (-1.0, (0.0, 0.0, 0.0)), (-0.95, (0.1, 0.2, 0.5)), # dark blue (-0.5, (0.0, 0.5, 1.0)), # blueish (-0.05, (0.4, 0.8, 0.8)), # cyanish ( 0.0, (1.0, 1.0, 1.0)), ( 0.05, (1.0, 0.9, 0.3)), # yellowish ( 0.5, (0.9, 0.5, 0.0)), # orangeish ( 0.95, (0.7, 0.1, 0.0)), # redish ( 1.0, (0.0, 0.0, 0.0)), ( 2.0, (0.0, 0.0, 0.0)), ] def phase_color_function(ctx, z): if ctx.isinf(z): return (1.0, 1.0, 1.0) if ctx.isnan(z): return (0.5, 0.5, 0.5) pi = 3.1415926535898 w = float(ctx.arg(z)) / pi w = max(min(w, 1.0), -1.0) for i in range(1,len(blue_orange_colors)): if blue_orange_colors[i][0] > w: a, (ra, ga, ba) = blue_orange_colors[i-1] b, (rb, gb, bb) = blue_orange_colors[i] s = (w-a) / (b-a) return ra+(rb-ra)*s, ga+(gb-ga)*s, ba+(bb-ba)*s def cplot(ctx, f, re=[-5,5], im=[-5,5], points=2000, color=None, verbose=False, file=None, dpi=None, axes=None): """ Plots the given complex-valued function *f* over a rectangular part of the complex plane specified by the pairs of intervals *re* and *im*. For example:: cplot(lambda z: z, [-2, 2], [-10, 10]) cplot(exp) cplot(zeta, [0, 1], [0, 50]) By default, the complex argument (phase) is shown as color (hue) and the magnitude is show as brightness. You can also supply a custom color function (*color*). This function should take a complex number as input and return an RGB 3-tuple containing floats in the range 0.0-1.0. Alternatively, you can select a builtin color function by passing a string as *color*: * "default" - default color scheme * "phase" - a color scheme that only renders the phase of the function, with white for positive reals, black for negative reals, gold in the upper half plane, and blue in the lower half plane. To obtain a sharp image, the number of points may need to be increased to 100,000 or thereabout. Since evaluating the function that many times is likely to be slow, the 'verbose' option is useful to display progress. .. note :: This function requires matplotlib (pylab). """ if color is None or color == "default": color = ctx.default_color_function if color == "phase": color = ctx.phase_color_function import pylab if file: axes = None fig = None if not axes: fig = pylab.figure() axes = fig.add_subplot(111) rea, reb = re ima, imb = im dre = reb - rea dim = imb - ima M = int(ctx.sqrt(points*dre/dim)+1) N = int(ctx.sqrt(points*dim/dre)+1) x = pylab.linspace(rea, reb, M) y = pylab.linspace(ima, imb, N) # Note: we have to be careful to get the right rotation. # Test with these plots: # cplot(lambda z: z if z.real < 0 else 0) # cplot(lambda z: z if z.imag < 0 else 0) w = pylab.zeros((N, M, 3)) for n in xrange(N): for m in xrange(M): z = ctx.mpc(x[m], y[n]) try: v = color(f(z)) except ctx.plot_ignore: v = (0.5, 0.5, 0.5) w[n,m] = v if verbose: print(str(n) + ' of ' + str(N)) rea, reb, ima, imb = [float(_) for _ in [rea, reb, ima, imb]] axes.imshow(w, extent=(rea, reb, ima, imb), origin='lower') axes.set_xlabel('Re(z)') axes.set_ylabel('Im(z)') if fig: if file: pylab.savefig(file, dpi=dpi) else: pylab.show() def splot(ctx, f, u=[-5,5], v=[-5,5], points=100, keep_aspect=True, \ wireframe=False, file=None, dpi=None, axes=None): """ Plots the surface defined by `f`. If `f` returns a single component, then this plots the surface defined by `z = f(x,y)` over the rectangular domain with `x = u` and `y = v`. If `f` returns three components, then this plots the parametric surface `x, y, z = f(u,v)` over the pairs of intervals `u` and `v`. For example, to plot a simple function:: >>> from mpmath import * >>> f = lambda x, y: sin(x+y)*cos(y) >>> splot(f, [-pi,pi], [-pi,pi]) # doctest: +SKIP Plotting a donut:: >>> r, R = 1, 2.5 >>> f = lambda u, v: [r*cos(u), (R+r*sin(u))*cos(v), (R+r*sin(u))*sin(v)] >>> splot(f, [0, 2*pi], [0, 2*pi]) # doctest: +SKIP .. note :: This function requires matplotlib (pylab) 0.98.5.3 or higher. """ import pylab import mpl_toolkits.mplot3d as mplot3d if file: axes = None fig = None if not axes: fig = pylab.figure() axes = mplot3d.axes3d.Axes3D(fig) ua, ub = u va, vb = v du = ub - ua dv = vb - va if not isinstance(points, (list, tuple)): points = [points, points] M, N = points u = pylab.linspace(ua, ub, M) v = pylab.linspace(va, vb, N) x, y, z = [pylab.zeros((M, N)) for i in xrange(3)] xab, yab, zab = [[0, 0] for i in xrange(3)] for n in xrange(N): for m in xrange(M): fdata = f(ctx.convert(u[m]), ctx.convert(v[n])) try: x[m,n], y[m,n], z[m,n] = fdata except TypeError: x[m,n], y[m,n], z[m,n] = u[m], v[n], fdata for c, cab in [(x[m,n], xab), (y[m,n], yab), (z[m,n], zab)]: if c < cab[0]: cab[0] = c if c > cab[1]: cab[1] = c if wireframe: axes.plot_wireframe(x, y, z, rstride=4, cstride=4) else: axes.plot_surface(x, y, z, rstride=4, cstride=4) axes.set_xlabel('x') axes.set_ylabel('y') axes.set_zlabel('z') if keep_aspect: dx, dy, dz = [cab[1] - cab[0] for cab in [xab, yab, zab]] maxd = max(dx, dy, dz) if dx < maxd: delta = maxd - dx axes.set_xlim3d(xab[0] - delta / 2.0, xab[1] + delta / 2.0) if dy < maxd: delta = maxd - dy axes.set_ylim3d(yab[0] - delta / 2.0, yab[1] + delta / 2.0) if dz < maxd: delta = maxd - dz axes.set_zlim3d(zab[0] - delta / 2.0, zab[1] + delta / 2.0) if fig: if file: pylab.savefig(file, dpi=dpi) else: pylab.show() VisualizationMethods.plot = plot VisualizationMethods.default_color_function = default_color_function VisualizationMethods.phase_color_function = phase_color_function VisualizationMethods.cplot = cplot VisualizationMethods.splot = splot mpmath-1.1.0/pkgdocs.sh000066400000000000000000000003451340375245600150000ustar00rootroot00000000000000TARFILE=mpmath-docsrc-`python -c "import mpmath; print mpmath.__version__"`.tar tar -cf $TARFILE README.rst CHANGES pkgdocs.sh demo/*.py doc/*.py \ `find doc/source -not \( -name .git -prune \) -type f | less` gzip $TARFILE mpmath-1.1.0/setup.cfg000066400000000000000000000007671340375245600146430ustar00rootroot00000000000000[pep8] # E101 - mix of tabs and spaces # W191 - use of tabs # W291 - trailing whitespace # W293 - trailing whitespace # E111 - 4 spaces per indentation level # E112 - 4 spaces per indentation level # E113 - 4 spaces per indentation level # W292 - no newline at end of file # W391 - blank line at end of file select = E101,W191,W291,W293,E111,E112,E113,W292,W391 [tool:pytest] addopts = --doctest-modules --ignore=setup.py --doctest-glob='*.txt' norecursedirs = doc/source/plots demo mpmath-1.1.0/setup.py000066400000000000000000000011301340375245600145150ustar00rootroot00000000000000#!/usr/bin/env python from distutils.core import setup setup(name='mpmath', description = 'Python library for arbitrary-precision floating-point arithmetic', version='1.1.0', url='http://mpmath.org', author='Fredrik Johansson', author_email='fredrik.johansson@gmail.com', license = 'BSD', packages=['mpmath', 'mpmath.libmp', 'mpmath.calculus', 'mpmath.functions', 'mpmath.matrices', 'mpmath.tests'], classifiers=['Topic :: Scientific/Engineering :: Mathematics'] )