[PATCH] Test also documentation under doc/

2 views
Skip to first unread message

Fabian Pedregosa

unread,
Jun 15, 2009, 11:33:45 AM6/15/09
to sympy-...@googlegroups.com, Fabian Pedregosa
This was previously untested, only docstrings where tested.

Implementation does not follow convention used by test in docstring and test files, where you have a runner that encapsulates the test and prints a nice output, it simply tests using doctest.testfile. It is not pretty, but at least we have the docs tested.

To test the docs, issue `python setup.py test_doc` at sympy's top level directory.

Most of the changes are derived from the fact that now pretty printing has changed a lot since the docs were written

Changed some printing examples that followed the syntax print_something to print something (print_python(expr) -> print python(expr)) because doctest does not tests the firtst correctly (it adds a None at the end).

Removed WildFunction docs in tutorial.txt, as WildFunction seems to be broken. See issue #1350 for more info

I also modified the match examples so that they are not platform-dependent

Removed :input: markup. There is no need for this, sphinx recognizes code blocks

Had to add some empty lines to modules/evalf.txt so that doctest recognizes correctly code blocks

Removed references to sqf_part, that function does not seem to exist

Also had to convert files that did not follow unix-style line ending (modules/evalf.txt) because doctest did not like them.

File doc/src/modules/evalf.txt takes a lot of time to complete because it has several tests that are quite heavy on computing. I did change the precission on one test (from 40 to 20) to make it a bit lighter.

Fix for failing test in polynomial.txt under amd64 by Ondrej Certik.
---
doc/src/index.txt | 2 +
doc/src/modules.txt | 1 +
doc/src/modules/concrete.txt | 6 +-
doc/src/modules/evalf.txt | 612 +++++++++++++++++++++------------------
doc/src/modules/functions.txt | 46 +++-
doc/src/modules/geometry.txt | 22 +-
doc/src/modules/integrals.txt | 27 +-
doc/src/modules/matrices.txt | 346 +++++++++++++---------
doc/src/modules/polynomials.txt | 146 ++++++----
doc/src/modules/rewriting.txt | 18 +-
doc/src/modules/series.txt | 16 +-
doc/src/modules/solvers.txt | 3 +-
doc/src/modules/statistics.txt | 39 ++-
doc/src/tutorial.txt | 153 ++++------
sympy/utilities/runtests.py | 13 +-
15 files changed, 829 insertions(+), 621 deletions(-)

