Addresses #707
Implements the Radix-2 Cooley-Tukey Fast Fourier Transform (FFT) algorithm to
compute the discrete fourier transform and inverse discrete fourier transform of a signal.
Inputs are currently restricted to lengths of powers of 2.
Following functions kept:
```pycon
>>> import inspect
... with_args = []
... with_kwargs = []
... for n in dir(mpmath):
... m = getattr(mpmath, n)
... try:
... s = inspect.signature(m)
... except:
... continue
... if any(_.kind == inspect._ParameterKind.VAR_POSITIONAL for _ in s.parameters.values()):
... for name in s.parameters:
... if s.parameters[name].kind == inspect._ParameterKind.VAR_POSITIONAL and name == 'args':
... with_args.append(n)
... break
... if any(_.kind == inspect._ParameterKind.VAR_KEYWORD for _ in s.parameters.values()):
... with_kwargs.append(n)
... print(with_args)
... print(with_kwargs)
...
['arange', 'ellipe', 'ellippi', 'linspace', 'matrix', 'ones', 'timing', 'zeros']
['multiplicity', 'timing']
```
We need support for multiple signatures in the first case. In the
second - it's impossible to implement these functions without kwargs.
Closes#1056
* Avoid spurious overflow in fp gammaprod
fp.binomial(1100, 1) raised OverflowError even though the result is
exactly 1100: gammaprod multiplies the individual gamma values, and
gamma(1101) exceeds the double range although the quotient does not.
Fall back to evaluating the regular numerator/denominator in log space
when a term overflows, so the quotient is computed whenever it is
representable. Genuinely out-of-range results, such as
fp.binomial(1100, 550), still raise OverflowError.
Closes#493
to_str extracted only dps+10 digits, narrower than format_scientific and
format_fixed which cover the whole mantissa. A value just above a decimal
boundary was then extracted as "...99999" one ULP low, so directed rounding
through str/nstr fell one ULP short of the 'e' format and the exact value.
Widen the base-10 window to match the sibling formatters.
Also fixed test for from_str(), coming from 30e8001e
format_fixed() extracts a handful of guard digits and lets round_digits()
decide, so a nonzero remainder lying past them was invisible: directed and
nearest rounding truncated the last digit instead of rounding it up. The
value is dyadic, so its exactness at the extracted digits is decidable;
pass that as a inexact flag and round on it. The "e" path and MPFR already
round these correctly.
Values whose leading digit falls past the last requested place skipped
round_digits() altogether and always printed zeros, even under rounding
away from zero; round them to one unit in the last place in that case.
Closes#1131
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
That should work at lest for 32-bit integers. Though, I think that
the repr/str representation loses all sence for precisions much
less than that ;-)
Closes#1116
* Weierstrass $\wp$: `weierp`
* inverse Weierstrass $\wp$: `weierpinv`
* derivative of Weierstrass $\wp$: `weierpprime`
* Weierstrass zeta: `weierzeta`
* Weierstrass sigma: `weiersigma`
Also adds parameter conversion functions:
* Weierstrass invariants $g_2, g_3$: `weierinvariants`
* half-periods $\omega_1, \omega_2$: `weierhalfperiods`
The idea for this PR was inspired by the `pyweierstrass` package by @stla / Stéphane Laurent:
* https://pyweierstrass.readthedocs.io/en/latest/
* https://github.com/stla/pyweierstrass
The code implementation in this PR is different to that in `pyweierstrass` although both packages derive from similar well known mathematical formulas. Differences between `pyweierstrass` and this `mpmath` implementation include but are not limited to:
* function names adapted to `mpmath` conventions;
* tau normalization: `tau` specifies the normalized period lattice `(1, tau)`, corresponding to half-periods `(1/2, tau/2)`; this differs from `pyweierstrass`, where `tau` denotes half-periods `(1, tau)`;
* support for disambiguating inverse values of Weierstrass $\wp$ by optionally passing the corresponding derivative value;
* internal refactoring of helper functions for integration with `mpmath`.
Dedicated to Stéphane Laurent who opened the original PR to request this functionality in `mpmath` and whose `pyweierstrass` package provided great utility to the author of this PR in the years since.
Co-authored-by: Stéphane Laurent <stla@users.noreply.github.com>
Closes#612
θ₃(z) ~ 1 + 2q¹cos(2z) + 2q⁴cos(4z) + ..., and we
are in |Im(z)| < |Re(log(q))|/2 domain.
To avoid severe cancellation we compute in fixed-point
only s ~ 2(cos(2z) + q³ cos(4z) + ...), then
return 1 + s*q.
Closes#1104
Second paragraph rephrased to:
> If the magnitude of *rounded* number is too large to represent as
> a regular float, it will be converted to infinity.
Closes#1085
* Fix qr_solve() failure on well-conditioned matrices with zero pivot
In householder(), the sign convention
p[j] = -sign(Re(A[j,j])) * sqrt(s)
collapses to zero when A[j,j] is exactly zero, because ctx.sign(0) == 0.
A zero p[j] makes kappa = 1/(s - p[j]*A[j,j]) = 1/s instead of the
correct 2/||v||**2, corrupting the Householder reflection. The damage
propagates to subsequent columns and eventually trips the
"matrix is numerically singular" guard.
Default sign to ctx.one when A[j,j] is zero (matching LAPACK's dlarfg
convention) so the reflection is computed correctly. The existing
singularity check is left in place to catch genuinely zero column
slices.
Fixes#983.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add bash script to test package version in a frozen application version and a separate CI job to run it. Closes#1044.
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
Remember, that the gmpy2 backend returns mpfr and mpc types
for mixed-mode arithmetics, when one operand is mpz or mpq.
Examples:
>>> mpz(1) + 0.1
mpfr('1.1000000000000001')
>>> mpz(1) + 1j
mpc('1.0+1.0j')
Also, mpfr type returned for true division of mpz's.
This enables *default* Python mechanism for integer string
conversion length limitation:
https://docs.python.org/3/library/stdtypes.html#integer-string-conversion-length-limitation
For the mpmath CLI it will be *off* by default. Usually, it doesn't
matter, as these limits not affect the gmpy2/gmp backends and working
with mpmath's types (mpf/mpc). Though, sometimes you want to play with
integers in the mpmath console and these limits are really annoying.
I consider this as a bugfix, despite it adds a new option.
This modifies the logarithm implementation for cases where taylor series
is more optimal (cancellation >= working precision), providing a faster
path for low precision cases depending on how close input is to 1.
The method could not be properly set for zeta().
kwargs didn't work fully for nstr() when applied to mpc types.
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
Python docs doesn't specify 0-padding behavior, when alignment is
specified. Lets be more strict here as Fraction/Decimal's: just reject
0 flag in this case.
float's behavior is just odd:
>>> format(1.123, '<020f')
'1.123000000000000000'
Processing in wrap_float_literals() can't work line-by-line, as the
tokenize.unparse() doesn't preserve indentation in this case. E.g.:
$ python -m mpmath --no-ipython
>>> def f():
... return 1.2
...
Traceback (most recent call last):
...
File "<unknown>", line 2
return mpf('1.2')
^^^^^^
IndentationError: expected an indented block after function definition on line 1
$ python3.9
Python 3.9.19+ (heads/3.9:3f5d9d12c7, Aug 29 2024, 13:17:09)
[GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> format(240605919345005.0, '.14g')
'2.40605919345e+14'
$ python3.8
Python 3.8.19+ (heads/3.8:e319f774f9, Aug 29 2024, 12:59:09)
[GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> format(240605919345005.0, '.14g')
'2.4060591934500e+14'
This reverts commit fc474e1069.
We don't have a concept of "complex infinity". But real infinity (of
any sign) is clearly a wrong answer here (it has well defined finite
phase and infinite absolute value), e.g.:
```pycon
>>> ellippi(1-1e-15, 1-1e-15j)
mpc(real='915673653288978.88', imag='-530451596311157.62')
>>> ellippi(1-1e-15, 1+1e-15j)
mpc(real='915673653288978.88', imag='530451596311157.62')
```
Closes#268
Probably this will look non-intuitive, but underlying floating-point
arithmetic is binary, not decimal. Thus, round(x, n) sometimes will pick
up a decimal representation with more than n digits. This is something
common for CPython < 2.7 and < 3.1:
Python 2.6.6 (r266:84292, Aug 12 2014, 07:57:07)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> round(0.42754287856598971, 2)
0.42999999999999999
And with this patch as well:
Python 3.12.5+ (heads/3.12:0181aa2e3e, Aug 29 2024, 14:55:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from mpmath import *
>>> round(mp.mpf(0.42754287856598971), 2)
mpf('0.42999999999999999')
>>> mp.pretty = True
>>> round(mp.mpf(0.42754287856598971), 2)
0.43
See also python/cpython#45921
Closes#455
In this case it was incorrectly assumed, that this is an equivalent of
'g' formatting type. It's not:
1) when no precision is specified - it should be equal to
repr_deps(prec) to represent the given value faithfully.
2) when fixed-point is used to format the result, it always includes at
least one digit past the decimal point.
Closes#856
This commit improves the code in `round_digits`: now the first digit in the `stddigits` list is excluded from the list of digits that must be rounded up when the `round_up` rounding mode is used. When rounding to a 0 digit, all the digits following it are looked up, and if one of them is different from 0, the 0 is rounded up.
This fixes some wrongfully formatted floats as, for example, when running the following code in the master branch
```python
>>> from gmpy2 import mpfr
>>> from mpmath import mp
>>> print('{:.2Uf}'.format(mpfr('0.25')))
0.25
>>> print('{:.2Uf}'.format(mp.mpf('0.25')))
0.26
>>>
```
After python/cpython#121149 this was broken on CPython 3.14:
_______________ [doctest] mpmath.functions.orthogonal.spherharm ____________
EXAMPLE LOCATION UNKNOWN, not showing all tests of that example
??? >>> fp.chop(fp.quad(lambda t,p: Y1(t,p)*Y2(t,p)*dS(t,p), *sphere))
Expected:
1.0000000000000007
Got:
1.0000000000000004
This particular failure could be fixed by:
diff --git a/mpmath/ctx_base.py b/mpmath/ctx_base.py
index 3309bfa..2ca2fac 100644
--- a/mpmath/ctx_base.py
+++ b/mpmath/ctx_base.py
@@ -110,7 +110,8 @@ def fdot(ctx, xs, ys=None, conjugate=False):
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)
+ return ctx.mpc(sum(((x*y).real for (x,y) in xs), ctx.zero),
+ sum(((x*y).imag for (x,y) in xs), ctx.zero))
def fprod(ctx, args):
prod = ctx.one
But this is just one case for the whole test suite...
Implemented the `__format__` method for the `_mpf` type.
Currently, `f`, `F`, `g`, `G`, `e`, and `E` formats are implemented, following the same specifications as specified for regular floats [here](https://docs.python.org/3/library/string.html#formatspec). Only nearest rounding is implemented.
A partial fix for #337.
The comparison in `mpmath/tests/test_convert.py::test_compatibility`
failed for `np.float16` in NumPy 2.0.0 since `2.0**-53` cannot be
represented in half-precision floating point type. (NumPy 2
implicitly converts the second operand to the type of the first one.)
Explicitly convert it to `np.float64` to ensure that the comparison is
done in sufficiently precise type.
// edited by Sergey B Kirpichev
The interval_count seems to be redundant, transformed_cache has entries
from the standard_cache... So, I believe a single dict is enough.
See #811. This partially address mentioned issue.
Now coverage reports will be submitted for pr's (this doesn't require a
token). But not for the master.
Not very helpful, as coverage diff will be wrt very outdated version of
the master, but...
Some systems (e.g., Debian/Ubuntu) ship a "python3" command instead of
"python" per PEP 394. But we may not be able to guarantee if
"python3" exists either, so we use sys.executable to determine the
name of the command.
* 'oo' and '-oo' for infinity
* '2+3*I' or '2+4I' (SymPy and Mathematica style imaginary unit)
* '2/3 + 4/5j' (rational parts for a complex number)
Closes#184
Affected functions: chebyfit(), polyval(), polyroots() and findpoly().
First step for #142
Please adapt your code to use asc=True (lowest degree - first) order of
polynomial coefficients. This will be a new default for mpmath releases
*after* the next release, v1.4.
Adapted from #414.
Partial fix for #345
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
* this version doesn't touch argument names (dps->ps)
* no support for float.hex()-style binary exponents
Closes#417. I think we can't do better: e.g. if we provide
the mpf._mpfr_ property - then in expressions like mpq(1,2)+mpf(1.0) -
second operand (and the whole expression) will be promoted to mpfr.
Also this corrects to_rational() private function to return a pair of
integers with same type.
To make this work correctly, rand() now supports arbitrary precision:
>>> x = mpmath.iv.rand() * mpmath.iv.convert(2**53)
>>> x - int(x)
mpi('0.0', '0.0')
>>> mpmath.iv.prec=1234
>>> x = mpmath.iv.rand() * mpmath.iv.convert(2**53)
>>> x - int(x)
mpi('0.05786680052076454587 ...
This change includes two hypsum related fixes:
1) It turns the ValueError exception, raised in mp.hypsum when encountering
convergence problems, into a more appropriate NoConvergence exception - just as
fp.hypsum does already.
2) It properly handles this NoConvergence exception withing the "fast path" of
hyp2f1. The same behavior is already used in the "fast path"s of _hyp2f0,
_hypq1fq, and _hyp_borel - and was broken since hypsum never raised the
expected NoConvergence exception (in the mp context). Similar to _hyp2f0, this
behavior can be suppressed with the keyword argument force_series=True.
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
Coverage tests added.
base=2**n and base=10 are supported so far. float(), float.fromhex()
and MPFR's style (see mpfr_strtofr() function) string formats are
accepted. to/from_bstr() undocumented helper functions were removed.
Partially taken from #414.
Co-authored-by: Jonathan Warner <warnerjon12@gmail.com>
The PyPy uses a different implementations for erf/erfc, while the
CPython per default uses coming with the libm (which answer is
better for 2.5). Let's choose an argument value where both
versions do agree.
* use math.erf, math.erfc, math.gamma
* use math.atan2
* use cmath.phase for fp.arg
* reorganize input handling in e1() and ei()
* remove unused code in math2.py
* use constants, e.g. math.inf or math.nan
* move most constants to the mpmath/ctx_fp.py
We use pytest for tests, it has everything that runtests.py has,
including support for profiling (pytest-profiling plugin).
So, let's drop this legacy stuff to avoid bugs like #579.
Adjusted function parameters to include an independent variable, t. Added other variations of each wave function. For square wave, added functions "squarew_floor" and "squarew_floorex". For triangle wave, added "trianglew_saw" function. For sawtooth, added functions "sawtoothw_mod" and "sawtoothw_floor".
The following things:
Added definitions, descriptions, and examples to functions "squarew", "squarew_floor", "squarew_floorex", "trianglew", "trianglew_saw", "sawtoothw", "sawtoothw_mod", "sawtooth_floor". Also added order of increasing run time for each type of signal wave.
Added logistic sigmoid function to signal.py file as well as the signal.txt file. Corrected examples in the signal.py file so that the period of each example is 2. Also, the last example of each function was correct so that input parameter t is 2 rather than 1.
Fixed typo from squarew_floorex to squarew_floor_ex
Tested the run time of all functions using 200 dps with t = 1.111111... Results were written under each function, giving both the function's return value as well as the run times.
Added type hints to all functions.
Added test file for signal.py.
Added unit triangle function to signal.txt and signal.py. Also added type hints to signal.txt and corrected sigmoid function in signal.py.
Added back signal.txt.
Changed signal files to be named signals.py and signals.txt.
Added unit triangle to test.py and fixed minor typos in docstrings.
Added 'triangle_wave' and 'sawtooth_wave'. Corrected sawtooth functions.
Removed extra wave functions and named remaining functions as squarew, trianglew, and sawtoothw. Added minor edits to function docstrings.
Removed test.py.
Corrected arguments to match those in signals.py.
Changed 'return 0' to 'return ctx.zero' and changed 'sigmoidw' to 'sigmoid'. Also changed 'signals.txt' to an rst file to match original repository.
square wave, triangle wave, sawtooth wave as a function of amplitude and period, but with really just meant as a template (largely copied from bessel.txt) from which Tina can do her work.
Added the following to mpmath/__init__.py
squarew = mp.squarew
trianglew = mp.trianglew
sawtoothw = mp.sawtoothw
unit_triangle = mp.unit_triangle
sigmoidw = mp.sigmoidw
This block was added to the bottom of the list of functions which began with "sqrt = mp.sqrt" and went up to "stirling2 = mp.stirling2".
runtests.py -skip ... can be used to skip test modules
testit(..., exit_on_fail=True) will return if a test fails
fixed a bug causing mpf values to return -1 hash rather than -2
Structure now more closely follow https://packaging.python.org/
To build docs:
python setup.py build_sphinx -c docs -b html,latex
make -C build/sphinx/latex all-pdf
The setuptools_scm usage was broken by 867d8784 (likely,
this is a source of problem in #585)
Closes#580 (an alternative to #583 and #581)
Solves #585 as well.
Note, this uses https://pypi.org/help/#apitoken feature
of PyPI. Instead of @master - I use the recent commit hash
from the gh-action-pypi-publish repo to make action more stable.
The secret used in ${{ secrets.PYPI_API_TOKEN }} needs to be created on
the settings page of the mpmath project.
Make matrices type-stable, not allowing mixed types in one matrix. Always use the type of the context.
Therefore, specifying an element type by the "force_type" argument does not make sense.
It did not work properly before either, the data was not stored in the given type:
```
>>> M = mpmath.matrix(mpmath.matrix([[0,1,2]]), force_type=bool)
>>> M
matrix(
[['0.0', '1.0', '1.0']])
>>> type(M[0,0])
<class 'mpmath.ctx_mp_python.mpf'>
>>> M._matrix__data
{(0, 1): mpf('1.0'), (0, 2): mpf('1.0')}
```
Now the argument is removed and gives a warning instead:
>>> mpmath.matrix(mpmath.matrix([[0,1,2]]), force_type=bool)
/mpmath/mpmath/matrices/matrices.py:288: UserWarning: The force_type argument was removed, it did not work properly anyway. If you want to force floating-point or interval computations, use the respective methods from `fp` or `mp` instead, e.g., `fp.matrix()` or `iv.matrix()`. If you want to truncate values to integer, use .apply(int) instead.
warnings.warn("The force_type argument was removed, it did not work"
matrix([['0.0', '1.0', '2.0']])
Non-interval datatypes were not converted to intervals, resulting in unexpected behavior. For example, M[i, j] didn't return mpi interval objects, but mpf floats, so M[i, j] * M[k, l] and, under certain conditions, M * M, was not performed as interval multiplication.
This could have unexpected consequences, as outlined below.
"Exact" computation for reference:
>>> import mpmath
>>> x = mpmath.convert('1.00000000000001') # 1.0000...001 rounded to the next mpf floating point value
>>> mpmath.mp.dps=1000
>>> x*x # Good approximation of x*x
mpf('1.00000000000001998401444325291756783368705994138804689654360263219301518944348572404123842716217041015625')
Interval arithmetic should return an interval containing that value, with some uncertainty.
Restart python to reset mp.dps.
Before this commit, the following occurs:
>>> import mpmath
>>> x = mpmath.convert('1.00000000000001')
>>> x
mpf('1.00000000000001')
>>> A = mpmath.matrix([[x]])
>>> B = mpmath.iv.matrix(A)
>>> C = mpmath.iv.matrix([[x]])
>>> A*A
matrix(
[['1.00000000000002']])
>>> B*B
matrix(
[['[1.000000000000019984, 1.000000000000019984]']])
>>> (B*B)[0,0].delta
mpi('0.0', '0.0')
>>> C*C
matrix(
[['[1.000000000000019984, 1.0000000000000202061]']])
B*B is wrong, the interval width must be nonzero at the default precision of 15 digits.
B*B is different from C*C, although both were initialized from the same numerical value and computed the same way.
After this commit, the result is valid:
>>> B*B
matrix(
[['[1.000000000000019984, 1.0000000000000202061]']])
>>> (B*B)[0,0].delta
mpi('2.2204460492503131e-16', '2.2204460492503131e-16')
Some more insight:
Old incorrect behavior:
>>> mpmath.iv.matrix(mpmath.eye(1))[0,0]
mpf('1.0')
New correct behavior:
>>> mpmath.iv.matrix(mpmath.eye(1))[0,0]
mpf('1.0')
>>> mpmath.iv.eye(1)[0,0]
mpi('1.0', '1.0')
>>> import mpmath
>>> mpmath.iv.matrix(mpmath.eye(1))
matrix(
[['[1.0, 1.0]']])
>>> mpmath.iv.matrix(mpmath.eye(1))[0,0]
mpi('1.0', '1.0')
>>> mpmath.fp.matrix(mpmath.eye(1))[0,0]
1.0
>>> mpmath.matrix(mpmath.eye(1))[0,0]
mpf('1.0')
The type now exactly matches the type returned by the context's matrix functions such as eye():
>>> mpmath.matrix(mpmath.eye(1))[0,0]
mpf('1.0')
>>> mpmath.eye(1)[0,0]
mpf('1.0')
>>> mpmath.iv.matrix(mpmath.eye(1))[0,0]
mpi('1.0', '1.0')
>>> mpmath.iv.eye(1)[0,0]
mpi('1.0', '1.0')
>>> mpmath.fp.matrix(mpmath.eye(1))[0,0]
1.0
>>> mpmath.fp.eye(1)[0,0]
1.0
This reverts c98b4d6. I believe, for platform-independent
Python library these tests are not needed, even if we add
gmpy-enabled tests. Right now this only enlarge the build
matrix and slowdown the testing process...
Problem: `rnd.getrandbits` can result in 0, so that `b` could equal to 0.
This fix makes it that b is a pseudorandom number close, but not equal,
to zero.
It's possible to install the Sage system as a normal Python package, as
e.g. in Fedora/Debian. In this case, presence of `sage.all` is not an
indicator whether the user is running Sage, and checking for 'SAGE_ROOT'
is more reliable.
see
https://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files
Also this commit expands some metadata, e.g. classifiers and
project_urls. Testing requirements are specified with "tests" extras.
Other development requirements are tracked with "develop" extras.
Peferences to extras are supported in tests_require since setuptools
v36.7.0, hence additional entry in setup_requires.
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`).
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::
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.
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`).
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::
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 <http://en.wikipedia.org/wiki/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)
If `matplotlib <http://matplotlib.sourceforge.net/>`_ 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.
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/
The mpmath setup files can be downloaded from the `Python Package Index <http://pypi.python.org/pypi/mpmath/>`_. 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 <http://pypi.python.org/pypi/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 <http://packages.debian.org/stable/python/python-mpmath>`_ and `ubuntu <https://launchpad.net/ubuntu/+source/mpmath>`_ 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 <http://www.opensuse.org/en/>`_. 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::
*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 <http://code.google.com/p/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 <https://pytest.org/>`_ 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 <https://github.com/fredrik-johansson/mpmath/issues>`_.
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 <http://sphinx.pocoo.org/>`_. 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 <http://sagemath.org/>`_, in version 4.1 or later of Sage.
Mpmath is preinstalled a regular Python module, and can be imported as usual within Sage::
In interactive code examples that follow, it will be assumed that
all items in the ``mpmath`` namespace have been imported::
To avoid inadvertently overriding other functions or objects, explicitly import
only the needed objects, or use the ``mpmath.`` or ``mp.`` namespaces::
>>> from mpmath import *
>>> from mpmath import sin
>>> sin(1)
mpf('0.8414709848078965')
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::
>>> import mpmath
>>> mpmath.sin(1)
mpf('0.8414709848078965')
from mpmath import sin, cos
sin(1), cos(1)
>>> from mpmath import mp # mp context object -- to be explained
>>> mp.sin(1)
mpf('0.8414709848078965')
import mpmath
mpmath.sin(1), mpmath.cos(1)
from mpmath import mp # mp context object -- to be explained
mp.sin(1), mp.cos(1)
..note::
Importing everything with ``from mpmath import *`` can be convenient,
especially when using mpmath interactively, but is best to avoid such
import statements in production code, as they make it unclear which
names are present in the namespace and wildcard-imported names may
conflict with other modules or variable names.
Number types
------------
@@ -40,6 +43,7 @@ The following section will provide a very short introduction to the types ``mpf`
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:
>>> from mpmath import mpf, mpc, mp
>>> mpf(4)
mpf('4.0')
>>> mpf(2.5)
@@ -49,7 +53,7 @@ The ``mpf`` type is analogous to Python's built-in ``float``. It holds a real nu
>>> mpf(mpf(2))
mpf('2.0')
>>> mpf("inf")
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:
@@ -76,7 +80,10 @@ Mpmath uses a global working precision; it does not keep track of the precision
Mpmath settings:
mp.prec = 53 [default: 53]
mp.dps = 15 [default: 15]
mp.rounding = 'n' [default: 'n']
mp.trap_complex = False [default: False]
mp.pretty_dps = 'str' [default: 'str']
mp.shortest_str = 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).
@@ -92,10 +99,10 @@ When the precision has been set, all ``mpf`` operations are carried out at that
The (binary) exponent is stored exactly and is independent of the precision.
The ``rounding`` property control default rounding mode for the context:
>>> mp.rounding # round to nearest is the default
'n'
>>> sin(1)
mpf('0.8414709848078965')
>>> mp.rounding = 'u' # round up
>>> sin(1)
mpf('0.84147098480789662')
>>> mp.rounding = 'n'
Temporarily changing the precision
..................................
@@ -125,10 +143,10 @@ It is often useful to change the precision during only part of a calculation. A
>>> # 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:
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
>>> from mpmath import extradps, workdps
>>> with workdps(20):
... print(mpf(1)/7)
... with extradps(10):
... print(mpf(1)/7)
@@ -138,7 +156,7 @@ Since Python 2.5, the ``with`` statement along with the mpmath functions ``workp
>>> 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 ``with`` statement ensures that the precision gets reset when exiting the block, even in the case that an exception is raised.
The ``workprec`` family of functions can also be used as function decorators:
@@ -152,6 +170,7 @@ The ``workprec`` family of functions can also be used as function decorators:
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``:
>>> from mpmath import exp, nprint
>>> mp.dps = 15
>>> print(exp(1))
2.71828182845905
@@ -180,6 +199,8 @@ Note that when creating a new ``mpf``, the value will at most be as accurate as
@@ -214,14 +235,49 @@ Setting the ``mp.pretty`` option will use the ``str()``-style output for ``repr(
>>> 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`:
To use enough digits to be able recreate value exactly, enable
``mp.shortest_str`` option. With this, repr/str and the new-style string
formatting *without format specifier* will use *minimal* number of decimal
digits that will preserve value on string input, like repr for CPython's
builtin floats:
>>> mp.shortest_str = True
>>> mp.pretty = True
>>> mpf(10.9) == mpf("10.9")
True
>>> mpf(10.9)
10.9
>>> f"{_}"
'10.9'
>>> mp.pretty = False
>>> mpf(10.9)
mpf('10.9')
>>> mp.shortest_str = False
Alternatively, set ``mp.pretty_dps``
to ``"repr"`` (default value is ``"str"``). Same option is used to control
default number of digits in the new-style string formatting *without format
specifier*, i.e. ``format(exp(mpf(1)))``.
>>> mp.pretty = True
>>> mpf(0.1)
0.1
>>> mp.pretty_dps = "repr"
>>> mpf(0.1)
0.10000000000000001
>>> mp.pretty_dps = "str"
>>> mp.pretty = False
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:`format syntax support
<mpmath.mpf.__format__>` or functions :func:`mpmath.nstr` and
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)
* Double-precision arithmetic using Python's builtin ``float`` and ``complex`` types (``fp``)
..note::
Using global context is not thread-safe, create instead
local contexts with e.g. :class:`~mpmath.MPContext`.
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(mpmath.fsum)
Help on method fsum in module mpmath.ctx_mp_python:
fsum(ctx, terms, absolute=False, squared=False) method of mpmath.ctx_mp.MPContext instance
<BLANKLINE>
fsum(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])
@@ -100,7 +103,6 @@ Common interface
[1.0 0.0]
[0.0 1.0]
>>> fp.pretty = False
>>> mp.pretty = False
Arbitrary-precision floating-point (``mp``)
@@ -110,6 +112,18 @@ The ``mp`` context is what most users probably want to use most of the time, as
See :doc:`basics` for a description of basic usage.
..autoclass:: mpmath.MPContext
Local contexts, created on demand, could be used just as the global ``mp``:
>>> from mpmath import MPContext
>>> ctx = MPContext()
>>> ctx.sin(1)
mpf('0.8414709848078965')
>>> ctx.prec = 113
>>> ctx.sin(1)
mpf('0.841470984807896506652502321630298954')
Arbitrary-precision interval arithmetic (``iv``)
------------------------------------------------
@@ -125,7 +139,6 @@ Interval arithmetic provides rigorous error tracking. If `f` is a mathematical f
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))
@@ -147,7 +160,11 @@ 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``::
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 raises :exc:`ValueError`::
>>> iv.mpf([1,2]) == iv.mpf([1,2])
True
@@ -159,12 +176,18 @@ The equality testing operators ``==`` and ``!=`` check whether their operands ar
True
>>> iv.mpf([1,2]) < 1
False
>>> iv.mpf([1,2]) < 2 # returns None
>>> iv.mpf([1,2]) < 2
Traceback (most recent call last):
...
ValueError
>>> 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([2,3])
Traceback (most recent call last):
...
ValueError
>>> iv.mpf([1,2]) < iv.mpf([-1,0])
False
@@ -196,12 +219,12 @@ Some transcendental functions are supported::
>>> iv.exp(0)
[1.0, 1.0]
>>> iv.exp(['-inf','inf'])
[0.0, +inf]
[0.0, inf]
>>>
>>> iv.exp(['-inf',0])
[0.0, 1.0]
>>> iv.exp([0,'inf'])
[1.0, +inf]
[1.0, inf]
>>> iv.exp([0,1])
[1.0, 2.7182818284590455349]
>>>
@@ -210,7 +233,7 @@ Some transcendental functions are supported::
>>> iv.log([0,1])
[-inf, 0.0]
>>> iv.log([0,'inf'])
[-inf, +inf]
[-inf, inf]
>>> iv.log(2)
[0.69314718055994528623, 0.69314718055994539725]
>>>
@@ -239,13 +262,19 @@ seen by increasing the precision::
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
>>> fp.sqrt(5)
2.23606797749979
>>> fp.sqrt(-5) # doctest:+SKIP
>>> fp.sqrt(-5)
2.23606797749979j
>>> fp.sin(10) # doctest:+SKIP
>>> fp.sin(10)
-0.5440211108893698
>>> fp.power(-1, 0.25) # doctest:+SKIP
>>> fp.power(-1, 0.25)
(0.7071067811865476+0.7071067811865475j)
>>> (-1) ** 0.25
(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::
@@ -304,3 +331,40 @@ The ``prec`` and ``dps`` attributes can be changed (for interface compatibility
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.
Beware that the ``fp`` context has signed zero, that can be used to distinguish
different sides of branch cuts. For example, ``fp.mpc(-1, -0.0)`` is treated
as though it lies *below* the branch cut for :func:`~mpmath.sqrt()`::
>>> fp.sqrt(fp.mpc(-1, -0.0))
-1j
>>> fp.sqrt(fp.mpc(-1, -1e-10))
(5e-11-1j)
But an argument of ``fp.mpc(-1, 0.0)`` is treated as though it lies *above* the
branch cut::
>>> fp.sqrt(fp.mpc(-1, +0.0))
1j
>>> fp.sqrt(fp.mpc(-1, +1e-10))
(5e-11+1j)
While near the branch cut, for small but nonzero deviations in components
results agreed with the ``mp`` contexts::
>>> fp.mpc(mp.sqrt(mp.mpc(-1, -1e-10)))
(5e-11-1j)
>>> fp.mpc(mp.sqrt(mp.mpc(-1, +1e-10)))
(5e-11+1j)
one has no signed zeros and allows to specify result *on the branch cut*
(nonpositive part of the real axis in this example)::
>>> fp.mpc(mp.sqrt(mp.mpc(-1, 0)))
1j
>>> fp.mpc(mp.sqrt(-1))
1j
Here it's continuous from the above of the :func:`~mpmath.sqrt()` branch
cut (from ``0`` along the negative real axis to the negative infinity).
@@ -7,25 +7,25 @@ Subject to certain restrictions, such "reverse engineering" is indeed possible t
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 <http://oldweb.cecm.sfu.ca/projects/ISC/ISCmain.html>`_ (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).
The number identification facilities in mpmath are inspired by the `Inverse Symbolic Calculator <http://wayback.cecm.sfu.ca/projects/ISC/ISCmain.html>`_ (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).
@@ -6,7 +6,7 @@ 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/
For general information about mpmath, see the project website https://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 <genindex.html>`_, or type ``help(mpmath.function_name)`` in the Python interactive prompt.
@@ -16,8 +16,8 @@ Introduction
.. toctree ::
:maxdepth:2
setup.txt
basics.txt
setup
basics
Basic features
----------------
@@ -25,9 +25,10 @@ Basic features
.. toctree ::
:maxdepth:2
contexts.txt
general.txt
plotting.txt
contexts
general
plotting
cli
Advanced mathematics
--------------------
@@ -38,10 +39,10 @@ provides extensive support for transcendental functions, evaluation of sums, int
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.