fix a major inefficiency in cos_sin for huge arguments. add manydigits problems demo. tweaks to manual and some housekeeping

This commit is contained in:
Fredrik Johansson
2008-03-12 14:16:05 +00:00
parent 04cfbe63ec
commit abc55f5140
7 changed files with 133 additions and 26 deletions
+4
View File
@@ -41,6 +41,10 @@ To install, 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
http://code.google.com/p/mpmath/source/checkout
+104
View File
@@ -0,0 +1,104 @@
"""
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.lib import *
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 first 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(secant(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
+5 -5
View File
@@ -387,7 +387,7 @@ pre.literal-block, pre.doctest-block {
</div>
<div class="section">
<h1><a class="toc-backref" href="#id2" id="basics" name="basics">2&nbsp;&nbsp;&nbsp;Basics</a></h1>
<p>For download and installation instructions, please refer to the README or the mpmath website (in most cases, installation should be as simple as running <tt class="docutils literal"><span class="pre">python</span> <span class="pre">easy_install</span> <span class="pre">mpmath</span></tt>). After the setup has completed, you can fire up the interactive Python interpreter and try the following:</p>
<p>For download and installation instructions, please refer to the README or the mpmath website. After the setup has completed, you can fire up the interactive Python interpreter and try the following:</p>
<pre class="literal-block">
&gt;&gt;&gt; from mpmath import *
&gt;&gt;&gt; mp.dps = 50
@@ -412,7 +412,7 @@ mpf('2.0')
&gt;&gt;&gt; mpf(&quot;inf&quot;)
mpf('+inf')
</pre>
<p>An <tt class="docutils literal"><span class="pre">mpc</span></tt> represents a complex number in rectangular form as a pair of <tt class="docutils literal"><span class="pre">mpf</span></tt> instances. It can be constructed from a Python <tt class="docutils literal"><span class="pre">complex</span></tt>, a real number, or a pair of real numbers:</p>
<p>The <tt class="docutils literal"><span class="pre">mpc</span></tt> type represents a complex number in rectangular form as a pair of <tt class="docutils literal"><span class="pre">mpf</span></tt> instances. It can be constructed from a Python <tt class="docutils literal"><span class="pre">complex</span></tt>, a real number, or a pair of real numbers:</p>
<pre class="literal-block">
&gt;&gt;&gt; mpc(2,3)
mpc(real='2.0', imag='3.0')
@@ -698,7 +698,7 @@ mpf('0.2500000000000000000000000000000000000000057')
<td>Natural logarithm (optionally base-b logarithm)</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">power(x,y)</span></tt></td>
<td>Power, x^y</td>
<td>Power, <tt class="docutils literal"><span class="pre">x**y</span></tt></td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">cos(x)</span></tt></td>
<td>Cosine</td>
@@ -901,14 +901,14 @@ mpf('0.2500000000000000000000000000000000000000057')
</div>
<div class="section">
<h3><a id="error-detection" name="error-detection">3.1.3&nbsp;&nbsp;&nbsp;Error detection</a></h3>
<p>The tanh-sinh algorithm is not suitable for adaptive quadrature, and does not perform well if there are singularities between the endpoints or if the integrand is very bumpy or oscillatory (such integrals should manually be split into smaller pieces). If the <tt class="docutils literal"><span class="pre">error</span></tt> option is set, <tt class="docutils literal"><span class="pre">quadts</span></tt> will return an error estimate along with the result; although this estimate is not always correct, it can be useful for debugging. You can also pass <tt class="docutils literal"><span class="pre">quadts</span></tt> the option <tt class="docutils literal"><span class="pre">verbose=True</span></tt> to show detailed progress.</p>
<p>The tanh-sinh algorithm is not suitable for adaptive quadrature, and does not perform well if there are singularities between the endpoints or if the integrand is oscillatory (such integrals should manually be split into smaller pieces). If the <tt class="docutils literal"><span class="pre">error</span></tt> option is set, <tt class="docutils literal"><span class="pre">quadts</span></tt> will return an error estimate along with the result; although this estimate is not always correct, it can be useful for debugging. You can also pass <tt class="docutils literal"><span class="pre">quadts</span></tt> the option <tt class="docutils literal"><span class="pre">verbose=True</span></tt> to show detailed progress.</p>
<p>A simple example where the algorithm fails is the function f(<em>x</em>) = abs(sin(<em>x</em>)), which is not smooth at <em>x</em> = pi. In this case, a close value is calculated, but the result is nowhere near the target accuracy; however, <tt class="docutils literal"><span class="pre">quadts</span></tt> gives a good estimate of the magnitude of the error:</p>
<pre class="literal-block">
&gt;&gt;&gt; mp.dps = 15
&gt;&gt;&gt; quadts(lambda x: abs(sin(x)), 0, 2*pi, error=True)
(mpf('3.9990089417677899'), mpf('0.001'))
</pre>
<p>Attempting to evaluate oscillatory integrals on large intervals by means of the tanh-sinh method is generally futile. This integral should be pi/2 = 1.57:</p>
<p>This highly oscillatory integral should be pi/2 = 1.57:</p>
<pre class="literal-block">
&gt;&gt;&gt; print quadts(lambda x: sin(x)/x, 0, inf, error=True)
(mpf('2.3840907358976544'), mpf('1.0'))
BIN
View File
Binary file not shown.
+5 -5
View File
@@ -28,7 +28,7 @@ This manual gives an introduction to mpmath's major features. Some supplementary
Basics
======
For download and installation instructions, please refer to the README or the mpmath website (in most cases, installation should be as simple as running ``python easy_install mpmath``). After the setup has completed, you can fire up the interactive Python interpreter and try the following::
For download and installation instructions, please refer to the README or the mpmath website. After the setup has completed, you can fire up the interactive Python interpreter and try the following::
>>> from mpmath import *
>>> mp.dps = 50
@@ -55,7 +55,7 @@ Mpmath provides two main numerical types: ``mpf`` and ``mpc``. The ``mpf`` type
>>> mpf("inf")
mpf('+inf')
An ``mpc`` 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::
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')
@@ -313,7 +313,7 @@ Function Description
``hypot(x,y)`` Euclidean norm
``exp(x)`` Exponential function
``log(x,b)`` Natural logarithm (optionally base-b logarithm)
``power(x,y)`` Power, x^y
``power(x,y)`` Power, ``x**y``
``cos(x)`` Cosine
``sin(x)`` Sine
``tan(x)`` Tangent
@@ -454,7 +454,7 @@ While double integrals are reasonably fast, even a simple triple integral at ver
Error detection
...............
The tanh-sinh algorithm is not suitable for adaptive quadrature, and does not perform well if there are singularities between the endpoints or if the integrand is very bumpy or oscillatory (such integrals should manually be split into smaller pieces). If the ``error`` option is set, ``quadts`` will return an error estimate along with the result; although this estimate is not always correct, it can be useful for debugging. You can also pass ``quadts`` the option ``verbose=True`` to show detailed progress.
The tanh-sinh algorithm is not suitable for adaptive quadrature, and does not perform well if there are singularities between the endpoints or if the integrand is oscillatory (such integrals should manually be split into smaller pieces). If the ``error`` option is set, ``quadts`` will return an error estimate along with the result; although this estimate is not always correct, it can be useful for debugging. You can also pass ``quadts`` the option ``verbose=True`` to show detailed progress.
A simple example where the algorithm fails is the function f(*x*) = abs(sin(*x*)), which is not smooth at *x* = pi. In this case, a close value is calculated, but the result is nowhere near the target accuracy; however, ``quadts`` gives a good estimate of the magnitude of the error::
@@ -462,7 +462,7 @@ A simple example where the algorithm fails is the function f(*x*) = abs(sin(*x*)
>>> quadts(lambda x: abs(sin(x)), 0, 2*pi, error=True)
(mpf('3.9990089417677899'), mpf('0.001'))
Attempting to evaluate oscillatory integrals on large intervals by means of the tanh-sinh method is generally futile. This integral should be pi/2 = 1.57::
This highly oscillatory integral should be pi/2 = 1.57::
>>> print quadts(lambda x: sin(x)/x, 0, inf, error=True)
(mpf('2.3840907358976544'), mpf('1.0'))
+14 -15
View File
@@ -1641,14 +1641,6 @@ def sin_taylor(x, prec):
k += 2
return s
def trig_reduce(x, prec):
pi_ = pi_fixed(prec)
pi4 = pi_ >> 2
pi2 = pi_ >> 1
n, rem = divmod(x + pi4, pi2)
rem -= pi4
return n, rem
def cos_sin(x, prec, rounding):
"""Simultaneously compute (cos(x), sin(x)) for real x."""
@@ -1661,6 +1653,7 @@ def cos_sin(x, prec, rounding):
return fone, fzero
magnitude = bc + exp
abs_mag = abs(magnitude)
# Very close to 0
if magnitude < -prec:
@@ -1682,17 +1675,23 @@ def cos_sin(x, prec, rounding):
s = fadd(x, (1, 1, magnitude-prec-4, 1), prec, rounding)
return c, s
bits_from_unit = abs(magnitude)
prec1 = prec + bits_from_unit + 15
wp = prec1
wp = wp1 = prec + 15
while 1:
n, rx = trig_reduce(to_fixed(x, wp), wp)
# Reduce modulo pi/4
rp = wp + abs_mag
a = to_fixed(x, rp)
pi_ = pi_fixed(rp)
pi4 = pi_ >> 2
pi2 = pi_ >> 1
n, rx = divmod(a+pi4, pi2)
rx -= pi4
rx >>= abs_mag
# If we're close to a root, we have to increase the
# fixed-point precision to obtain full relative accuracy
if abs(rx >> (prec1-8)) < 10:
wp += prec1 - bitcount(abs(rx))
if abs(rx >> (wp1 - 8)) < 10:
wp += wp1 - bitcount(abs(rx))
else:
break
+1 -1
View File
@@ -7,6 +7,6 @@ setup(name='mpmath',
author='Fredrik Johansson',
author_email='fredrik.johansson@gmail.com',
license = 'BSD',
packages=['mpmath', 'mpmath/lib', 'mpmath/apps', 'mpmath/tests'],
packages=['mpmath', 'demo', 'mpmath/tests'],
classifiers=['Topic :: Scientific/Engineering :: Mathematics']
)