diff --git a/doc/src/index.txt b/doc/src/index.txt
index 08e1342..9240925 100644
--- a/doc/src/index.txt
+++ b/doc/src/index.txt
@@ -29,4 +29,6 @@ Contents:
If something cannot be easily accesible from this page, it's a bug (`please
report it`_).

+This documentation is maintaned with doctutils, so you might see some comments in the form #doctest:... . You can safely ignore them.
+
.. _please report it: http://code.google.com/p/sympy/issues/list
diff --git a/doc/src/modules.txt b/doc/src/modules.txt
index 6c46683..8791796 100644
--- a/doc/src/modules.txt
+++ b/doc/src/modules.txt
@@ -28,6 +28,7 @@ access any SymPy module, or use this contens:
modules/polynomials.txt
modules/printing.txt
modules/plotting.txt
+ modules/query.txt
modules/statistics.txt
modules/concrete.txt
modules/solvers.txt
diff --git a/doc/src/modules/concrete.txt b/doc/src/modules/concrete.txt
index 9d495d7..dc8b6ef 100644
--- a/doc/src/modules/concrete.txt
+++ b/doc/src/modules/concrete.txt
@@ -13,6 +13,8 @@ To check if a sequence is of this type you can use `is_hypergeometric` method
which is available in Basic class. Here is simple example involving a
polynomial:

+ >>> from sympy import *
+ >>> n, k = symbols('nk')
>>> (n**2 + 1).is_hypergeometric(n)
True

@@ -73,5 +75,7 @@ minimal degree. Otherwise is will return `None` to say that sequence is not
hypergeometric:

>>> hypersimp(factorial(2*n), n)
- (1 + 2*n)*(2 + 2*n)
+ 2
+ 2 + 6*n + 4*n
>>> hypersimp(factorial(n**2), n)
+ None
diff --git a/doc/src/modules/evalf.txt b/doc/src/modules/evalf.txt
index 53251fe..2d31177 100644
--- a/doc/src/modules/evalf.txt
+++ b/doc/src/modules/evalf.txt
@@ -1,282 +1,330 @@
-Numerical evaluation
-====================
-
-Basics
-------
-
-Exact SymPy expressions can be converted to floating-point approximations (decimal numbers) using either the ``.evalf()`` method or the ``N()`` function. ``N(expr, <args>)`` is equivalent to ``sympify(expr).evalf(<args>)``.
-
- >>> from sympy import *
- >>> N(sqrt(2)*pi)
- 4.44288293815837
- >>> (sqrt(2)*pi).evalf()
- 4.44288293815837
-
-By default, numerical evaluation is performed to an accuracy of 15 decimal digits. You can optionally pass a desired accuracy (which should be a positive integer) as an argument to ``evalf`` or ``N``:
-
- >>> N(sqrt(2)*pi, 5)
- 4.4429
- >>> N(sqrt(2)*pi, 50)
- 4.4428829381583662470158809900606936986146216893757
-
-Complex numbers are supported:
-
- >>> N(1/(pi + I), 20)
- 0.28902548222223624241 - 0.091999668350375232456*I
-
-If the expression contains symbols or for some other reason cannot be evaluated numerically, calling ``.evalf()`` or ``N()`` returns the original expression, or in some cases a partially evaluated expression. For example, when the expression is a polynomial in expanded form, the coefficients are evaluated:
-
- >>> x = Symbol('x')
- >>> (pi*x**2 + x/3).evalf()
- 0.333333333333333*x + 3.14159265358979*x**2
-
-You can also use the standard Python functions ``float()``, ``complex()`` to convert SymPy expressions to regular Python numbers:
-
- >>> float(pi)
- 3.1415926535897931
- >>> complex(pi+E*I)
- (3.1415926535897931+2.7182818284590451j)
-
-If these functions are used, failure to evaluate the expression to an explicit number (for example if the expression contains symbols) will raise an exception.
-
-There is essentially no upper precision limit. The following command, for example, computes the first 100,000 digits of π/e:
-
- >>> N(pi/E, 100000)
- ...
-
-This shows digits 999,951 through 1,000,000 of pi:
-
- >>> str(N(pi, 10**6))[-50:]
- '95678796130331164628399634646042209010610577945815'
-
-High-precision calculations can be slow. It is recommended (but entirely optional) to install gmpy (http://code.google.com/p/gmpy/), which will significantly speed up computations such as the one above.
-
-Floating-point numbers
-----------------------
-
-Floating-point numbers in SymPy are instances of the class ``Real``. A ``Real`` can be created with a custom precision as second argument:
-
- >>> Real(0.1)
- 0.100000000000000
- >>> Real(0.1, 10)
- 0.1000000000
- >>> Real(0.1, 30)
- 0.100000000000000005551115123126
-
-As the last example shows, Python floats are only accurate to about 15 digits as inputs. To create a ``Real`` from a high-precision decimal number, it is better to pass a string or ``evalf`` a ``Rational``:
-
- >>> Real('0.1', 30)
- 0.100000000000000000000000000000
- >>> Rational(1,10).evalf(30)
- 0.100000000000000000000000000000
-
-The precision of a number determines 1) the precision to use when performing arithmetic with the number, and 2) the number of digits to display when printing the number. When two numbers with different precision are used together in an arithmetic operation, the higher of the precisions is used for the result. Note that precision therefore cannot be used as a model of error propagation or significance arithmetic; rather, this scheme is designed to ensure stability of numerical algorithms.
-
-``N`` and ``evalf`` can be used to change the precision of existing floating-point numbers:
-
- >>> N(3.5)
- 3.50000000000000
- >>> N(3.5, 5)
- 3.5000
- >>> N(3.5, 30)
- 3.50000000000000000000000000000
-
-Accuracy and error handling
----------------------------
-
-When the input to ``N`` or ``evalf`` is a complicated expression, numerical error propagation becomes a concern. As an example, consider the 100'th Fibonacci number and the excellent (but not exact) approximation φ^100 / √5 where φ is the golden ratio. With ordinary floating-point arithmetic, subtracting these numbers from each other erroneously results in a complete cancellation:
-
- >>> float(GoldenRatio**100/sqrt(5))
- 3.5422484817926187e+020
- >>> float(fibonacci(100))
- 3.5422484817926187e+020
- >>> float(fibonacci(100)) - float(GoldenRatio**100/sqrt(5))
- 0.0
-
-``N`` and ``evalf`` keep track of errors and automatically increase the precision used internally in order to obtain a correct result:
-
- >>> N(fibonacci(100) - GoldenRatio**100/sqrt(5))
- -5.64613129282185e-22
-
-Unfortunately, numerical evaluation cannot tell an expression that is exactly zero apart from one that is merely very small. The working precision is therefore capped, by default to around 100 digits. If we try with the 1000'th Fibonacci number, the following happens:
-
- >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5))
- -.0e+84
-
-The lack of digits in the returned number indicates that ``N`` failed to achieve full accuracy. The result indicates that the magnitude of the expression is something less than 10^84, but that is not a particularly good answer. To force a higher working precision, the ``maxprec`` keyword argument can be used:
-
- >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), maxprec=500)
- -4.60123853010113e-210
-
-Normally, ``maxprec`` can be set very high (thousands of digits), but be aware that this may cause significant slowdown in extreme cases. Alternatively, the ``strict=True`` option can be set to force an exception instead of silently returning a value with less than the requested accuracy:
-
- >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), strict=True)
- Traceback (most recent call last):
- ...
- sympy.core.evalf.PrecisionExhausted: Failed to distinguish the expression:
- -
- 43466557686937456435688527675040625802564660517371780402481729089536555417949051
- 89040387984007925516929592259308032263477520968962323987332247116164299644090653
- 3187938298969649928516003704476137795166849228875 - 5**(1/2)*GoldenRatio**1000/5
- -
- from zero. Try simplifying the input, using chop=True, or providing a higher max
- prec for evalf
-
-If we add a term so that the Fibonacci approximation becomes exact (the full form of Binet's formula), we get an expression that is exactly zero, but ``N`` does not know this:
-
- >>> f = fibonacci(100) - (GoldenRatio**100 - (GoldenRatio-1)**100)/sqrt(5)
- >>> N(f)
- .0e-113
- >>> N(f, maxprec=1000)
- .0e-1345
-
-In situations where such cancellations are known to occur, the ``chop`` options is useful. This basically replaces very small numbers with exact zeros:
-
- >>> N(f, chop=True)
- 0
-
-The ``chop`` option is very useful for cleaning up small real or imaginary parts:
-
- >>> N((E+pi*I)*(E-pi*I))
- 17.2586605000200 + .0e-16*I
- >>> N((E+pi*I)*(E-pi*I), chop=True)
- 17.2586605000200
-
-Sums and integrals
-------------------
-
-Sums (in particular infinite series) and integrals can be used like regular closed-form expressions, and support arbitrary-precision evaluation:
-
- >>> var('n x')
- (n, x)
- >>> Sum(1/n**n, (n, 1, oo)).evalf()
- 1.29128599706266
- >>> Integral(x**(-x), (x, 0, 1)).evalf()
- 1.29128599706266
- >>> Sum(1/n**n, (n, 1, oo)).evalf(50)
- 1.2912859970626635404072825905956005414986193682745
- >>> Integral(x**(-x), (x, 0, 1)).evalf(50)
- 1.2912859970626635404072825905956005414986193682745
- >>> (Integral(exp(-x**2), (x, -oo, oo)) ** 2).evalf(30)
- 3.14159265358979323846264338328
-
-By default, the tanh-sinh quadrature algorithm is used to evaluate integrals. This algorithm is very efficient and robust for smooth integrands (and even integrals with endpoint singularities), but may struggle with integrals that are highly oscillatory or have mid-interval discontinuities. In many cases, ``evalf``/``N`` will correctly estimate the error. With the following integral, the result is accurate but only good to four digits:
-
- >>> f = abs(sin(x))
- >>> Integral(abs(sin(x)), (x, 0, 4)).evalf()
- 2.346
-
-It is better to split this integral into two pieces:
-
- >>> (Integral(f, (x, 0, pi)) + Integral(f, (x, pi, 4))).evalf()
- 2.34635637913639
-
-A similar example is the following oscillatory integral:
-
- >>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(maxprec=20)
- 5.03e-1
-
-It can be dealt with much more efficiently by telling ``evalf`` or ``N`` to use an oscillatory quadrature algorithm:
-
- >>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(quad='osc')
- 0.504067061906928
- >>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(40, quad='osc')
- 0.5040670619069283719898561177411482296250
-
-Oscillatory quadrature requires an integrand containing a factor cos(ax+b) or sin(ax+b). Note that many other oscillatory integrals can be transformed to this form with a change of variables:
-
- >>> Integral(sin(1/x), (x, 0, 1)).transform(x, 1/x)
- Integral(1/x**2*sin(x), (x, 1, oo))
- >>> N(_, quad='osc')
- 0.504067061906928
-
-Infinite series use direct summation if the series converges quickly enough. Otherwise, extrapolation methods (generally the Euler-Maclaurin formula but also Richardson extrapolation) are used to speed up convergence. This allows high-precision evaluation of slowly convergent series:
-
- >>> var('k')
- k
- >>> Sum(1/k**2, (k, 1, oo)).evalf()
- 1.64493406684823
- >>> zeta(2).evalf()
- 1.64493406684823
- >>> Sum(1/k-log(1+1/k), (k, 1, oo)).evalf()
- 0.577215664901533
- >>> Sum(1/k-log(1+1/k), (k, 1, oo)).evalf(50)
- 0.57721566490153286060651209008240243104215933593992
- >>> EulerGamma.evalf(50)
- 0.57721566490153286060651209008240243104215933593992
-
-The Euler-Maclaurin formula is also used for finite series, allowing them to be approximated quickly without evaluating all terms:
-
- >>> Sum(1/k, (k, 10000000, 20000000)).evalf()
- 0.693147255559946
-
-Note that ``evalf`` makes some assumptions that are not always optimal. For fine-tuned control over numerical summation, it might be worthwhile to manually use the method ``Sum.euler_maclaurin``.
-
-Special optimizations are used for rational hypergeometric series (where the term is a product of polynomials, powers, factorials, binomial coefficients and the like). ``N``/``evalf`` sum series of this type very rapidly to high precision. For example, this Ramanujan formula for pi can be summed to 10,000 digits in a fraction of a second with a simple command:
-
- >>> f = factorial
- >>> R = 9801/sqrt(8)/Sum(f(4*n)*(1103+26390*n)/f(n)**4/396**(4*n), (n, 0, oo))
- >>> N(R, 10000)
- 3.141592653589793238462643383279502884197169399375105820974944592307816406286208
- 99862803482534211706798214808651328230664709384460955058223172535940812848111745
- 02841027019385211055596446229489549303819644288109756659334461284756482337867831
- ...
-
-Numerical simplification
-------------------------
-
-The function ``nsimplify`` attempts to find a formula that is numerically equal to the given input. This feature can be used to guess an exact formula for an approximate floating-point input, or to guess a simpler formula for a complicated symbolic input. The algorithm used by ``nsimplify`` is capable of identifying simple fractions, simple algebraic expressions, linear combinations of given constants, and certain elementary functional transformations of any of the preceding.
-
-Optionally, ``nsimplify`` can be passed a list of constants to include (e.g. pi) and a minimum numerical tolerance. Here are some elementary examples:
-
- >>> nsimplify(0.1)
- 1/10
- >>> nsimplify(6.28, [pi], tolerance=0.01)
- 2*pi
- >>> nsimplify(pi, tolerance=0.01)
- 22/7
- >>> nsimplify(pi, tolerance=0.001)
- 355/113
- >>> nsimplify(0.33333, tolerance=1e-4)
- 1/3
- >>> nsimplify(2.0**(1/3.), tolerance=0.001)
- 635/504
- >>> nsimplify(2.0**(1/3.), tolerance=0.001, full=True)
- 2**(1/3)
-
-Here are several more advanced examples:
-
- >>> nsimplify(Real('0.130198866629986772369127970337',30), [pi, E])
- 1/(2*E + 5*pi/7)
- >>> pprint(nsimplify(cos(atan('1/3'))))
- ____
- 3*\/ 10
- --------
- 10
- >>> pprint(nsimplify(4/(1+sqrt(5)), [GoldenRatio]))
- -2 + 2*GoldenRatio
- >>> pprint(nsimplify(2 + exp(2*atan('1/4')*I)))
- 49 8*I
- -- + ---
- 17 17
- >>> pprint(nsimplify((1/(exp(3*pi*I/5)+1))))
- _____________
- / ___
- / \/ 5
- 1/2 - I* / 1/4 + -----
- \/ 10
- >>> pprint(nsimplify(I**I, [pi]))
- -pi
- ---
- 2
- e
- >>> pprint(nsimplify(Sum(1/n**2, (n, 1, oo)), [pi]))
- 2
- pi
- ---
- 6
- >>> pprint(nsimplify(gamma('1/4')*gamma('3/4'), [pi]))
- ___
- pi*\/ 2
-
-
+Numerical evaluation
+====================
+
+Basics
+------
+
+Exact SymPy expressions can be converted to floating-point approximations (decimal numbers) using either the ``.evalf()`` method or the ``N()`` function. ``N(expr, <args>)`` is equivalent to ``sympify(expr).evalf(<args>)``.
+
+ >>> from sympy import *
+ >>> N(sqrt(2)*pi)
+ 4.44288293815837
+ >>> (sqrt(2)*pi).evalf()
+ 4.44288293815837
+
+
+By default, numerical evaluation is performed to an accuracy of 15 decimal digits. You can optionally pass a desired accuracy (which should be a positive integer) as an argument to ``evalf`` or ``N``:
+
+ >>> N(sqrt(2)*pi, 5)
+ 4.4429
+ >>> N(sqrt(2)*pi, 50)
+ 4.4428829381583662470158809900606936986146216893757
+
+
+Complex numbers are supported:
+
+ >>> N(1/(pi + I), 20)
+ 0.28902548222223624241 - 0.091999668350375232456*I
+
+
+If the expression contains symbols or for some other reason cannot be evaluated numerically, calling ``.evalf()`` or ``N()`` returns the original expression, or in some cases a partially evaluated expression. For example, when the expression is a polynomial in expanded form, the coefficients are evaluated:
+
+ >>> x = Symbol('x')
+ >>> (pi*x**2 + x/3).evalf()
+ 2
+ 0.333333333333333*x + 3.14159265358979*x
+
+
+You can also use the standard Python functions ``float()``, ``complex()`` to convert SymPy expressions to regular Python numbers:
+
+ >>> float(pi)
+ 3.14159265359
+ >>> complex(pi+E*I)
+ (3.14159265359+2.71828182846j)
+
+
+If these functions are used, failure to evaluate the expression to an explicit number (for example if the expression contains symbols) will raise an exception.
+
+There is essentially no upper precision limit. The following command, for example, computes the first 100,000 digits of π/e:
+
+ >>> N(pi/E, 100000) #doctest: +SKIP
+ ...
+
+
+This shows digits 999,951 through 1,000,000 of pi:
+
+ >>> str(N(pi, 10**6))[-50:] #doctest: +SKIP
+ '95678796130331164628399634646042209010610577945815'
+
+
+High-precision calculations can be slow. It is recommended (but entirely optional) to install gmpy (http://code.google.com/p/gmpy/), which will significantly speed up computations such as the one above.
+
+Floating-point numbers
+----------------------
+
+Floating-point numbers in SymPy are instances of the class ``Real``. A ``Real`` can be created with a custom precision as second argument:
+
+ >>> Real(0.1)
+ 0.100000000000000
+ >>> Real(0.1, 10)
+ 0.1000000000
+ >>> Real(0.1, 30)
+ 0.100000000000000005551115123126
+
+
+As the last example shows, Python floats are only accurate to about 15 digits as inputs. To create a ``Real`` from a high-precision decimal number, it is better to pass a string or ``evalf`` a ``Rational``:
+
+ >>> Real('0.1', 30)
+ 0.100000000000000000000000000000
+ >>> Rational(1,10).evalf(30)
+ 0.100000000000000000000000000000
+
+
+The precision of a number determines 1) the precision to use when performing arithmetic with the number, and 2) the number of digits to display when printing the number. When two numbers with different precision are used together in an arithmetic operation, the higher of the precisions is used for the result. Note that precision therefore cannot be used as a model of error propagation or significance arithmetic; rather, this scheme is designed to ensure stability of numerical algorithms.
+
+``N`` and ``evalf`` can be used to change the precision of existing floating-point numbers:
+
+ >>> N(3.5)
+ 3.50000000000000
+ >>> N(3.5, 5)
+ 3.5000
+ >>> N(3.5, 30)
+ 3.50000000000000000000000000000
+
+
+Accuracy and error handling
+---------------------------
+
+When the input to ``N`` or ``evalf`` is a complicated expression, numerical error propagation becomes a concern. As an example, consider the 100'th Fibonacci number and the excellent (but not exact) approximation φ^100 / √5 where φ is the golden ratio. With ordinary floating-point arithmetic, subtracting these numbers from each other erroneously results in a complete cancellation:
+
+ >>> float(GoldenRatio**1000/sqrt(5))
+ 4.34665576869e+208
+ >>> float(fibonacci(1000))
+ 4.34665576869e+208
+ >>> float(fibonacci(1000)) - float(GoldenRatio**1000/sqrt(5))
+ 0.0
+
+
+``N`` and ``evalf`` keep track of errors and automatically increase the precision used internally in order to obtain a correct result:
+
+ >>> N(fibonacci(100) - GoldenRatio**100/sqrt(5))
+ -5.64613129282185e-22
+
+
+Unfortunately, numerical evaluation cannot tell an expression that is exactly zero apart from one that is merely very small. The working precision is therefore capped, by default to around 100 digits. If we try with the 1000'th Fibonacci number, the following happens:
+
+ >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5))
+ -.0e+84
+
+
+The lack of digits in the returned number indicates that ``N`` failed to achieve full accuracy. The result indicates that the magnitude of the expression is something less than 10^84, but that is not a particularly good answer. To force a higher working precision, the ``maxprec`` keyword argument can be used:
+
+ >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), maxprec=500)
+ -4.60123853010113e-210
+
+
+Normally, ``maxprec`` can be set very high (thousands of digits), but be aware that this may cause significant slowdown in extreme cases. Alternatively, the ``strict=True`` option can be set to force an exception instead of silently returning a value with less than the requested accuracy:
+
+ >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), strict=True)
+ Traceback (most recent call last):
+ ...
+ PrecisionExhausted: Failed to distinguish the expression:
+ <BLANKLINE>
+ 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875 - 5**(1/2)*GoldenRatio**1000/5
+ <BLANKLINE>
+ from zero. Try simplifying the input, using chop=True, or providing a higher maxprec for evalf
+
+
+If we add a term so that the Fibonacci approximation becomes exact (the full form of Binet's formula), we get an expression that is exactly zero, but ``N`` does not know this:
+
+ >>> f = fibonacci(100) - (GoldenRatio**100 - (GoldenRatio-1)**100)/sqrt(5)
+ >>> N(f)
+ .0e-113
+ >>> N(f, maxprec=1000)
+ .0e-1345
+
+
+In situations where such cancellations are known to occur, the ``chop`` options is useful. This basically replaces very small numbers with exact zeros:
+
+ >>> N(f, chop=True)
+ 0
+
+
+The ``chop`` option is very useful for cleaning up small real or imaginary parts:
+
+ >>> N((E+pi*I)*(E-pi*I))
+ 17.25866050002 + .0e-16*I
+ >>> N((E+pi*I)*(E-pi*I), chop=True)
+ 17.2586605000200
+
+
+Sums and integrals
+------------------
+
+Sums (in particular infinite series) and integrals can be used like regular closed-form expressions, and support arbitrary-precision evaluation:
+
+ >>> var('n x')
+ (n, x)
+ >>> Sum(1/n**n, (n, 1, oo)).evalf()
+ 1.29128599706266
+ >>> Integral(x**(-x), (x, 0, 1)).evalf()
+ 1.29128599706266
+ >>> Sum(1/n**n, (n, 1, oo)).evalf(50)
+ 1.2912859970626635404072825905956005414986193682745
+ >>> Integral(x**(-x), (x, 0, 1)).evalf(50)
+ 1.2912859970626635404072825905956005414986193682745
+ >>> (Integral(exp(-x**2), (x, -oo, oo)) ** 2).evalf(30)
+ 3.14159265358979323846264338328
+
+
+By default, the tanh-sinh quadrature algorithm is used to evaluate integrals. This algorithm is very efficient and robust for smooth integrands (and even integrals with endpoint singularities), but may struggle with integrals that are highly oscillatory or have mid-interval discontinuities. In many cases, ``evalf``/``N`` will correctly estimate the error. With the following integral, the result is accurate but only good to four digits:
+
+ >>> f = abs(sin(x))
+ >>> Integral(abs(sin(x)), (x, 0, 4)).evalf()
+ 2.346
+
+
+It is better to split this integral into two pieces:
+
+ >>> (Integral(f, (x, 0, pi)) + Integral(f, (x, pi, 4))).evalf()
+ 2.34635637913639
+
+
+A similar example is the following oscillatory integral:
+
+ >>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(maxprec=20)
+ 5.e-1
+
+
+It can be dealt with much more efficiently by telling ``evalf`` or ``N`` to use an oscillatory quadrature algorithm:
+
+ >>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(quad='osc')
+ 0.504067061906928
+ >>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(20, quad='osc')
+ 0.50406706190692837199
+
+
+Oscillatory quadrature requires an integrand containing a factor cos(ax+b) or sin(ax+b). Note that many other oscillatory integrals can be transformed to this form with a change of variables:
+
+ >>> intgrl = Integral(sin(1/x), (x, 0, 1)).transform(x, 1/x)
+ >>> intgrl
+ oo
+ /
+ |
+ | sin(x)
+ | ------ dx
+ | 2
+ | x
+ |
+ /
+ 1
+ >>> N(intgrl, quad='osc')
+ 0.504067061906928
+
+
+Infinite series use direct summation if the series converges quickly enough. Otherwise, extrapolation methods (generally the Euler-Maclaurin formula but also Richardson extrapolation) are used to speed up convergence. This allows high-precision evaluation of slowly convergent series:
+
+ >>> var('k')
+ k
+ >>> Sum(1/k**2, (k, 1, oo)).evalf()
+ 1.64493406684823
+ >>> zeta(2).evalf()
+ 1.64493406684823
+ >>> Sum(1/k-log(1+1/k), (k, 1, oo)).evalf()
+ 0.577215664901533
+ >>> Sum(1/k-log(1+1/k), (k, 1, oo)).evalf(50)
+ 0.57721566490153286060651209008240243104215933593992
+ >>> EulerGamma.evalf(50)
+ 0.57721566490153286060651209008240243104215933593992
+
+
+The Euler-Maclaurin formula is also used for finite series, allowing them to be approximated quickly without evaluating all terms:
+
+ >>> Sum(1/k, (k, 10000000, 20000000)).evalf()
+ 0.693147255559946
+
+
+Note that ``evalf`` makes some assumptions that are not always optimal. For fine-tuned control over numerical summation, it might be worthwhile to manually use the method ``Sum.euler_maclaurin``.
+
+Special optimizations are used for rational hypergeometric series (where the term is a product of polynomials, powers, factorials, binomial coefficients and the like). ``N``/``evalf`` sum series of this type very rapidly to high precision. For example, this Ramanujan formula for pi can be summed to 10,000 digits in a fraction of a second with a simple command:
+
+ >>> f = factorial
+ >>> n = Symbol('n', integer=True)
+ >>> R = 9801/sqrt(8)/Sum(f(4*n)*(1103+26390*n)/f(n)**4/396**(4*n), (n, 0, oo)) #doctest: +SKIP
+ >>> N(R, 10000) #doctest: +SKIP
+ 3.141592653589793238462643383279502884197169399375105820974944592307816406286208
+ 99862803482534211706798214808651328230664709384460955058223172535940812848111745
+ 02841027019385211055596446229489549303819644288109756659334461284756482337867831
+ ...
+
+
+Numerical simplification
+------------------------
+
+The function ``nsimplify`` attempts to find a formula that is numerically equal to the given input. This feature can be used to guess an exact formula for an approximate floating-point input, or to guess a simpler formula for a complicated symbolic input. The algorithm used by ``nsimplify`` is capable of identifying simple fractions, simple algebraic expressions, linear combinations of given constants, and certain elementary functional transformations of any of the preceding.
+
+Optionally, ``nsimplify`` can be passed a list of constants to include (e.g. pi) and a minimum numerical tolerance. Here are some elementary examples:
+
+ >>> nsimplify(0.1)
+ 1/10
+ >>> nsimplify(6.28, [pi], tolerance=0.01)
+ 2*pi
+ >>> nsimplify(pi, tolerance=0.01)
+ 22/7
+ >>> nsimplify(pi, tolerance=0.001)
+ 355
+ ---
+ 113
+ >>> nsimplify(0.33333, tolerance=1e-4)
+ 1/3
+ >>> nsimplify(2.0**(1/3.), tolerance=0.001)
+ 635
+ ---
+ 504
+ >>> nsimplify(2.0**(1/3.), tolerance=0.001, full=True)
+ 3 ___
+ \/ 2
+
+
+Here are several more advanced examples:
+
+ >>> nsimplify(Real('0.130198866629986772369127970337',30), [pi, E])
+ 1
+ ----------
+ 5*pi
+ 2*E + ----
+ 7
+ >>> nsimplify(cos(atan('1/3')))
+ ____
+ 3*\/ 10
+ --------
+ 10
+ >>> nsimplify(4/(1+sqrt(5)), [GoldenRatio])
+ -2 + 2*GoldenRatio
+ >>> nsimplify(2 + exp(2*atan('1/4')*I))
+ 49 8*I
+ -- + ---
+ 17 17
+ >>> nsimplify((1/(exp(3*pi*I/5)+1)))
+ _____________
+ / ___
+ / \/ 5
+ 1/2 - I* / 1/4 + -----
+ \/ 10
+ >>> nsimplify(I**I, [pi])
+ -pi
+ ---
+ 2
+ e
+ >>> n = Symbol('n')
+ >>> nsimplify(Sum(1/n**2, (n, 1, oo)), [pi])
+ 2
+ pi
+ ---
+ 6
+ >>> nsimplify(gamma('1/4')*gamma('3/4'), [pi])
+ ___
+ pi*\/ 2
+
+
+
diff --git a/doc/src/modules/functions.txt b/doc/src/modules/functions.txt
index f47ac00..a4b22af 100644
--- a/doc/src/modules/functions.txt
+++ b/doc/src/modules/functions.txt
@@ -4,39 +4,49 @@ Functions Module
.. module:: sympy.functions

Elementary
---------
+==========
+
This module implements elementary functions (abs, max, etc.)

+
abs
---
+
Returns the absolute value of the argument.

Examples::
>>> from sympy.functions import abs
+ >>> abs(-1)
+ 1
+
.. autoclass:: sympy.functions.elementary.abs

+
arg
---
+
Returns the argument (in radians) of a complex number. For a real
number, the arguement is always 0.

Examples::
>>> from sympy.functions import arg
+ >>> from sympy import I, sqrt
>>> arg(2.0)
0
>>> arg(I)
pi
--
- 2
+ 2
>>> arg(sqrt(2) + I*sqrt(2))
pi
--
- 4
+ 4

.. autoclass:: sympy.functions.elementary.arg

conjugate
---------
+
Returns the 'complex conjugate <http://en.wikipedia.org/wiki/Complex_conjugation>'_
of the argument. In mathematics, the complex conjugate of a complex number is given
by changing the sign of the imaginary part. Thus, the conjugate of the complex number
@@ -49,6 +59,7 @@ by changing the sign of the imaginary part. Thus, the conjugate of the complex n

Examples::
>>> from sympy.functions import conjugate
+ >>> from sympy import I
>>> conjugate(2)
2
>>> conjugate(I)
@@ -56,8 +67,10 @@ Examples::

.. autoclass:: sympy.functions.elementary.conjugate

+
min_
---
+
Returns the minimum of two (comparable) expressions.

Examples::
@@ -67,22 +80,26 @@ Examples::
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> min_(1,x)
- min_(1,x)
+ min_(1, x)

It is named min_ and not min to avoid conflicts with built-in function min.

.. autoclass:: sympy.functions.elementary.min_

+
max
---
+
Returns the maximum of two (comparable) expressions

It is named max_ and not max to avoid conflicts with built-in function min.

.. autoclass:: sympy.functions.elementary.max_

+
re
--
+
Return the real part of an expression

Examples::
@@ -90,10 +107,13 @@ Examples::
>>> from sympy import I
>>> re(2+3*I)
2
+
.. autoclass:: sympy.functions.elementary.re

+
sqrt
----
+
Returns the square root of an expression. It is equivalent to raise to Rational(1,2)

>>> from sympy.functions import sqrt
@@ -103,6 +123,7 @@ Returns the square root of an expression. It is equivalent to raise to Rational(

.. autoclass:: sympy.functions.elementary.sqrt

+
sign
----

@@ -112,7 +133,7 @@ Returns the sign of an expression, that is:
1 if expr is positive

>>> from sympy.functions import sign
- >>> sign(-oo)
+ >>> sign(-1)
-1
>>> sign(0)
0
@@ -121,32 +142,43 @@ Returns the sign of an expression, that is:


Combinatorial
---------
+=============
+
This moduel implement's some combinatorial functions.

+
Binomial
--------
+
.. autoclass:: sympy.functions.combinatorial.factorials.Binomial

+
Factorial
---------
+
.. autoclass:: sympy.functions.combinatorial.factorials.Factorial

+
FallingFactorial
---------------
+
.. autoclass:: sympy.functions.combinatorial.factorials.FallingFactorial

+
MultiFactorial
-----------
+
.. autoclass:: sympy.functions.combinatorial.factorials.MultiFactorial

+
RisingFactorial
-------------
+
.. autoclass:: sympy.functions.combinatorial.factorials.RisingFactorial


Special
-------
+=======

DiracDelta
-----------
diff --git a/doc/src/modules/geometry.txt b/doc/src/modules/geometry.txt
index 64a6b3e..61d74c3 100644
--- a/doc/src/modules/geometry.txt
+++ b/doc/src/modules/geometry.txt
@@ -39,6 +39,7 @@ Example Usage
The following Python session gives one an idea of how to work with some of the
geometry module.

+ >>> from sympy import *
>>> from sympy.geometry import *
>>> x = Point(0, 0)
>>> y = Point(1, 1)
@@ -52,10 +53,12 @@ geometry module.
>>> t.area
1/2
>>> t.medians[x]
- >>> Segment(Point(1, 1/2), Point(0, 0))
+ ((0, 0), (1, 1/2))
+ >>> Segment(Point(1, S(1)/2), Point(0, 0))
+ ((0, 0), (1, 1/2))
>>> m = t.medians
>>> intersection(m[x], m[y], m[zp])
- [Point(2/3, 1/3)]
+ [(2/3, 1/3)]
>>> c = Circle(x, 5)
>>> l = Line(Point(5, -5), Point(5, 5))
>>> c.is_tangent(l) # is l tangent to c?
@@ -64,7 +67,10 @@ geometry module.
>>> c.is_tangent(l) # is l tangent to c?
False
>>> intersection(c, l)
- [Point(-25/2*2/25**(1/2), -25/2*2/25**(1/2)), Point(25/2*2/25**(1/2), 25/2*2/25**(1/2))]
+ ___ ___ ___ ___
+ -5*\/ 2 -5*\/ 2 5*\/ 2 5*\/ 2
+ [(--------, --------), (-------, -------)]
+ 2 2 2 2

Intersection of medians
-----------------------
@@ -108,11 +114,11 @@ An in-depth example: Pappus' Theorem
>>> l2 = Line(Point(0, 0), Point(2, -2))
>>>
>>> def subs_point(l, val):
- >>> """Take an arbitrary point and make it a fixed point."""
- >>> t = Symbol('t')
- >>> ap = l.arbitrary_point()
- >>> return Point(ap[0].subs(t, val), ap[1].subs(t, val))
- >>>
+ ... """Take an arbitrary point and make it a fixed point."""
+ ... t = Symbol('t')
+ ... ap = l.arbitrary_point()
+ ... return Point(ap[0].subs(t, val), ap[1].subs(t, val))
+ ...
>>> p11 = subs_point(l1, 5)
>>> p12 = subs_point(l1, 6)
>>> p13 = subs_point(l1, 11)
diff --git a/doc/src/modules/integrals.txt b/doc/src/modules/integrals.txt
index 7405f07..1b4453e 100644
--- a/doc/src/modules/integrals.txt
+++ b/doc/src/modules/integrals.txt
@@ -20,32 +20,37 @@ SymPy can integrate a vast array of functions. It can integrate polynomial funct
2 3
x x
x + -- + --
- 2 3
-rational functions...
+ 2 3
+
+Rational functions::

>>> integrate(x/(x**2+2*x+1), x)
- 1
- ----- + log(1 + x)
- 1 + x
+ 1
+ log(1 + x) + -----
+ 1 + x
+

Exponential-polynomial functions. Multiplicative combinations of polynomials and the functions exp, cos and sin can be integrated by hand using repeated integration by parts, which is an extremely tedious process. Happily, SymPy will deal with these integrals.

>>> integrate(x**2 * exp(x) * cos(x), x)
- x x 2 x 2 x
- e *sin(x) cos(x)*e x *cos(x)*e x *e *sin(x) x
- --------- - --------- + ------------ + ------------ - x*e *sin(x)
- 2 2 2 2
+ x 2 x x 2 x
+ e *sin(x) x *e *sin(x) x cos(x)*e x *cos(x)*e
+ --------- + ------------ - x*e *sin(x) - --------- + ------------
+ 2 2 2 2
+

even a few nonelementary integrals (in particular, some integrals involving the error function) can be evaluated::

>>> integrate(exp(-x**2)*erf(x), x)
- ____ 2
+ ____ 2
\/ pi *erf (x)
--------------
- 4
+ 4
+

Internals
---------
+
There is a general method for calculating antiderivatives of elementary functions, called the Risch algorithm. The Risch algorithm is a decision procedure that can determine whether an elementary solution exists, and in that case calculate it. It can be extended to handle many nonelementary functions in addition to the elementary ones.

SymPy currently uses a simplified version of the Risch algorithm, called the Risch-Norman algorithm. This algorithm is much faster, but may fail to find an antiderivative, although it is still very powerful. SymPy also uses pattern matching and heuristics to speed up evaluation of some types of integrals, e.g. polynomials.
diff --git a/doc/src/modules/matrices.txt b/doc/src/modules/matrices.txt
index 148a8f1..9fc0a11 100644
--- a/doc/src/modules/matrices.txt
+++ b/doc/src/modules/matrices.txt
@@ -9,18 +9,20 @@ Creating Matrices
The linear algebra module is designed to be as simple as possible. First, we
import and declare our first Matrix object:

- >>> from sympy.matrices import Matrix
+ >>> from sympy.matrices import *
>>> Matrix([[1,0], [0,1]])
- ⎡1 0⎤
- ⎣0 1⎦
+ [1 0]
+ [ ]
+ [0 1]

This is the standard manner one creates a matrix, i.e. with a list of
appropriately-sizes lists. SymPy also supports more advanced methods of matrix
creation including a single list of values and dimension inputs:

>>> Matrix(2, 3, [1, 2, 3, 4, 5, 6])
- ⎡1 2 3⎤
- ⎣4 5 6⎦
+ [1 2 3]
+ [ ]
+ [4 5 6]

More interestingly (and usefully), we can use a 2-variable function (or lambda)
to make one. Here we create an indicator function which is 1 on the diagonal
@@ -33,45 +35,50 @@ and then use it to make the identity matrix:
... return 0
...
>>> Matrix(4, 4, f)
- ⎡1 0 0 0⎤
- ⎢0 1 0 0⎥
- ⎢0 0 1 0⎥
- ⎣0 0 0 1⎦
+ [1 0 0 0]
+ [ ]
+ [0 1 0 0]
+ [ ]
+ [0 0 1 0]
+ [ ]
+ [0 0 0 1]

Finally let's use lambda to create a 1-line matrix with 1's in the even
permutation entries:

>>> Matrix(3, 4, lambda i,j: 1 - (i+j) % 2)
- ⎡1 0 1 0⎤
- ⎢0 1 0 1⎥
- ⎣1 0 1 0⎦
+ [1 0 1 0]
+ [ ]
+ [0 1 0 1]
+ [ ]
+ [1 0 1 0]

There are also a couple of special constructors for quick matrix construction -
``eye`` is the identity matrix, ``zeros`` and ``ones`` for matrices of all
zeros and ones, respectively:

>>> eye(4)
- ⎡1 0 0 0⎤
- ⎢ ⎥
- ⎢0 1 0 0⎥
- ⎢ ⎥
- ⎢0 0 1 0⎥
- ⎢ ⎥
- ⎣0 0 0 1⎦
+ [1 0 0 0]
+ [ ]
+ [0 1 0 0]
+ [ ]
+ [0 0 1 0]
+ [ ]
+ [0 0 0 1]
>>> zeros(2)
- ⎡0 0⎤
- ⎢ ⎥
- ⎣0 0⎦
+ [0 0]
+ [ ]
+ [0 0]
>>> zeros((2, 5))
- ⎡0 0 0 0 0⎤
- ⎢ ⎥
- ⎣0 0 0 0 0⎦
+ [0 0 0 0 0]
+ [ ]
+ [0 0 0 0 0]
>>> ones(3)
- ⎡1 1 1⎤
- ⎢ ⎥
- ⎢1 1 1⎥
- ⎢ ⎥
- ⎣1 1 1⎦
+ [1 1 1]
+ [ ]
+ [1 1 1]
+ [ ]
+ [1 1 1]
>>> ones((1, 3))
[1 1 1]

@@ -100,13 +107,15 @@ Now, the more standard entry access is a pair of indices:
Since this is Python we're also able to slice submatrices::

>>> M[0:2,0:2]
- ⎡1 2⎤
- ⎣4 5⎦
- >>> M[1:2,2:2]
-
+ [1 2]
+ [ ]
+ [4 5]
+ >>> M[1:2,2]
+ [6]
>>> M[:,2]
- ⎡3⎤
- ⎣6⎦
+ [3]
+ [ ]
+ [6]

Remember in the 2nd example above that slicing 2:2 gives an empty range and
that, as in python, a 4 column list is indexed from 0 to 3. In particular, this
@@ -115,70 +124,94 @@ mean a quick way to create a copy of the matrix is:
>>> M2 = M[:,:]
>>> M2[0,0] = 100
>>> M
- ⎡1 2 3⎤
- ⎣4 5 6⎦
+ [1 2 3]
+ [ ]
+ [4 5 6]

See? Changing M2 didn't change M. Since we can slice, we can also assign
entries:

>>> M = Matrix(([1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]))
>>> M
- ⎡ 1 2 3 4⎤
- ⎢ 5 6 7 8⎥
- ⎢ 9 10 11 12⎥
- ⎣13 14 15 16⎦
+ [1 2 3 4 ]
+ [ ]
+ [5 6 7 8 ]
+ [ ]
+ [9 10 11 12]
+ [ ]
+ [13 14 15 16]
>>> M[2,2] = M[0,3] = 0
>>> M
- ⎡ 1 2 3 0⎤
- ⎢ 5 6 7 8⎥
- ⎢ 9 10 0 12⎥
- ⎣13 14 15 16⎦
+ [1 2 3 0 ]
+ [ ]
+ [5 6 7 8 ]
+ [ ]
+ [9 10 0 12]
+ [ ]
+ [13 14 15 16]

as well as assign slices:

>>> M = Matrix(([1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]))
>>> M[2:,2:] = Matrix(2,2,lambda i,j: 0)
>>> M
- ⎡ 1 2 3 4⎤
- ⎢ 5 6 7 8⎥
- ⎢ 9 10 0 0⎥
- ⎣13 14 0 0⎦
+ [1 2 3 4]
+ [ ]
+ [5 6 7 8]
+ [ ]
+ [9 10 0 0]
+ [ ]
+ [13 14 0 0]

All the standard arithmetic operations are supported:

>>> M = Matrix(([1,2,3],[4,5,6],[7,8,9]))
>>> M - M
- ⎡0 0 0⎤
- ⎢0 0 0⎥
- ⎣0 0 0⎦
+ [0 0 0]
+ [ ]
+ [0 0 0]
+ [ ]
+ [0 0 0]
>>> M + M
- ⎡ 2 4 6⎤
- ⎢ 8 10 12⎥
- ⎣14 16 18⎦
+ [2 4 6 ]
+ [ ]
+ [8 10 12]
+ [ ]
+ [14 16 18]
>>> M * M
- ⎡ 30 36 42⎤
- ⎢ 66 81 96⎥
- ⎣102 126 150⎦
+ [30 36 42 ]
+ [ ]
+ [66 81 96 ]
+ [ ]
+ [102 126 150]
>>> M2 = Matrix(3,1,[1,5,0])
>>> M*M2
- ⎡11⎤
- ⎢29⎥
- ⎣47⎦
+ [11]
+ [ ]
+ [29]
+ [ ]
+ [47]
>>> M**2
- ⎡ 30 36 42⎤
- ⎢ 66 81 96⎥
- ⎣102 126 150⎦
+ [30 36 42 ]
+ [ ]
+ [66 81 96 ]
+ [ ]
+ [102 126 150]

As well as some useful vector operations:

>>> M.row_del(0)
+ None
>>> M
- ⎡4 5 6⎤
- ⎣7 8 9⎦
+ [4 5 6]
+ [ ]
+ [7 8 9]
>>> M.col_del(1)
+ None
>>> M
- ⎡4 6⎤
- ⎣7 9⎦
+ [4 6]
+ [ ]
+ [7 9]
>>> v1 = Matrix([1,2,3])
>>> v2 = Matrix([4,5,6])
>>> v3 = v1.cross(v2)
@@ -196,18 +229,26 @@ appropriate size:
>>> M1 = eye(3)
>>> M2 = zeros((3, 4))
>>> M1.row_join(M2)
- ⎡1 0 0 0 0 0 0⎤
- ⎢0 1 0 0 0 0 0⎥
- ⎣0 0 1 0 0 0 0⎦
+ [1 0 0 0 0 0 0]
+ [ ]
+ [0 1 0 0 0 0 0]
+ [ ]
+ [0 0 1 0 0 0 0]
>>> M3 = zeros((4, 3))
>>> M1.col_join(M3)
- ⎡1 0 0⎤
- ⎢0 1 0⎥
- ⎢0 0 1⎥
- ⎢0 0 0⎥
- ⎢0 0 0⎥
- ⎢0 0 0⎥
- ⎣0 0 0⎦
+ [1 0 0]
+ [ ]
+ [0 1 0]
+ [ ]
+ [0 0 1]
+ [ ]
+ [0 0 0]
+ [ ]
+ [0 0 0]
+ [ ]
+ [0 0 0]
+ [ ]
+ [0 0 0]


Operations on entries
@@ -217,39 +258,52 @@ We are not restricted to having multiplication between two matrices:

>>> M = eye(3)
>>> 2*M
- ⎡2 0 0⎤
- ⎢0 2 0⎥
- ⎣0 0 2⎦
+ [2 0 0]
+ [ ]
+ [0 2 0]
+ [ ]
+ [0 0 2]
>>> 3*M
- ⎡3 0 0⎤
- ⎢0 3 0⎥
- ⎣0 0 3⎦
+ [3 0 0]
+ [ ]
+ [0 3 0]
+ [ ]
+ [0 0 3]

but we can also apply functions to our matrix entries using applyfunc(). Here we'll declare a function that double any input number. Then we apply it to the 3x3 identity matrix:

>>> f = lambda x: 2*x
>>> eye(3).applyfunc(f)
- ⎡2 0 0⎤
- ⎢0 2 0⎥
- ⎣0 0 2⎦
+ [2 0 0]
+ [ ]
+ [0 2 0]
+ [ ]
+ [0 0 2]

One more useful matrix-wide entry application function is the substitution function. Let's declare a matrix with symbolic entries then substitute a value. Remember we can substitute anything - even another symbol!:

+ >>> from sympy import Symbol
>>> x = Symbol('x')
>>> M = eye(3) * x
>>> M
- ⎡x 0 0⎤
- ⎢0 x 0⎥
- ⎣0 0 x⎦
+ [x 0 0]
+ [ ]
+ [0 x 0]
+ [ ]
+ [0 0 x]
>>> M.subs(x, 4)
- ⎡4 0 0⎤
- ⎢0 4 0⎥
- ⎣0 0 4⎦
+ [4 0 0]
+ [ ]
+ [0 4 0]
+ [ ]
+ [0 0 4]
>>> y = Symbol('y')
>>> M.subs(x, y)
- ⎡y 0 0⎤
- ⎢0 y 0⎥
- ⎣0 0 y⎦
+ [y 0 0]
+ [ ]
+ [0 y 0]
+ [ ]
+ [0 0 y]


Linear algebra
@@ -273,53 +327,69 @@ and the inverse. In SymPy the inverse is computed by Gaussian elimination by
default but we can specify it be done by LU decomposition as well:

>>> M2.inv()
- ⎡1 0 0⎤
- ⎢0 1 0⎥
- ⎣0 0 1⎦
+ [1 0 0]
+ [ ]
+ [0 1 0]
+ [ ]
+ [0 0 1]
>>> M2.inv("LU")
- ⎡1 0 0⎤
- ⎢0 1 0⎥
- ⎣0 0 1⎦
+ [1 0 0]
+ [ ]
+ [0 1 0]
+ [ ]
+ [0 0 1]
>>> M.inv("LU")
- ⎡-3/14 1/14 1/2⎤
- ⎢-1/28 5/28 -1/4⎥
- ⎣ 3/7 -1/7 0⎦
+ [-3/14 1/14 1/2 ]
+ [ ]
+ [-1/28 5/28 -1/4]
+ [ ]
+ [ 3/7 -1/7 0 ]
>>> M * M.inv("LU")
- ⎡1 0 0⎤
- ⎢0 1 0⎥
- ⎣0 0 1⎦
+ [1 0 0]
+ [ ]
+ [0 1 0]
+ [ ]
+ [0 0 1]

We can perform a QR factorization which is handy for solving systems:

>>> A = Matrix([[1,1,1],[1,1,3],[2,3,4]])
>>> Q, R = A.QRdecomposition()
>>> Q
- ⎡ ⎤
- ⎢ ⎽⎽⎽ ⎥
- ⎢ ⎽⎽⎽⎽⎽ -╲╱ 3 ⎽⎽⎽⎽⎽⎥
- ⎢ ╲╱ 1/6 ────── -╲╱ 1/2 ⎥
- ⎢ 3 ⎥
- ⎢ ⎥
- ⎢ ⎽⎽⎽ ⎥
- ⎢ ⎽⎽⎽⎽⎽ -╲╱ 3 ⎽⎽⎽⎽⎽⎥
- ⎢ ╲╱ 1/6 ────── ╲╱ 1/2 ⎥
- ⎢ 3 ⎥
- ⎢ ⎥
- ⎢ ⎽⎽⎽ ⎥
- ⎢ ⎽⎽⎽⎽⎽ ╲╱ 3 ⎥
- ⎢2*╲╱ 1/6 ───── 0⎥
- ⎣ 3 ⎦
+ [ ___ ___ ___]
+ [\/ 6 -\/ 3 -\/ 2 ]
+ [----- ------ ------]
+ [ 6 3 2 ]
+ [ ]
+ [ ___ ___ ___ ]
+ [\/ 6 -\/ 3 \/ 2 ]
+ [----- ------ ----- ]
+ [ 6 3 2 ]
+ [ ]
+ [ ___ ___ ]
+ [\/ 6 \/ 3 ]
+ [----- ----- 0 ]
+ [ 3 3 ]
>>> R
- ⎡ ⎽⎽⎽ ⎽⎽⎽⎽⎽ ⎽⎽⎽⎽⎽⎤
- ⎢ ╲╱ 6 8*╲╱ 1/6 12*╲╱ 1/6 ⎥
- ⎢ ⎽⎽⎽⎽⎽ ⎥
- ⎢ 0 ╲╱ 1/3 0⎥
- ⎢ ⎽⎽⎽⎥
- ⎣ 0 0 ╲╱ 2 ⎦
+ [ ___ ]
+ [ ___ 4*\/ 6 ___]
+ [\/ 6 ------- 2*\/ 6 ]
+ [ 3 ]
+ [ ]
+ [ ___ ]
+ [ \/ 3 ]
+ [ 0 ----- 0 ]
+ [ 3 ]
+ [ ]
+ [ ___ ]
+ [ 0 0 \/ 2 ]
>>> Q*R
- ⎡1 1 1⎤
- ⎢1 1 3⎥
- ⎣2 3 4⎦
+ [1 1 1]
+ [ ]
+ [1 1 3]
+ [ ]
+ [2 3 4]
+

In addition to the solvers in the solver.py file, we can solve the system Ax=b
by passing the b vector to the matrix A's LUsolve function. Here we'll cheat a
@@ -331,9 +401,11 @@ that it's correct:
>>> b = A*x
>>> soln = A.LUsolve(b)
>>> soln
- ⎡3⎤
- ⎢7⎥
- ⎣5⎦
+ [3]
+ [ ]
+ [7]
+ [ ]
+ [5]

There's also a nice Gram-Schmidt orthogonalizer which will take a set of
vectors and orthogonalize then with respect to another another. There is an
@@ -360,7 +432,7 @@ Let's take a look at the vectors:
[-1551/706]
[ -423/706]
>>> for i in out2:
- ... print i
+ ... print i #doctest: +SKIP
...
[2*(1/38)**(1/2)]
[3*(1/38)**(1/2)]
diff --git a/doc/src/modules/polynomials.txt b/doc/src/modules/polynomials.txt
index 2ee25dc..30b2425 100644
--- a/doc/src/modules/polynomials.txt
+++ b/doc/src/modules/polynomials.txt
@@ -30,22 +30,25 @@ say, the rational numbers, q and r are uniquely defined this way.

>>> f = 5*x**2 + 10*x + 3
>>> g = 2*x + 2
- >>> q, r = div(f, g)
+ >>> q, r = div(f, g, x, y)
>>> q
- 5 + (5/2)*x
+ 5*x
+ 5/2 + ---
+ 2
>>> r
- 3
+ -2
>>> (q*g + r).expand()
- 13 + 5*x**2 + 15*x
+ 2
+ 3 + 10*x + 5*x

As you can see, q has a non-integer coefficient. If you want to do division
only in the ring of polynomials with integer coefficients you can specify an
additional parameter.

- >>> q, r = div(f, g, coeff='int')
- >>> q
+ >>> q, r = div(f, g, coeff='int') #doctest: +SKIP
+ >>> q #doctest: +SKIP
0
- >>> r
+ >>> r #doctest: +SKIP
13 + 5*x**2 + 15*x

But be warned, that this ring is no longer euclidean and that the degree of the
@@ -53,21 +56,23 @@ remainder doesn't need to be smaller than that of f. Since 2 doesn't divide 5,
2*x doesn't divide 5*x**2, even if the degree is smaller. But:

>>> g = 5*x + 1
- >>> q, r = div(f, g, coeff='int')
- >>> q
+ >>> q, r = div(f, g, x, coeff='int') #doctest: +SKIP
+ >>> q #doctest: +SKIP
x
- >>> r
+ >>> r #doctest: +SKIP
13 + 14*x
- >>> (q*g + r).expand()
+ >>> (q*g + r).expand() #doctest: +SKIP
13 + 5*x**2 + 15*x

This also works for polynomials with multiple variables.

>>> f = x*y + y*z
>>> g = 3*x + 3*z
- >>> q, r = div(f, g)
+ >>> q, r = div(f, g, x, y)
>>> q
- (1/3)*y
+ y
+ -
+ 3
>>> r
0

@@ -78,11 +83,15 @@ coefficient, you can specify the variables explicitly:
>>> a, b, c = symbols('abc')
>>> f = a*x**2 + b*x + c
>>> g = 3*x + 2
- >>> q, r = div(f, g, var=[x])
+ >>> q, r = div(f, g, x)
>>> q
- -2/9*a + (1/3)*b + (1/3)*a*x
+ 2*a b a*x
+ - --- + - + ---
+ 9 3 3
>>> r
- c - 2/3*b + (4/9)*a
+ 2*b 4*a
+ c - --- + ---
+ 3 9

Another option is division by multiple polynomials at the same time. In
general, the output is not unique and depends on the order of the divisors and
@@ -92,19 +101,27 @@ the given monomial order (if specified).
>>> f = x*y + y*z + z*x
>>> g1 = x + 1
>>> g2 = 2*y + 1
- >>> q, r = div(f, [g1, g2])
+ >>> q, r = div(f, [g1, g2], x, y, z)
>>> q
- [y + z, (-1/2) + (1/2)*z]
+ z
+ [y + z, -1/2 + -]
+ 2
>>> r
- 1/2 - 3/2*z
+ 3*z
+ 1/2 - ---
+ 2
>>> (q[0]*g1 + q[1]*g2 + r).expand()
x*y + x*z + y*z

- >>> q, r = div(f, [g2, g1])
+ >>> q, r = div(f, [g2, g1], x, y, z)
>>> q
- [(1/2)*x + (1/2)*z, (-1/2) + z]
+ x z
+ [- + -, -1/2 + z]
+ 2 2
>>> r
- 1/2 - 3/2*z
+ 3*z
+ 1/2 - ---
+ 2
>>> (q[0]*g2 + q[1]*g1 + r).expand()
x*y + x*z + y*z

@@ -119,7 +136,7 @@ considered.

>>> f = 12*(x + 1)*x
>>> g = 16*x**2
- >>> gcd(f, g)
+ >>> gcd(f, g, x)
4*x

It also works with multiple variables. In this case, the variables are ordered
@@ -127,37 +144,38 @@ alphabetically, be default, which has influence on the leading coefficient.

>>> f = x*y/2 + y**2
>>> g = 3*x + 6*y
- >>> gcd(f, g)
+ >>> gcd(f, g, x, y)
x + 2*y
- >>> gcd(f, g, var=[y, x])
- y + (1/2)*x
+ >>> gcd(f, g, y, x)
+ x
+ y + -
+ 2

The lcm is connected with the gcd and one can be computed using the other.

>>> f = x*y**2 + x**2*y
>>> g = x**2*y**2
- >>> gcd(f, g)
+ >>> gcd(f, g, x, y)
x*y
- >>> lcm(f, g)
- x**2*y**3 + x**3*y**2
+ >>> lcm(f, g, x, y)
+ 3 2 2 3
+ x *y + x *y
>>> (f*g).expand()
- x**3*y**4 + x**4*y**3
- >>> (gcd(f, g)*lcm(f, g)).expand()
- x**3*y**4 + x**4*y**3
+ 4 3 3 4
+ x *y + x *y
+ >>> (gcd(f, g, x, y)*lcm(f, g, x, y)).expand()
+ 4 3 3 4
+ x *y + x *y

Square-free factorization
~~~~~~~~~~~~~~~~~~~~~~~~~

-You can compute the square-free part of a univariate polynomial, which is the
-product of all the different irreducible divisors.
-
- >>> sqf_part(x**3*(x+1)**2)
- x + x**2
-
The square-free factorization of a univariate polynomial is the product of all factors (not irreducible) of degree 1, 2 ...

- >>> sqf((x + 2)*(x*(x + 1))**2)
- (x + x**2)**2*(2 + x)
+ >>> sqf((x + 2)*(x*(x + 1))**2, x)
+ 2
+ [2 + x, x + x ]
+

Factorization
~~~~~~~~~~~~~
@@ -167,10 +185,15 @@ with rational coefficients.
::

>>> factor(Rational(1,2)*x**4 + Rational(5,12)*x**3 - Rational(1,3)*x**2)
- -1/12*x**2*(1 - 2*x)*(4 + 3*x)
+ 2
+ -x *(1 - 2*x)*(4 + 3*x)
+ -----------------------
+ 12

>>> factor(x**2 + 4*x*y + 4*y**2)
- (x + 2*y)**2
+ 2
+ (x + 2*y)
+

Groebner bases
~~~~~~~~~~~~~~
@@ -178,11 +201,13 @@ Groebner bases
Buchberger's algorithm is implemented, supporting various monomial orders.
::

- >>> groebner([x**2 + 1, y**4*x + x**3], order='lex')
- [(-1) + y**4, 1 + x**2]
+ >>> groebner([x**2 + 1, y**4*x + x**3], x, y, order='lex')
+ 2 4
+ [1 + x , -1 + y ]

- >>> groebner([x**2 + 1, y**4*x + x**3, x*y*z**3], order='grevlex')
- [(-1) + y**4, z**3, 1 + x**2]
+ >>> groebner([x**2 + 1, y**4*x + x**3, x*y*z**3], x, y, z, order='grevlex')
+ 4 3 2
+ [-1 + y , z , 1 + x ]

Solving Equations
~~~~~~~~~~~~~~~~~
@@ -190,18 +215,33 @@ Solving Equations
We have (incomplete) methods to find the complex or even symbolic roots of
polynomials and to solve some systems of polynomial equations.
::
+ >>> from sympy import roots, solve_poly_system
+ >>> solve(x**3 + 2*x + 3, x)
+ ____ ____
+ I*\/ 11 I*\/ 11
+ [1/2 - --------, -1, 1/2 + --------]
+ 2 2
+

- >>> roots(x**3 + 2*x + 3)
- [-1, 1/2 + (1/2)*I*11**(1/2), 1/2 - 1/2*I*11**(1/2)]
+ >>> p = Symbol('p')
+ >>> q = Symbol('q')
+ >>> sorted(solve(x**2 + p*x + q, x))
+ ___________ ___________
+ / 2 / 2
+ p \/ -4*q + p p \/ -4*q + p
+ [- - + --------------, - - - --------------]
+ 2 2 2 2

- >>> roots(x**2 + p*x + q, var=[x])
- [(1/2)*(p**2 - 4*q)**(1/2) - 1/2*p, -1/2*p - 1/2*(p**2 - 4*q)**(1/2)]

- >>> solve_system([y - x, x - 5])
+ >>> solve_poly_system([y - x, x - 5], x, y)
[(5, 5)]

- >>> solve_system([y**2 - x**3 + 1, y*x])
- [(0, I), (0, -I), (1, 0), ((-1/2) + (1/2)*I*3**(1/2), 0), ((-1/2) - 1/2*I*3**(1/2), 0)]
+ >>> solve_poly_system([y**2 - x**3 + 1, y*x], x, y)
+ ___ ___
+ I*\/ 3 I*\/ 3
+ [(0, I), (0, -I), (1, 0), (-1/2 + -------, 0), (-1/2 - -------, 0)]
+ 2 2
+

The Poly and Polynomial class
-----------------------------
diff --git a/doc/src/modules/rewriting.txt b/doc/src/modules/rewriting.txt
index d3a5a86..a2071fc 100644
--- a/doc/src/modules/rewriting.txt
+++ b/doc/src/modules/rewriting.txt
@@ -18,11 +18,15 @@ of more general functions is possible. Below are listed all currently available
expand rules.

Expanding of arithmetic expressions involving products and powers:
+ >>> from sympy import *
+ >>> x, y, z = symbols('xyz')
>>> ((x + y)*(x - y)).expand(basic=True)
- x**2 - y**2
-
+ 2 2
+ x - y
>>> ((x + y + z)**2).expand(basic=True)
- x**2 + y**2 + z**2 + 2*x*y + 2*x*z + 2*y*z
+ 2 2 2
+ 2*x*y + 2*x*z + 2*y*z + x + y + z
+

Arithmetic expand is done by default in `expand()` so the keyword `basic` can
be omitted. However you can set `basic=False` to avoid this type of expand if
@@ -33,10 +37,10 @@ Another type of expand rule is expanding complex valued expressions and putting
them into a normal form. For this `complex` keyword is used. Note that it will
always perform arithmetic expand to obtain the desired normal form:

- >>> (x + I*y).expand(complex=True)
+ >>> (x + I*y).expand(complex=True) #doctest: +SKIP
-im(y) + I*re(y) + I*im(x) + re(x)

- >>> sin(x + I*y).expand(complex=True)
+ >>> sin(x + I*y).expand(complex=True) #doctest: +SKIP
sin(-im(y) + re(x))*cosh(re(y) + im(x)) + I*cos(-im(y) + re(x))*sinh(re(y) + im(x))

Note also that the same behavior can be obtained by using `as_real_imag()`
@@ -45,9 +49,9 @@ place and the imaginary part in the other. This can be also done in a two step
process by using `collect` function:

>>> (x + I*y).as_real_imag()
- (-im(y) + re(x), re(y) + im(x))
+ (-im(y) + re(x), im(x) + re(y))

- >>> collect((x + I*y).expand(complex=True), I, evaluate=False)
+ >>> collect((x + I*y).expand(complex=True), I, evaluate=False) #doctest: +SKIP
{I: re(y) + im(x), 1: -im(y) + re(x)}

There is also possibility for expanding expressions in terms of expressions of
diff --git a/doc/src/modules/series.txt b/doc/src/modules/series.txt
index 9b194b5..2502972 100644
--- a/doc/src/modules/series.txt
+++ b/doc/src/modules/series.txt
@@ -9,16 +9,16 @@ series(x*cos(x),x), which is possibly more intuative than (x*cos(x)).series(x).

Examples
--------
- >>> from sympy import cos, series
- >>> from sympy.series import series
+ >>> from sympy import Symbol, cos, series
+ >>> x = Symbol('x')
>>> series(cos(x),x)
- 1 - x**2/2 + x**4/24 + O(x**6)
+ 2 4
+ x x
+ 1 - -- + -- + O(x**6)
+ 2 24
+

TODO and Bugs
-------------
-The series expansion about a point other than x=0 does not work:
- >>> series(cos(x),x,10)
- 1 - x**2/2 + x**4/24 + O(x**6)
-
-This is a bug in Basic.series() (issue 1334). When fixed there, the bug will
+The series expansion about a point other than x=0 does not work. This is a bug in Basic.series() (issue 1334). When fixed there, the bug will
also be automatically fixed here.
diff --git a/doc/src/modules/solvers.txt b/doc/src/modules/solvers.txt
index 308def3..4b04023 100644
--- a/doc/src/modules/solvers.txt
+++ b/doc/src/modules/solvers.txt
@@ -13,9 +13,10 @@ Use solve() to solve algebraic equations. We suppose all equations are equaled t
so solving x**2 == 1 translates into the following code::

>>> from sympy.solvers import solve
+ >>> from sympy import Symbol
>>> x = Symbol('x')
>>> solve( x**2 - 1, x )
- [-1, 1]
+ [1, -1]

The first argument for solve() is an equation (equaled to zero) and the second argument
is the symbol that we want to solve the equation for.
diff --git a/doc/src/modules/statistics.txt b/doc/src/modules/statistics.txt
index daf069d..4b1cc9d 100644
--- a/doc/src/modules/statistics.txt
+++ b/doc/src/modules/statistics.txt
@@ -6,7 +6,8 @@ Statistics
The *statistics* module in SymPy implements standard probability distributions
and related tools. Its contents can be imported with the following statement::

- from sympy.statistics import *
+ >>> from sympy import *
+ >>> from sympy.statistics import *

Normal distributions
--------------------
@@ -30,13 +31,13 @@ You can generate random numbers from the desired distribution with the
``random`` method:

>>> N = Normal(10, 5)
- >>> N.random()
+ >>> N.random() #doctest: +SKIP
4.914375200829805834246144514
- >>> N.random()
+ >>> N.random() #doctest: +SKIP
11.84331557474637897087177407
- >>> N.random()
+ >>> N.random() #doctest: +SKIP
17.22474580071733640806996846
- >>> N.random()
+ >>> N.random() #doctest: +SKIP
9.864643097429464546621602494

The probability density function (pdf) and cumulative distribution function
@@ -46,11 +47,20 @@ particular values:
>>> N = Normal(1, 1)
>>> x = Symbol('x')
>>> N.pdf(1)
- (1/2)**(1/2)*pi**(-1/2)
+ ___
+ \/ 2
+ --------
+ ____
+ 2*\/ pi
>>> N.pdf(3).evalf()
- 0.05399096651318805195056420043
+ 0.0539909665131881
>>> N.cdf(x)
- 1/2 - 1/2*erf((1/2)**(1/2)*(1 - x))
+ / ___ \
+ |\/ 2 *(1 - x)|
+ erf|-------------|
+ \ 2 /
+ 1/2 - ------------------
+ 2
>>> N.cdf(-oo), N.cdf(1), N.cdf(oo)
(0, 1/2, 1)
>>> N.cdf(5).evalf()
@@ -63,9 +73,12 @@ convenient alternative syntax for cdf(b)-cdf(a)):
>>> N.probability(-oo, 0)
1/2
>>> N.probability(-1, 1)
- (1/2)*erf(2*(1/2)**(1/2))
- >>> _.evalf()
- 0.477249868051821
+ / ___\
+ |\/ 2 |
+ erf|-----|
+ \ 2 /
+ >>> N.probability(-1, 1).evalf()
+ 0.682689492137086

You can also generate a symmetric confidence interval from a given desired
confidence level (given as a fraction 0-1). For the normal distribution, 68%,
@@ -78,11 +91,11 @@ and 3 standard deviations:
>>> N.confidence(0.95)
(-1.95996398454005, 1.95996398454005)
>>> N.confidence(0.997)
- (-2.96773792534179, 2.96773792534179)
+ (-2.96773792534178, 2.96773792534178)

Plug the interval back in to see that the value is correct:

- >>> N.probability(*N.confidence(0.95)).evalf()
+ >>> N.probability(*N.confidence(0.95)).evalf() #doctest: +SKIP
0.95

Other distributions
diff --git a/doc/src/tutorial.txt b/doc/src/tutorial.txt
index c2a370f..55b2526 100644
--- a/doc/src/tutorial.txt
+++ b/doc/src/tutorial.txt
@@ -41,15 +41,15 @@ and try it from a Python intepreter:

.. parsed-literal::

- $ :input:`cd sympy-0.5.12`
- $ :input:`python`
+ $ cd sympy-0.5.12
+ $ python
Python 2.4.4 (#2, Jan 3 2008, 13:36:28)
[GCC 4.2.3 20071123 (prerelease) (Debian 4.2.2-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
- >>> :input:`from sympy import Symbol, cos`
- >>> :input:`x = Symbol("x")`
- >>> :input:`(1/cos(x)).series(x, 0, 10)`
- 1 + (1/2)*x**2 + (5/24)*x**4 + (61/720)*x**6 + (277/8064)*x**8 + O(x**10)
+ >>> from sympy import Symbol, cos
+ >>> x = Symbol("x")
+ >>> (1/cos(x)).series(x, 0, 10)
+ 1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)

You can use SymPy as shown above and this is indeed the recommended way if you
use it in your program. You can also install it using ``./setup.py install`` as
@@ -167,10 +167,10 @@ have arbitrary precission::
pi**2

>>> pi.evalf()
- 3.141592653589793238462643383
+ 3.14159265358979

>>> (pi+exp(1)).evalf()
- 5.859874482049203234066343309
+ 5.85987448204884

as you see, evalf evaluates the expression to a floating-point number

@@ -197,15 +197,15 @@ Then you can play with them::
2*x

>>> (x+y)**2
- (x+y)**2
+ (x + y)**2

>>> ((x+y)**2).expand()
- 2*x*y+x**2+y**2
+ 2*x*y + x**2 + y**2

And substitute them for other symbols or numbers using ``subs(old, new)``::

>>> ((x+y)**2).subs(x, 1)
- (1+y)**2
+ (1 + y)**2

>>> ((x+y)**2).subs(x, y)
4*y**2
@@ -309,12 +309,12 @@ You can differentiate any SymPy expression using ``diff(func, var)``. Examples::
2*cos(2*x)

>>> diff(tan(x), x)
- cos(x)**(-2)
+ 1 + tan(x)**2

You can check, that it is correct by::

>>> limit((tan(x+y)-tan(x))/y, y, 0)
- cos(x)**(-2)
+ 1 + tan(x)**2

Higher derivatives can be calculated using the ``diff(func, var, n)`` method::

@@ -340,9 +340,9 @@ Use ``.series(var, point, order)``::
>>> from sympy import *
>>> x = Symbol('x')
>>> cos(x).series(x, 0, 10)
- 1 - 1/2*x**2 + (1/24)*x**4 - 1/720*x**6 + (1/40320)*x**8 + O(x**10)
+ 1 - x**2/2 + x**4/24 - x**6/720 + x**8/40320 + O(x**10)
>>> (1/cos(x)).series(x, 0, 10)
- 1 + (1/2)*x**2 + (5/24)*x**4 + (61/720)*x**6 + (277/8064)*x**8 + O(x**10)
+ 1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)

Another simple example::

@@ -385,14 +385,14 @@ You can integrate elementary functions::
x**6
>>> integrate(sin(x), x)
-cos(x)
- >>> integrate(log(x), x)
+ >>> integrate(log(x), x) #doctest: +SKIP
x*log(x) - x
- >>> integrate(2*x + sinh(x), x)
+ >>> integrate(2*x + sinh(x), x) #doctest: +SKIP
x**2 + cosh(x)

Also special functions are handled easily::

- >>> integrate(exp(-x**2)*erf(x), x)
+ >>> integrate(exp(-x**2)*erf(x), x) #doctest: +SKIP
(1/4)*pi**(1/2)*erf(x)**2

It is possible to compute definite integral::
@@ -425,7 +425,7 @@ Complex numbers
>>> exp(I*x).expand()
exp(I*x)
>>> exp(I*x).expand(complex=True)
- 1/exp(im(x))*cos(re(x)) + I/exp(im(x))*sin(re(x))
+ I*exp(-im(x))*sin(re(x)) + cos(re(x))*exp(-im(x))
>>> x = Symbol("x", real=True)
>>> exp(I*x).expand(complex=True)
I*sin(x) + cos(x)
@@ -648,24 +648,21 @@ Matrices are created as instances from the Matrix class::

>>> from sympy import Matrix
>>> Matrix([[1,0], [0,1]])
- [1 0]
- [0 1]
+ [1, 0]
+ [0, 1]

you can also put Symbols in it::

>>> x = Symbol('x')
>>> y = Symbol('y')
>>> A = Matrix([[1,x], [y,1]])
- >>> A #doctest: +NORMALIZE_WHITESPACE
- [1 x]
- [y 1]
-
- >>> A**2 #doctest: +NORMALIZE_WHITESPACE
- [1+x*y 2*x]
- [2*y 1+x*y]
+ >>> A
+ [1, x]
+ [y, 1]

- >>> 1
- 1
+ >>> A**2
+ [1 + x*y, 2*x]
+ [ 2*y, 1 + x*y]

For more information an examples with Matrices, see the LinearAlgebraTutorial.

@@ -681,10 +678,10 @@ substitutions, as follows::
>>> from sympy import *
>>> x = Symbol('x')
>>> p = Wild('p')
- >>> q = Wild('q')
- >>> (5*x**2 + 3*x).match(p*x**2 + q*x)
- {p_: 5, q_: 3}
+ >>> (5*x**2).match(p*x**2)
+ {p_: 5}

+ >>> q = Wild('q')
>>> (x**2).match(p*x**q)
{p_: 1, q_: 2}

@@ -693,18 +690,6 @@ If the match is unsuccessful, it returns ``None``::
>>> print (x+1).match(p**x)
None

-One can also make use of the `WildFunction` class to perform
-more specific matches with functions and their arguments::
-
- >>> f = WildFunction('f', nofargs=1)
- >>> (5*cos(x)).match(p*f)
- {p_: 5, f_: cos(x)}
- >>> (cos(3*x)).match(f(p*x))
- {p_: 3, f_: cos}
- >>> g = WildFunction('g', nofargs=2)
- >>> (5*cos(x)).match(p*g)
- None
-
One can also use the exclude parameter of the ``Wild`` class to ensure that
certain things do not show up in the result::

@@ -745,19 +730,21 @@ This is a nice ascii-art printing produced by a ``pprint`` function:

>>> from sympy import Integral, pprint
>>> from sympy.abc import x
- >>> pprint(x**2)
+ >>> pprint(x**2) #doctest: +NORMALIZE_WHITESPACE
2
x
>>> pprint(1/x)
1
- ─
+ -
x
>>> pprint(Integral(x**2, x))
- ⌠
- ⎮ 2
- ⎮ x dx
- ⌡
- >>>
+ /
+ |
+ | 2
+ | x dx
+ |
+ /
+

See also the wiki `Pretty Printing
<http://wiki.sympy.org/wiki/Pretty_Printing>`_ for more examples of a nice
@@ -777,80 +764,62 @@ Tip: To make the pretty printing default in the python interpreter, use::
>>> x**3/3
3
x
- ──
+ --
3
- >>> Integral(x**2, x)
- ⌠
- ⎮ 2
- ⎮ x dx
- ⌡
-
+ >>> Integral(x**2, x) #doctest: +NORMALIZE_WHITESPACE
+ /
+ |
+ | 2
+ | x dx
+ |
+ /


