Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote branch 'upstream/master'

  • Loading branch information...
commit d3760495568408a334e4ff81619cbca7faa3ec3e 2 parents 2a08d8d + 5614a67
@alxspopov authored
View
6 .mailmap
@@ -79,3 +79,9 @@ Luke Peterson <hazelnusse@gmail.com> Dale Lukas Peterson
Davy Mao <e_equals_mass_speed_light_squared@hotmail.com> icedtrees <e_equals_mass_speed_light_squared@hotmail.com>
Kendhia <kendhia@gmail.com> ALGHeArT <algheart@live.fr>
Nathan Alison <nathan.f.alison@gmail.com> Nathan <nathan@ubuntu.(none)>
+Raoul Bourquin <raoulb@bluewin.ch> <raoulb@bluewin.chh>
+Sachin Irukula <sachin.irukula@gmail.com> sachin irukula <sachin.irukula@gmail.com>
+Siddhanathan Shanmugam <siddhanathan@gmail.com> Siddhu <siddhanathan@gmail.com>
+Siddhanathan Shanmugam <siddhanathan@gmail.com> Siddhu <siddhu@siddhu-laptop.(none)>
+Jim Zhang <Hyriodula@gmail.com> Neynt <Hyriodula@gmail.com>
+Jim Zhang <Hyriodula@gmail.com> Jim Zhang <hyriodula@gmail.com>
View
12 AUTHORS
@@ -1,8 +1,10 @@
-People with a * next to their names are not found in the metadata of the git history.
-
All people who contributed to SymPy by sending at least a patch or more (in
the order of the date of their first contribution), except those who
-explicitly didn't want to be mentioned:
+explicitly didn't want to be mentioned. You can find missing people from this
+file by using git log --reverse --format="%aN <%aE>" | awk ' !x[$0]++' (the
+order from that command will be a little different, but close to the order
+here). People with a * next to their names are not found in the metadata of
+the git history.
Ondřej Čertík <ondrej@certik.cz>
Fabian Pedregosa <fabian@fseoane.net>
@@ -190,9 +192,11 @@ Christian Bühler <christian@cbuehler.de>
Carsten Knoll <CarstenKnoll@gmx.de>
M R Bharath <catchmrbharath@gmail.com>
Matthias Toews <mat.toews@googlemail.com>
+Sergiu Ivanov <unlimitedscolobb@gmail.com>
Jorge E. Cardona <jorgeecardona@gmail.com>
Sanket Agarwal <sanket@sanketagarwal.com>
Manoj Babu K. <manoj.babu2378@gmail.com>
Sai Nikhil <tsnlegend@gmail.com>
Aleksandar Makelov <amakelov@college.harvard.edu>
-Sachin <sachin.irukula@gmail.com>
+Raphael Michel <webmaster@raphaelmichel.de>
+Sachin Irukula <sachin.irukula@gmail.com>
View
4 doc/src/aboutus.txt
@@ -197,12 +197,14 @@ want to be mentioned here, so see our repository history for a full list).
#. Carsten Knoll: improvement to preview()
#. M R Bharath: modified use of int_tested, improvement to Permutation
#. Matthias Toews: File permissions
+#. Sergiu Ivanov: Fixes to zoo
#. Jorge E. Cardona: Cleanup in polys
#. Sanket Agarwal: Rewrite coverage_doctest.py script
#. Manoj Babu K.: Improve gamma function
#. Sai Nikhil: Fix to Heavyside with complex arguments
#. Aleksandar Makelov: Fixes regarding the dihedral group generator
-#. Sachin: changes to allow Dict sorting
+#. Raphael Michel: German translation of the tutorial
+#. Sachin Irukula: Changes to allow Dict sorting
Up-to-date list in the order of the first contribution is given in the `AUTHORS
<https://github.com/sympy/sympy/blob/master/AUTHORS>`_ file.
View
2  sympy/__init__.py
@@ -68,7 +68,7 @@ def __sympy_debug():
#from physics import units
from plotting import Plot, textplot
from printing import pretty, pretty_print, pprint, pprint_use_unicode, \
- pprint_try_use_unicode, print_gtk, print_tree
+ pprint_try_use_unicode, print_gtk, print_tree, pager_print
from printing import ccode, fcode, latex, preview
from printing import python, print_python, srepr, sstr, sstrrepr
from interactive import init_session, init_printing
View
47 sympy/core/expr.py
@@ -451,35 +451,30 @@ def is_constant(self, *wrt, **flags):
if self.is_zero:
return True
- # try numerical evaluation in reals to see if we get two different
- # values
+ # try numerical evaluation to see if we get two different values
failing_number = None
if wrt == free:
- # try 0 and 1 via subsitution
+ # try 0 and 1
a = self.subs(zip(free, [0]*len(free)))
- if a.is_Rational:
+ if a is S.NaN:
+ a = self._random(None, 0, 0, 0, 0)
+ if a is not None and a is not S.NaN:
b = self.subs(zip(free, [1]*len(free)))
- if b.is_Rational:
- if a != b:
+ if b is S.NaN:
+ b = self._random(None, 1, 0, 1, 0)
+ if b is not None and b is not S.NaN:
+ if b.equals(a) is False:
return False
- # try 0 and 1 via evaluation
- a = self._random(None, 0, 0, 0, 0)
- if a is not None:
- b = self._random(None, 1, 0, 1, 0)
- if b is not None:
+ # try random real
+ b = self._random(None, -1, 0, 1, 0)
+ if b is not None and b is not S.NaN and b.equals(a) is False:
+ return False
+ # try random complex
+ b = self._random()
+ if b is not None and b is not S.NaN:
if a != b:
return False
- # try random real
- b = self._random(None, -1, 0, 1, 0)
- if b is not None:
- if a != b:
- return False
- # try random complex
- b = self._random()
- if b is not None:
- if a != b:
- return False
- failing_number = a if a.is_number else b
+ failing_number = a if a.is_number else b
# now we will test each wrt symbol (or all free symbols) to see if the
# expression depends on them or not using differentiation. This is
@@ -523,10 +518,16 @@ def equals(self, other, failing_expression=False):
# simplification steps that are done will be very fast.
diff = (self - other).as_content_primitive()[1]
diff = factor_terms(diff.simplify(), radical=True)
+
if not diff:
return True
- elif diff.is_Number or pure_complex(diff):
+
+ if all(f.is_Atom for m in Add.make_args(diff)
+ for f in Mul.make_args(m)):
+ # if there is no expanding to be done after simplifying
+ # then this can't be a zero
return False
+
constant = diff.is_constant(simplify=False, failing_number=True)
if constant is False or \
not diff.free_symbols and not diff.is_number:
View
10 sympy/core/tests/test_expr.py
@@ -1258,16 +1258,18 @@ def test_equals():
assert (3*meter**2).equals(0) is False
# from integrate(x*sqrt(1+2*x), x);
- # diff is zero, but differentiation does not show it
+ # diff is zero only when assumptions allow
i = 2*sqrt(2)*x**(S(5)/2)*(1 + 1/(2*x))**(S(5)/2)/5 + \
2*sqrt(2)*x**(S(3)/2)*(1 + 1/(2*x))**(S(5)/2)/(-6 - 3/x)
ans = sqrt(2*x + 1)*(6*x**2 + x - 1)/15
diff = i - ans
- assert diff.equals(0) is not False # should be True, but now it's None
- # XXX TODO add a force=True option to equals to posify both
- # self and other before beginning comparisions
+ assert diff.equals(0) is False
+ assert diff.subs(x, -S.Half/2) == 7*sqrt(2)/120
+ # there are regions for x for which the expression is True, for
+ # example, when x < -1/2 or x > 0 the expression is zero
p = Symbol('p', positive=True)
assert diff.subs(x, p).equals(0) is True
+ assert diff.subs(x, -1).equals(0) is True
def test_random():
from sympy import posify
View
63 sympy/interactive/session.py
@@ -68,7 +68,35 @@ def _make_message(ipython=True, quiet=False, source=None):
return message
-def _init_ipython_session(argv=[], auto=False):
+def enable_automatic_symbols(app):
+ """Allow IPython to automatially create symbols (``isympy -a``). """
+ import re
+ re_nameerror = re.compile("name '(?P<symbol>[A-Za-z_][A-Za-z0-9_]*)' is not defined")
+
+ def _handler(self, etype, value, tb, tb_offset=None):
+ """Handle :exc:`NameError` exception and allow injection of missing symbols. """
+ if etype is NameError and tb.tb_next and not tb.tb_next.tb_next:
+ match = re_nameerror.match(str(value))
+
+ if match is not None:
+ # XXX: Make sure Symbol is in scope. Otherwise you'll get infinite recursion.
+ self.run_cell("%(symbol)s = Symbol('%(symbol)s')" %
+ {'symbol': match.group("symbol")}, store_history=False)
+
+ try:
+ code = self.user_ns['In'][-1]
+ except (KeyError, IndexError):
+ pass
+ else:
+ self.run_cell(code, store_history=False)
+ return None
+
+ stb = self.InteractiveTB.structured_traceback(etype, value, tb, tb_offset=tb_offset)
+ self._showtraceback(etype, value, stb)
+
+ app.shell.set_custom_exc((NameError,), _handler)
+
+def init_ipython_session(argv=[], auto=False):
"""Construct new IPython session. """
import IPython
@@ -81,38 +109,15 @@ def _init_ipython_session(argv=[], auto=False):
app.display_banner = False
app.initialize(argv)
- import re
- re_nameerror = re.compile("name '(?P<symbol>[A-Za-z_][A-Za-z0-9_]*)' is not defined")
-
- def _handler(self, etype, value, tb, tb_offset=None):
- """Handle :exc:`NameError` exception and allow injection of missing symbols. """
- if etype is NameError and tb.tb_next and not tb.tb_next.tb_next:
- match = re_nameerror.match(str(value))
-
- if match is not None:
- self.run_cell("%(symbol)s = Symbol('%(symbol)s')" %
- {'symbol': match.group("symbol")}, store_history=False)
-
- try:
- code = self.user_ns_hidden['In'][-1]
- except (KeyError, IndexError):
- pass
- else:
- self.run_cell(code, store_history=False)
- return None
-
- stb = self.InteractiveTB.structured_traceback(etype, value, tb, tb_offset=tb_offset)
- self._showtraceback(etype, value, stb)
-
if auto:
- app.shell.set_custom_exc((NameError,), _handler)
+ enable_automatic_symbols(app)
return app.shell
else:
from IPython.Shell import make_IPython
return make_IPython(argv)
-def _init_python_session():
+def init_python_session():
"""Construct new Python session. """
from code import InteractiveConsole
@@ -222,7 +227,7 @@ def init_session(ipython=None, pretty_print=True, order=None,
in_ipython = False
if ipython is False:
- ip = _init_python_session()
+ ip = init_python_session()
mainloop = ip.interact
else:
try:
@@ -231,7 +236,7 @@ def init_session(ipython=None, pretty_print=True, order=None,
if ipython is not True:
if not quiet:
print no_ipython
- ip = _init_python_session()
+ ip = init_python_session()
mainloop = ip.interact
else:
raise RuntimeError("IPython is not available on this system")
@@ -251,7 +256,7 @@ def init_session(ipython=None, pretty_print=True, order=None,
if ip is not None:
in_ipython = True
else:
- ip = _init_ipython_session(argv=argv, auto=auto)
+ ip = init_ipython_session(argv=argv, auto=auto)
if IPython.__version__ >= '0.11':
# runsource is gone, use run_cell instead, which doesn't
View
33 sympy/interactive/tests/test_ipython.py
@@ -0,0 +1,33 @@
+"""Tests of tools for setting up interactive IPython sessions. """
+
+from sympy.interactive.session import init_ipython_session, enable_automatic_symbols
+
+from sympy.core import Symbol
+from sympy.external import import_module
+from sympy.utilities.pytest import raises
+
+# TODO: The code below could be made more granular with something like:
+#
+# @requires('IPython', version=">=0.11")
+# def test_automatic_symbols(ipython):
+
+ipython = import_module("IPython", min_module_version="0.11")
+
+if not ipython:
+ #bin/test will not execute any tests now
+ disabled = True
+
+# TODO: Add tests that would verify that enable_automatic_symbols() doesn't
+# break anything. For example typing `factorial` or `all` in an interpreter
+# shouldn't result in a new symbol.
+def test_automatic_symbols():
+ app = init_ipython_session()
+ app.run_cell("from sympy import *")
+
+ enable_automatic_symbols(app)
+
+ symbol = "verylongsymbolname"
+ assert symbol not in app.user_ns
+ app.run_cell(symbol, False)
+ assert symbol in app.user_ns
+ assert isinstance(app.user_ns[symbol], Symbol)
View
3  sympy/printing/pretty/__init__.py
@@ -1,6 +1,7 @@
"""ASCII-ART 2D pretty-printer"""
-from pretty import pretty, pretty_print, pprint, pprint_use_unicode, pprint_try_use_unicode
+from pretty import (pretty, pretty_print, pprint, pprint_use_unicode,
+ pprint_try_use_unicode, pager_print)
# if unicode output is available -- let's use it
pprint_try_use_unicode()
View
16 sympy/printing/pretty/pretty.py
@@ -1438,3 +1438,19 @@ def pretty_print(expr, **settings):
print pretty(expr, **settings)
pprint = pretty_print
+
+def pager_print(expr, **settings):
+ """Prints expr using the pager, in pretty form.
+
+ This invokes a pager command using pydoc. Lines are not wrapped
+ automatically. This routine is meant to be used with a pager that allows
+ sideways scrolling, like ``less -S``.
+
+ Parameters are the same as for ``pretty_print``. If you wish to wrap lines,
+ pass ``num_columns=None`` to auto-detect the width of the terminal.
+
+ """
+ from pydoc import pager
+ if 'num_columns' not in settings:
+ settings['num_columns'] = 500000 # disable line wrap
+ pager(pretty(expr, **settings))
View
2  sympy/series/limits.py
@@ -92,7 +92,7 @@ def limit(e, z, z0, dir="+"):
if ex.is_number:
if c is None:
base = b.subs(z, z0)
- if base.is_bounded and (ex.is_bounded or base is not S.One):
+ if base.is_finite and (ex.is_bounded or base is not S.One):
return base**ex
else:
if z0 == 0 and ex < 0:
View
16 sympy/series/tests/test_limits.py
@@ -33,6 +33,22 @@ def test_basic1():
assert limit(gamma(1/x + 3), x, oo) == 2
assert limit(S.NaN, x, -oo) == S.NaN
assert limit(Order(2)*x, x, S.NaN) == S.NaN
+ assert limit(Sum(1/x, (x, 1, y)) - 1/y, y, oo) == Sum(1/x, (x, 1, oo))
+ assert limit(gamma(1/x + 3), x, oo) == 2
+ assert limit(S.NaN, x, -oo) == S.NaN
+ assert limit(Order(2)*x, x, S.NaN) == S.NaN
+ assert limit(1/(x-1), x, 1, dir="+") == oo
+ assert limit(1/(x-1), x, 1, dir="-") == -oo
+ assert limit(1/(5-x)**3, x, 5, dir="+") == -oo
+ assert limit(1/(5-x)**3, x, 5, dir="-") == oo
+ assert limit(1/sin(x), x, pi, dir="+") == -oo
+ assert limit(1/sin(x), x, pi, dir="-") == oo
+ assert limit(1/cos(x), x, pi/2, dir="+") == -oo
+ assert limit(1/cos(x), x, pi/2, dir="-") == oo
+ assert limit(1/tan(x**3), x, (2*pi)**(S(1)/3), dir="+") == oo
+ assert limit(1/tan(x**3), x, (2*pi)**(S(1)/3), dir="-") == -oo
+ assert limit(1/cot(x)**3, x, (3*pi/2), dir="+") == -oo
+ assert limit(1/cot(x)**3, x, (3*pi/2), dir="-") == oo
# approaching 0
# from dir="+"
View
15 sympy/solvers/solvers.py
@@ -29,7 +29,7 @@
from sympy.functions.elementary.miscellaneous import real_root
from sympy.simplify import (simplify, collect, powsimp, posify, powdenest,
nsimplify)
-from sympy.simplify.sqrtdenest import sqrt_depth
+from sympy.simplify.sqrtdenest import sqrt_depth, _mexpand
from sympy.matrices import Matrix, zeros
from sympy.polys import roots, cancel, Poly, together, factor
from sympy.functions.elementary.piecewise import piecewise_fold, Piecewise
@@ -2179,14 +2179,15 @@ def _take(d):
if cov is None:
cov = []
- eq, reps = posify(eq)
- if syms:
- syms = [s.subs([(v, k) for k, v in reps.items()]) for s in syms]
eq = powdenest(eq)
eq, d = eq.as_numer_denom()
+ eq = _mexpand(eq)
if _take(d):
dens.add(d)
+ if not eq.free_symbols:
+ return eq, cov, list(dens)
+
poly = eq.as_poly()
rads = set([g for g in poly.gens if _take(g) and
@@ -2276,10 +2277,6 @@ def _take(d):
neq = unrad(eq, *syms, **dict(cov=cov, dens=dens, n=len(rterms)))
if neq:
eq = neq[0]
- eq = eq.subs(reps)
if eq.could_extract_minus_sign():
eq = -eq
- return (expand_mul(expand_multinomial(eq)),
- [(c[0], c[1].subs(reps)) for c in cov],
- [d.subs(reps) for d in dens]
- )
+ return (_mexpand(eq), cov, list(dens))
View
10 sympy/solvers/tests/test_solvers.py
@@ -7,7 +7,7 @@
from sympy.core.function import nfloat
from sympy.solvers import solve_linear_system, solve_linear_system_LU,\
solve_undetermined_coeffs
-from sympy.solvers.solvers import _invert, unrad, checksol
+from sympy.solvers.solvers import _invert, unrad, checksol, posify
from sympy.utilities.pytest import XFAIL, raises, skip
@@ -706,6 +706,14 @@ def s_check(rv, ans):
assert solve(sqrt(17*x - sqrt(x**2 - 5)) - 7) == [3]
assert solve(sqrt(x) - sqrt(x - 1) + sqrt(sqrt(x))) == []
+ # don't posify the expession in unrad and use _mexpand
+ z = sqrt(2*x + 1)/sqrt(x) - sqrt(2 + 1/x)
+ p = posify(z)[0]
+ assert solve(p) == []
+ assert solve(z) == []
+ assert solve(z + 6*I) == [-S(1)/11]
+ assert solve(p + 6*I) == []
+
@XFAIL
def test_multivariate():
assert solve((x**2 - 2*x + 1).subs(x, log(x) + 3*x)) == [LambertW(3*S.Exp1)/3]
Please sign in to comment.
Something went wrong with that request. Please try again.