**Python printing**

- >>> from sympy.printing.python import print_python
+ >>> from sympy.printing.python import python
>>> from sympy import Integral
>>> from sympy.abc import x
- >>> print_python(x**2)
+ >>> print python(x**2)
x = Symbol('x')
e = x**2
- >>> print_python(1/x)
+ >>> print python(1/x)
x = Symbol('x')
e = 1/x
- >>> print_python(Integral(x**2, x))
+ >>> print python(Integral(x**2, x))
x = Symbol('x')
e = Integral(x**2, x)
- >>>
+

**LaTeX printing**

>>> from sympy import Integral, latex
>>> from sympy.abc import x
>>> latex(x**2)
- '${x}^{2}$'
+ $x^{2}$
>>> latex(1/x)
- '${x}^{-1}$'
+ $\frac{1}{x}$
>>> latex(Integral(x**2, x))
- '$\\int {x}^{2}\\,dx$'
+ $\int x^{2}\,dx$
>>>

**MathML**

::

- >>> from sympy.printing.mathml import print_mathml
+ >>> from sympy.printing.mathml import mathml
>>> from sympy import Integral, latex
>>> from sympy.abc import x
- >>> print_mathml(x**2)
- <apply>
- <power/>
- <ci>
- x
- </ci>
- <cn>
- 2
- </cn>
- </apply>
-
- >>> print_mathml(1/x)
- <apply>
- <power/>
- <ci>
- x
- </ci>
- <cn>
- -1
- </cn>
- </apply>
-
- >>>
+ >>> print mathml(x**2)
+ <apply><power/><ci>x</ci><cn>2</cn></apply>
+ >>> print mathml(1/x)
+ <apply><power/><ci>x</ci><cn>-1</cn></apply>

**Pyglet**

>>> from sympy import Integral, pngview
>>> from sympy.abc import x
- >>> pngview(Integral(x**2, x))
+ >>> pngview(Integral(x**2, x)) #doctest:+SKIP

And a pyglet window with the LaTeX rendered expression will popup:

diff --git a/sympy/utilities/runtests.py b/sympy/utilities/runtests.py
index cd514e2..4fa6ecf 100644
--- a/sympy/utilities/runtests.py
+++ b/sympy/utilities/runtests.py
@@ -109,7 +109,18 @@ def doctest(*paths, **kwargs):
t.add_paths(paths)
else:
t.add_paths(["sympy"])
- return t.test()
+ dtest = t.test()
+
+ # test documentation under doc/src/
+ import doctest
+ excluded = ['doc/src/modules/plotting.txt']
+ doc_files = glob('doc/src/*.txt') + glob('doc/src/modules/*.txt')
+ for ex in excluded:
+ doc_files.remove(ex)
+ for doc_file in doc_files:
+ print "Testing ", doc_file
+ print "Failed %s, tested %s" % doctest.testfile(doc_file, module_relative=False)
+ return dtest


class SymPyTests(object):
--
1.6.2.2

Vinzent Steinberg

unread,
Jun 15, 2009, 6:17:16 PM6/15/09
to sympy-...@googlegroups.com
Thank you for this massive amount of work, this was really needed!

git am can't apply the patch for me:

Applying: Test also documentation under doc/
/home/one/src/sympy/git/.git/rebase-apply/patch:61: trailing whitespace.

    2 + 6*n + 4*n
/home/one/src/sympy/git/.git/rebase-apply/patch:385: trailing whitespace.
    0.333333333333333*x + 3.14159265358979*x
/home/one/src/sympy/git/.git/rebase-apply/patch:401: trailing whitespace.
    ...
/home/one/src/sympy/git/.git/rebase-apply/patch:478: trailing whitespace.
    >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), strict=True)
/home/one/src/sympy/git/.git/rebase-apply/patch:481: trailing whitespace.

    PrecisionExhausted: Failed to distinguish the expression:
error: patch failed: doc/src/modules/evalf.txt:1
error: doc/src/modules/evalf.txt: patch does not apply
Patch failed at 0002 Test also documentation under doc/
When you have resolved this problem run "git am -i --resolved".
If you would prefer to skip this patch, instead run "git am -i --skip".
To restore the original branch and stop patching run "git am -i --abort".

I'll try to pull from you branch.

Vinzent

Vinzent Steinberg

unread,
Jun 15, 2009, 6:36:27 PM6/15/09
to sympy-...@googlegroups.com
2009/6/16 Vinzent Steinberg <vinzent....@googlemail.com>


I'll try to pull from you branch.

Well, I could not find it. You are using another repository than http://fseoane.net/cgi-bin/gitweb.cgi?p=sympy.git;a=summary ?

Vinzent

Fabian Pedregosa

unread,
Jun 16, 2009, 8:19:54 AM6/16/09
to sympy-...@googlegroups.com
yes, there are some issues with the file doc/src/modules/evalf.txt,
because it used windows-style line end. What platform are you on?

I've uploaded my branch, so

git pull http://fseoane.net/git/sympy.git doc

should now work

Thanks.

>
> Vinzent
>
>
> >


--
http://fseoane.net/blog/

Vinzent Steinberg

unread,
Jun 16, 2009, 8:44:07 AM6/16/09
to sympy-...@googlegroups.com
2009/6/16 Fabian Pedregosa <fab...@fseoane.net>


Vinzent Steinberg wrote:
> Thank you for this massive amount of work, this was really needed!
>
> git am can't apply the patch for me:
>
> Applying: Test also documentation under doc/
> /home/one/src/sympy/git/.git/rebase-apply/patch:61: trailing whitespace.
>     2 + 6*n + 4*n
> /home/one/src/sympy/git/.git/rebase-apply/patch:385: trailing whitespace.
>     0.333333333333333*x + 3.14159265358979*x
> /home/one/src/sympy/git/.git/rebase-apply/patch:401: trailing whitespace.
>     ...
> /home/one/src/sympy/git/.git/rebase-apply/patch:478: trailing whitespace.
>     >>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), strict=True)
> /home/one/src/sympy/git/.git/rebase-apply/patch:481: trailing whitespace.
>     PrecisionExhausted: Failed to distinguish the expression:
> error: patch failed: doc/src/modules/evalf.txt:1
> error: doc/src/modules/evalf.txt: patch does not apply
> Patch failed at 0002 Test also documentation under doc/
> When you have resolved this problem run "git am -i --resolved".
> If you would prefer to skip this patch, instead run "git am -i --skip".
> To restore the original branch and stop patching run "git am -i --abort".
>
> I'll try to pull from you branch.

yes, there are some issues with the file doc/src/modules/evalf.txt,
because it used windows-style line end. What platform are you on?

Was on Linux. Doesn't our code-quality tests test for line ends? Maybe not the docs?
 


I've uploaded my branch, so

git pull http://fseoane.net/git/sympy.git doc

should now work

Thanks.

Thank you, I'll try it out.

Vinzent

Ondrej Certik

unread,
Jun 16, 2009, 12:16:32 PM6/16/09
to sympy-...@googlegroups.com, Priit Laes

Looks good to me. After Vinzent approves, lets get it in.

Fabian, could you please also review this from Priit?

http://github.com/plaes/sympy/tree/doc-fixes

Thanks,
Ondrej

Vinzent Steinberg

unread,
Jun 16, 2009, 6:51:53 PM6/16/09
to sympy-...@googlegroups.com
Only a few minor comments:

2009/6/15 Fabian Pedregosa <fab...@fseoane.net>
 Why not -oo?

Why skip? It's currently broken?
 


Looks great and all tests pass.

Vinzent

Fabian Pedregosa

unread,
Jun 17, 2009, 9:05:28 AM6/17/09
to sympy-...@googlegroups.com, Ondrej Certik
Thanks for your comments. I deleted the +SKIP from those tests, since
there were no reason to skip them.

I pushed this in ... watching that the buildbots ... however it is
failing the tests under python2.4 because docutils on that version does
not recognize the option +SKIP.

I'll take a look on the weekend on this because I've got exams tomorrow
and the day after, but feel free to revert the patch if you find the
failures of the buildbot annoying

Vinzent Steinberg wrote:
> Only a few minor comments:
>
> 2009/6/15 Fabian Pedregosa <fab...@fseoane.net <mailto:fab...@fseoane.net>>
> <http://sympy.functions.elementary.re>
--
http://fseoane.net/blog/

Vinzent Steinberg

unread,
Jun 17, 2009, 9:23:17 AM6/17/09
to sympy-...@googlegroups.com
2009/6/17 Fabian Pedregosa <fab...@fseoane.net>

Thanks for your comments. I deleted the +SKIP from those tests, since
there were no reason to skip them.

I pushed this in ... watching that the buildbots ... however it is
failing the tests under python2.4 because docutils on that version does
not recognize the option +SKIP.

I'll take a look on the weekend on this because I've got exams tomorrow
and the day after,

Good luck and much success!
 
but feel free to revert the patch if you find the
failures of the buildbot annoying

To be honest, I don't care much about doctests failing on Python 2.4.

Vinzent
 

Ondrej Certik

unread,
Jun 17, 2009, 1:25:35 PM6/17/09
to sympy-...@googlegroups.com

I do! As long as we officially support python2.4 and we still do, it
needs to run. I think doctests allow to implement our own directives,
so we just backport SKIP from python2.5.

This will be useful to learn anyway, because it'd be cool to add new
directrives like FLOATINGPOINT, where it would test the first 6 digits
only (for example), or INT, and it would take both 134 and 134L as the
same number, etc.

Ondrej

Fabian Pedregosa

unread,
Jun 17, 2009, 6:40:27 PM6/17/09
to sympy-...@googlegroups.com
Ondrej Certik wrote:
> On Wed, Jun 17, 2009 at 7:23 AM, Vinzent
> Steinberg<vinzent....@googlemail.com> wrote:
>> 2009/6/17 Fabian Pedregosa <fab...@fseoane.net>
>>> Thanks for your comments. I deleted the +SKIP from those tests, since
>>> there were no reason to skip them.
>>>
>>> I pushed this in ... watching that the buildbots ... however it is
>>> failing the tests under python2.4 because docutils on that version does
>>> not recognize the option +SKIP.
>>>
>>> I'll take a look on the weekend on this because I've got exams tomorrow
>>> and the day after,
>> Good luck and much success!
>>
>>> but feel free to revert the patch if you find the
>>> failures of the buildbot annoying
>> To be honest, I don't care much about doctests failing on Python 2.4.
>
> I do! As long as we officially support python2.4 and we still do, it
> needs to run. I think doctests allow to implement our own directives,
> so we just backport SKIP from python2.5.
>

register the directive is pretty easy:

diff --git a/sympy/utilities/runtests.py b/sympy/utilities/runtests.py
index d772e96..040e0ba 100644
--- a/sympy/utilities/runtests.py
+++ b/sympy/utilities/runtests.py
@@ -113,6 +113,8 @@ def doctest(*paths, **kwargs):

# test documentation under doc/src/
import doctest
+ # If we're using py24, then ignore the +SKIP directive.
+ if sys.version_info[:2] < (2,5): doctest.register_optionflag('SKIP')
excluded = ['doc/src/modules/plotting.txt']
doc_files = glob('doc/src/*.txt') + glob('doc/src/modules/*.txt')
for ex in excluded:


However, you still have to implement the flag by subclassing doctest
(horrors). From the docs:

"""
... this isn’t useful unless you intend to extend doctest internals via
subclassing:

""""
http://docs.python.org/library/doctest.html

...

> This will be useful to learn anyway, because it'd be cool to add new
> directrives like FLOATINGPOINT, where it would test the first 6 digits
> only (for example), or INT, and it would take both 134 and 134L as the
> same number, etc.
>
> Ondrej
>
> >
>


--
http://fseoane.net/blog/

Ondrej Certik

unread,
Jun 17, 2009, 6:56:45 PM6/17/09
to sympy-...@googlegroups.com

No, it's easy. This patch fixes it:

diff --git a/Lib/doctest.py b/Lib/doctest.py
index e4348b5..6804805 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1229,6 +1229,10 @@ class DocTestRunner:
else:
self.optionflags &= ~optionflag

+ # If 'SKIP' is set, then skip this example.
+ if self.optionflags & SKIP:
+ continue
+
# Record that we started this example.
tries += 1
if not quiet:


It's in the DocTestRunner.__run() class. Now the question is how to
best incorporate it in, e.g. if we should just copy that method
verbatim, override it in our own DocTestRunner class and add the two
lines in.

I also copied the __run() method from python2.6 to python2.4 to see
the differences and fortunately the only patch is this:


From 94da4b95f5bb48155210cbb97349ac3b50dfc390 Mon Sep 17 00:00:00 2001
From: Ondrej Certik <ond...@certik.cz>
Date: Wed, 17 Jun 2009 16:55:00 -0600
Subject: [PATCH] python2.6 difference

---
Lib/doctest.py | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/Lib/doctest.py b/Lib/doctest.py
index e4348b5..6fb1927 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1229,6 +1229,10 @@ class DocTestRunner:
else:
self.optionflags &= ~optionflag

+ # If 'SKIP' is set, then skip this example.
+ if self.optionflags & SKIP:
+ continue
+
# Record that we started this example.
tries += 1
if not quiet:
@@ -1309,7 +1313,7 @@ class DocTestRunner:

# Record and return the number of failures and tries.
self.__record_outcome(test, failures, tries)
- return failures, tries
+ return TestResults(failures, tries)

def __record_outcome(self, test, f, t):
"""
--
1.6.0.4

So as you can see, all we have to do is to register SKIP, copy the
__run() method from python2.6 and then at the end test if we are in
python2.4 and if so, "return failures, tries", otherwise "return
TestResults(failures, tries)".

Ondrej

Fabian Pedregosa

unread,
Jun 18, 2009, 8:50:54 AM6/18/09
to sympy-...@googlegroups.com
Ondrej Certik wrote:
> On Wed, Jun 17, 2009 at 4:40 PM, Fabian Pedregosa<fab...@fseoane.net> wrote:
>> Ondrej Certik wrote:
>>> On Wed, Jun 17, 2009 at 7:23 AM, Vinzent
>>> Steinberg<vinzent....@googlemail.com> wrote:
>>>> 2009/6/17 Fabian Pedregosa <fab...@fseoane.net>
>>>>> Thanks for your comments. I deleted the +SKIP from those tests, since
>>>>> there were no reason to skip them.
>>>>>
>>>>> I pushed this in ... watching that the buildbots ... however it is
>>>>> failing the tests under python2.4 because docutils on that version does
>>>>> not recognize the option +SKIP.
>>>>>

attached patch fixes it by inheriting from DocTestRunner and overriding
the __run method with the one present in python2.5


--
http://fseoane.net/blog/

0001-Fix-testing-the-rst-docs-under-python2.4.patch

Ondrej Certik

unread,
Jun 18, 2009, 9:17:04 AM6/18/09
to sympy-...@googlegroups.com
On Thu, Jun 18, 2009 at 6:50 AM, Fabian Pedregosa<fab...@fseoane.net> wrote:
> Ondrej Certik wrote:
>> On Wed, Jun 17, 2009 at 4:40 PM, Fabian Pedregosa<fab...@fseoane.net> wrote:
>>> Ondrej Certik wrote:
>>>> On Wed, Jun 17, 2009 at 7:23 AM, Vinzent
>>>> Steinberg<vinzent....@googlemail.com> wrote:
>>>>> 2009/6/17 Fabian Pedregosa <fab...@fseoane.net>
>>>>>> Thanks for your comments. I deleted the +SKIP from those tests, since
>>>>>> there were no reason to skip them.
>>>>>>
>>>>>> I pushed this in ... watching that the buildbots ... however it is
>>>>>> failing the tests under python2.4 because docutils on that version does
>>>>>> not recognize the option +SKIP.
>>>>>>
>
> attached patch fixes it by inheriting from DocTestRunner and overriding
> the __run method with the one present in python2.5

Sounds good, push it in.


Ondrej

Reply all
Reply to author
Forward
0 new messages