I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

View File

@ -0,0 +1,313 @@
import sympy
import tempfile
import os
from sympy.core.mod import Mod
from sympy.core.relational import Eq
from sympy.core.symbol import symbols
from sympy.external import import_module
from sympy.tensor import IndexedBase, Idx
from sympy.utilities.autowrap import autowrap, ufuncify, CodeWrapError
from sympy.testing.pytest import skip
numpy = import_module('numpy', min_module_version='1.6.1')
Cython = import_module('Cython', min_module_version='0.15.1')
f2py = import_module('numpy.f2py', import_kwargs={'fromlist': ['f2py']})
f2pyworks = False
if f2py:
try:
autowrap(symbols('x'), 'f95', 'f2py')
except (CodeWrapError, ImportError, OSError):
f2pyworks = False
else:
f2pyworks = True
a, b, c = symbols('a b c')
n, m, d = symbols('n m d', integer=True)
A, B, C = symbols('A B C', cls=IndexedBase)
i = Idx('i', m)
j = Idx('j', n)
k = Idx('k', d)
def has_module(module):
"""
Return True if module exists, otherwise run skip().
module should be a string.
"""
# To give a string of the module name to skip(), this function takes a
# string. So we don't waste time running import_module() more than once,
# just map the three modules tested here in this dict.
modnames = {'numpy': numpy, 'Cython': Cython, 'f2py': f2py}
if modnames[module]:
if module == 'f2py' and not f2pyworks:
skip("Couldn't run f2py.")
return True
skip("Couldn't import %s." % module)
#
# test runners used by several language-backend combinations
#
def runtest_autowrap_twice(language, backend):
f = autowrap((((a + b)/c)**5).expand(), language, backend)
g = autowrap((((a + b)/c)**4).expand(), language, backend)
# check that autowrap updates the module name. Else, g gives the same as f
assert f(1, -2, 1) == -1.0
assert g(1, -2, 1) == 1.0
def runtest_autowrap_trace(language, backend):
has_module('numpy')
trace = autowrap(A[i, i], language, backend)
assert trace(numpy.eye(100)) == 100
def runtest_autowrap_matrix_vector(language, backend):
has_module('numpy')
x, y = symbols('x y', cls=IndexedBase)
expr = Eq(y[i], A[i, j]*x[j])
mv = autowrap(expr, language, backend)
# compare with numpy's dot product
M = numpy.random.rand(10, 20)
x = numpy.random.rand(20)
y = numpy.dot(M, x)
assert numpy.sum(numpy.abs(y - mv(M, x))) < 1e-13
def runtest_autowrap_matrix_matrix(language, backend):
has_module('numpy')
expr = Eq(C[i, j], A[i, k]*B[k, j])
matmat = autowrap(expr, language, backend)
# compare with numpy's dot product
M1 = numpy.random.rand(10, 20)
M2 = numpy.random.rand(20, 15)
M3 = numpy.dot(M1, M2)
assert numpy.sum(numpy.abs(M3 - matmat(M1, M2))) < 1e-13
def runtest_ufuncify(language, backend):
has_module('numpy')
a, b, c = symbols('a b c')
fabc = ufuncify([a, b, c], a*b + c, backend=backend)
facb = ufuncify([a, c, b], a*b + c, backend=backend)
grid = numpy.linspace(-2, 2, 50)
b = numpy.linspace(-5, 4, 50)
c = numpy.linspace(-1, 1, 50)
expected = grid*b + c
numpy.testing.assert_allclose(fabc(grid, b, c), expected)
numpy.testing.assert_allclose(facb(grid, c, b), expected)
def runtest_issue_10274(language, backend):
expr = (a - b + c)**(13)
tmp = tempfile.mkdtemp()
f = autowrap(expr, language, backend, tempdir=tmp,
helpers=('helper', a - b + c, (a, b, c)))
assert f(1, 1, 1) == 1
for file in os.listdir(tmp):
if not (file.startswith("wrapped_code_") and file.endswith(".c")):
continue
with open(tmp + '/' + file) as fil:
lines = fil.readlines()
assert lines[0] == "/******************************************************************************\n"
assert "Code generated with SymPy " + sympy.__version__ in lines[1]
assert lines[2:] == [
" * *\n",
" * See http://www.sympy.org/ for more information. *\n",
" * *\n",
" * This file is part of 'autowrap' *\n",
" ******************************************************************************/\n",
"#include " + '"' + file[:-1]+ 'h"' + "\n",
"#include <math.h>\n",
"\n",
"double helper(double a, double b, double c) {\n",
"\n",
" double helper_result;\n",
" helper_result = a - b + c;\n",
" return helper_result;\n",
"\n",
"}\n",
"\n",
"double autofunc(double a, double b, double c) {\n",
"\n",
" double autofunc_result;\n",
" autofunc_result = pow(helper(a, b, c), 13);\n",
" return autofunc_result;\n",
"\n",
"}\n",
]
def runtest_issue_15337(language, backend):
has_module('numpy')
# NOTE : autowrap was originally designed to only accept an iterable for
# the kwarg "helpers", but in issue 10274 the user mistakenly thought that
# if there was only a single helper it did not need to be passed via an
# iterable that wrapped the helper tuple. There were no tests for this
# behavior so when the code was changed to accept a single tuple it broke
# the original behavior. These tests below ensure that both now work.
a, b, c, d, e = symbols('a, b, c, d, e')
expr = (a - b + c - d + e)**13
exp_res = (1. - 2. + 3. - 4. + 5.)**13
f = autowrap(expr, language, backend, args=(a, b, c, d, e),
helpers=('f1', a - b + c, (a, b, c)))
numpy.testing.assert_allclose(f(1, 2, 3, 4, 5), exp_res)
f = autowrap(expr, language, backend, args=(a, b, c, d, e),
helpers=(('f1', a - b, (a, b)), ('f2', c - d, (c, d))))
numpy.testing.assert_allclose(f(1, 2, 3, 4, 5), exp_res)
def test_issue_15230():
has_module('f2py')
x, y = symbols('x, y')
expr = Mod(x, 3.0) - Mod(y, -2.0)
f = autowrap(expr, args=[x, y], language='F95')
exp_res = float(expr.xreplace({x: 3.5, y: 2.7}).evalf())
assert abs(f(3.5, 2.7) - exp_res) < 1e-14
x, y = symbols('x, y', integer=True)
expr = Mod(x, 3) - Mod(y, -2)
f = autowrap(expr, args=[x, y], language='F95')
assert f(3, 2) == expr.xreplace({x: 3, y: 2})
#
# tests of language-backend combinations
#
# f2py
def test_wrap_twice_f95_f2py():
has_module('f2py')
runtest_autowrap_twice('f95', 'f2py')
def test_autowrap_trace_f95_f2py():
has_module('f2py')
runtest_autowrap_trace('f95', 'f2py')
def test_autowrap_matrix_vector_f95_f2py():
has_module('f2py')
runtest_autowrap_matrix_vector('f95', 'f2py')
def test_autowrap_matrix_matrix_f95_f2py():
has_module('f2py')
runtest_autowrap_matrix_matrix('f95', 'f2py')
def test_ufuncify_f95_f2py():
has_module('f2py')
runtest_ufuncify('f95', 'f2py')
def test_issue_15337_f95_f2py():
has_module('f2py')
runtest_issue_15337('f95', 'f2py')
# Cython
def test_wrap_twice_c_cython():
has_module('Cython')
runtest_autowrap_twice('C', 'cython')
def test_autowrap_trace_C_Cython():
has_module('Cython')
runtest_autowrap_trace('C99', 'cython')
def test_autowrap_matrix_vector_C_cython():
has_module('Cython')
runtest_autowrap_matrix_vector('C99', 'cython')
def test_autowrap_matrix_matrix_C_cython():
has_module('Cython')
runtest_autowrap_matrix_matrix('C99', 'cython')
def test_ufuncify_C_Cython():
has_module('Cython')
runtest_ufuncify('C99', 'cython')
def test_issue_10274_C_cython():
has_module('Cython')
runtest_issue_10274('C89', 'cython')
def test_issue_15337_C_cython():
has_module('Cython')
runtest_issue_15337('C89', 'cython')
def test_autowrap_custom_printer():
has_module('Cython')
from sympy.core.numbers import pi
from sympy.utilities.codegen import C99CodeGen
from sympy.printing.c import C99CodePrinter
class PiPrinter(C99CodePrinter):
def _print_Pi(self, expr):
return "S_PI"
printer = PiPrinter()
gen = C99CodeGen(printer=printer)
gen.preprocessor_statements.append('#include "shortpi.h"')
expr = pi * a
expected = (
'#include "%s"\n'
'#include <math.h>\n'
'#include "shortpi.h"\n'
'\n'
'double autofunc(double a) {\n'
'\n'
' double autofunc_result;\n'
' autofunc_result = S_PI*a;\n'
' return autofunc_result;\n'
'\n'
'}\n'
)
tmpdir = tempfile.mkdtemp()
# write a trivial header file to use in the generated code
with open(os.path.join(tmpdir, 'shortpi.h'), 'w') as f:
f.write('#define S_PI 3.14')
func = autowrap(expr, backend='cython', tempdir=tmpdir, code_gen=gen)
assert func(4.2) == 3.14 * 4.2
# check that the generated code is correct
for filename in os.listdir(tmpdir):
if filename.startswith('wrapped_code') and filename.endswith('.c'):
with open(os.path.join(tmpdir, filename)) as f:
lines = f.readlines()
expected = expected % filename.replace('.c', '.h')
assert ''.join(lines[7:]) == expected
# Numpy
def test_ufuncify_numpy():
# This test doesn't use Cython, but if Cython works, then there is a valid
# C compiler, which is needed.
has_module('Cython')
runtest_ufuncify('C99', 'numpy')

View File

@ -0,0 +1,379 @@
# This tests the compilation and execution of the source code generated with
# utilities.codegen. The compilation takes place in a temporary directory that
# is removed after the test. By default the test directory is always removed,
# but this behavior can be changed by setting the environment variable
# SYMPY_TEST_CLEAN_TEMP to:
# export SYMPY_TEST_CLEAN_TEMP=always : the default behavior.
# export SYMPY_TEST_CLEAN_TEMP=success : only remove the directories of working tests.
# export SYMPY_TEST_CLEAN_TEMP=never : never remove the directories with the test code.
# When a directory is not removed, the necessary information is printed on
# screen to find the files that belong to the (failed) tests. If a test does
# not fail, py.test captures all the output and you will not see the directories
# corresponding to the successful tests. Use the --nocapture option to see all
# the output.
# All tests below have a counterpart in utilities/test/test_codegen.py. In the
# latter file, the resulting code is compared with predefined strings, without
# compilation or execution.
# All the generated Fortran code should conform with the Fortran 95 standard,
# and all the generated C code should be ANSI C, which facilitates the
# incorporation in various projects. The tests below assume that the binary cc
# is somewhere in the path and that it can compile ANSI C code.
from sympy.abc import x, y, z
from sympy.external import import_module
from sympy.testing.pytest import skip
from sympy.utilities.codegen import codegen, make_routine, get_code_generator
import sys
import os
import tempfile
import subprocess
pyodide_js = import_module('pyodide_js')
# templates for the main program that will test the generated code.
main_template = {}
main_template['F95'] = """
program main
include "codegen.h"
integer :: result;
result = 0
%(statements)s
call exit(result)
end program
"""
main_template['C89'] = """
#include "codegen.h"
#include <stdio.h>
#include <math.h>
int main() {
int result = 0;
%(statements)s
return result;
}
"""
main_template['C99'] = main_template['C89']
# templates for the numerical tests
numerical_test_template = {}
numerical_test_template['C89'] = """
if (fabs(%(call)s)>%(threshold)s) {
printf("Numerical validation failed: %(call)s=%%e threshold=%(threshold)s\\n", %(call)s);
result = -1;
}
"""
numerical_test_template['C99'] = numerical_test_template['C89']
numerical_test_template['F95'] = """
if (abs(%(call)s)>%(threshold)s) then
write(6,"('Numerical validation failed:')")
write(6,"('%(call)s=',e15.5,'threshold=',e15.5)") %(call)s, %(threshold)s
result = -1;
end if
"""
# command sequences for supported compilers
compile_commands = {}
compile_commands['cc'] = [
"cc -c codegen.c -o codegen.o",
"cc -c main.c -o main.o",
"cc main.o codegen.o -lm -o test.exe"
]
compile_commands['gfortran'] = [
"gfortran -c codegen.f90 -o codegen.o",
"gfortran -ffree-line-length-none -c main.f90 -o main.o",
"gfortran main.o codegen.o -o test.exe"
]
compile_commands['g95'] = [
"g95 -c codegen.f90 -o codegen.o",
"g95 -ffree-line-length-huge -c main.f90 -o main.o",
"g95 main.o codegen.o -o test.exe"
]
compile_commands['ifort'] = [
"ifort -c codegen.f90 -o codegen.o",
"ifort -c main.f90 -o main.o",
"ifort main.o codegen.o -o test.exe"
]
combinations_lang_compiler = [
('C89', 'cc'),
('C99', 'cc'),
('F95', 'ifort'),
('F95', 'gfortran'),
('F95', 'g95')
]
def try_run(commands):
"""Run a series of commands and only return True if all ran fine."""
if pyodide_js:
return False
with open(os.devnull, 'w') as null:
for command in commands:
retcode = subprocess.call(command, stdout=null, shell=True,
stderr=subprocess.STDOUT)
if retcode != 0:
return False
return True
def run_test(label, routines, numerical_tests, language, commands, friendly=True):
"""A driver for the codegen tests.
This driver assumes that a compiler ifort is present in the PATH and that
ifort is (at least) a Fortran 90 compiler. The generated code is written in
a temporary directory, together with a main program that validates the
generated code. The test passes when the compilation and the validation
run correctly.
"""
# Check input arguments before touching the file system
language = language.upper()
assert language in main_template
assert language in numerical_test_template
# Check that environment variable makes sense
clean = os.getenv('SYMPY_TEST_CLEAN_TEMP', 'always').lower()
if clean not in ('always', 'success', 'never'):
raise ValueError("SYMPY_TEST_CLEAN_TEMP must be one of the following: 'always', 'success' or 'never'.")
# Do all the magic to compile, run and validate the test code
# 1) prepare the temporary working directory, switch to that dir
work = tempfile.mkdtemp("_sympy_%s_test" % language, "%s_" % label)
oldwork = os.getcwd()
os.chdir(work)
# 2) write the generated code
if friendly:
# interpret the routines as a name_expr list and call the friendly
# function codegen
codegen(routines, language, "codegen", to_files=True)
else:
code_gen = get_code_generator(language, "codegen")
code_gen.write(routines, "codegen", to_files=True)
# 3) write a simple main program that links to the generated code, and that
# includes the numerical tests
test_strings = []
for fn_name, args, expected, threshold in numerical_tests:
call_string = "%s(%s)-(%s)" % (
fn_name, ",".join(str(arg) for arg in args), expected)
if language == "F95":
call_string = fortranize_double_constants(call_string)
threshold = fortranize_double_constants(str(threshold))
test_strings.append(numerical_test_template[language] % {
"call": call_string,
"threshold": threshold,
})
if language == "F95":
f_name = "main.f90"
elif language.startswith("C"):
f_name = "main.c"
else:
raise NotImplementedError(
"FIXME: filename extension unknown for language: %s" % language)
with open(f_name, "w") as f:
f.write(
main_template[language] % {'statements': "".join(test_strings)})
# 4) Compile and link
compiled = try_run(commands)
# 5) Run if compiled
if compiled:
executed = try_run(["./test.exe"])
else:
executed = False
# 6) Clean up stuff
if clean == 'always' or (clean == 'success' and compiled and executed):
def safe_remove(filename):
if os.path.isfile(filename):
os.remove(filename)
safe_remove("codegen.f90")
safe_remove("codegen.c")
safe_remove("codegen.h")
safe_remove("codegen.o")
safe_remove("main.f90")
safe_remove("main.c")
safe_remove("main.o")
safe_remove("test.exe")
os.chdir(oldwork)
os.rmdir(work)
else:
print("TEST NOT REMOVED: %s" % work, file=sys.stderr)
os.chdir(oldwork)
# 7) Do the assertions in the end
assert compiled, "failed to compile %s code with:\n%s" % (
language, "\n".join(commands))
assert executed, "failed to execute %s code from:\n%s" % (
language, "\n".join(commands))
def fortranize_double_constants(code_string):
"""
Replaces every literal float with literal doubles
"""
import re
pattern_exp = re.compile(r'\d+(\.)?\d*[eE]-?\d+')
pattern_float = re.compile(r'\d+\.\d*(?!\d*d)')
def subs_exp(matchobj):
return re.sub('[eE]', 'd', matchobj.group(0))
def subs_float(matchobj):
return "%sd0" % matchobj.group(0)
code_string = pattern_exp.sub(subs_exp, code_string)
code_string = pattern_float.sub(subs_float, code_string)
return code_string
def is_feasible(language, commands):
# This test should always work, otherwise the compiler is not present.
routine = make_routine("test", x)
numerical_tests = [
("test", ( 1.0,), 1.0, 1e-15),
("test", (-1.0,), -1.0, 1e-15),
]
try:
run_test("is_feasible", [routine], numerical_tests, language, commands,
friendly=False)
return True
except AssertionError:
return False
valid_lang_commands = []
invalid_lang_compilers = []
for lang, compiler in combinations_lang_compiler:
commands = compile_commands[compiler]
if is_feasible(lang, commands):
valid_lang_commands.append((lang, commands))
else:
invalid_lang_compilers.append((lang, compiler))
# We test all language-compiler combinations, just to report what is skipped
def test_C89_cc():
if ("C89", 'cc') in invalid_lang_compilers:
skip("`cc' command didn't work as expected (C89)")
def test_C99_cc():
if ("C99", 'cc') in invalid_lang_compilers:
skip("`cc' command didn't work as expected (C99)")
def test_F95_ifort():
if ("F95", 'ifort') in invalid_lang_compilers:
skip("`ifort' command didn't work as expected")
def test_F95_gfortran():
if ("F95", 'gfortran') in invalid_lang_compilers:
skip("`gfortran' command didn't work as expected")
def test_F95_g95():
if ("F95", 'g95') in invalid_lang_compilers:
skip("`g95' command didn't work as expected")
# Here comes the actual tests
def test_basic_codegen():
numerical_tests = [
("test", (1.0, 6.0, 3.0), 21.0, 1e-15),
("test", (-1.0, 2.0, -2.5), -2.5, 1e-15),
]
name_expr = [("test", (x + y)*z)]
for lang, commands in valid_lang_commands:
run_test("basic_codegen", name_expr, numerical_tests, lang, commands)
def test_intrinsic_math1_codegen():
# not included: log10
from sympy.core.evalf import N
from sympy.functions import ln
from sympy.functions.elementary.exponential import log
from sympy.functions.elementary.hyperbolic import (cosh, sinh, tanh)
from sympy.functions.elementary.integers import (ceiling, floor)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (acos, asin, atan, cos, sin, tan)
name_expr = [
("test_fabs", abs(x)),
("test_acos", acos(x)),
("test_asin", asin(x)),
("test_atan", atan(x)),
("test_cos", cos(x)),
("test_cosh", cosh(x)),
("test_log", log(x)),
("test_ln", ln(x)),
("test_sin", sin(x)),
("test_sinh", sinh(x)),
("test_sqrt", sqrt(x)),
("test_tan", tan(x)),
("test_tanh", tanh(x)),
]
numerical_tests = []
for name, expr in name_expr:
for xval in 0.2, 0.5, 0.8:
expected = N(expr.subs(x, xval))
numerical_tests.append((name, (xval,), expected, 1e-14))
for lang, commands in valid_lang_commands:
if lang.startswith("C"):
name_expr_C = [("test_floor", floor(x)), ("test_ceil", ceiling(x))]
else:
name_expr_C = []
run_test("intrinsic_math1", name_expr + name_expr_C,
numerical_tests, lang, commands)
def test_instrinsic_math2_codegen():
# not included: frexp, ldexp, modf, fmod
from sympy.core.evalf import N
from sympy.functions.elementary.trigonometric import atan2
name_expr = [
("test_atan2", atan2(x, y)),
("test_pow", x**y),
]
numerical_tests = []
for name, expr in name_expr:
for xval, yval in (0.2, 1.3), (0.5, -0.2), (0.8, 0.8):
expected = N(expr.subs(x, xval).subs(y, yval))
numerical_tests.append((name, (xval, yval), expected, 1e-14))
for lang, commands in valid_lang_commands:
run_test("intrinsic_math2", name_expr, numerical_tests, lang, commands)
def test_complicated_codegen():
from sympy.core.evalf import N
from sympy.functions.elementary.trigonometric import (cos, sin, tan)
name_expr = [
("test1", ((sin(x) + cos(y) + tan(z))**7).expand()),
("test2", cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))),
]
numerical_tests = []
for name, expr in name_expr:
for xval, yval, zval in (0.2, 1.3, -0.3), (0.5, -0.2, 0.0), (0.8, 2.1, 0.8):
expected = N(expr.subs(x, xval).subs(y, yval).subs(z, zval))
numerical_tests.append((name, (xval, yval, zval), expected, 1e-12))
for lang, commands in valid_lang_commands:
run_test(
"complicated_codegen", name_expr, numerical_tests, lang, commands)

View File

@ -0,0 +1,12 @@
from sympy.external.gmpy import LONG_MAX, iroot
from sympy.testing.pytest import raises
def test_iroot():
assert iroot(2, LONG_MAX) == (1, False)
assert iroot(2, LONG_MAX + 1) == (1, False)
for x in range(3):
assert iroot(x, 1) == (x, True)
raises(ValueError, lambda: iroot(-1, 1))
raises(ValueError, lambda: iroot(0, 0))
raises(ValueError, lambda: iroot(0, -1))

View File

@ -0,0 +1,40 @@
from sympy.external import import_module
from sympy.testing.pytest import warns
# fixes issue that arose in addressing issue 6533
def test_no_stdlib_collections():
'''
make sure we get the right collections when it is not part of a
larger list
'''
import collections
matplotlib = import_module('matplotlib',
import_kwargs={'fromlist': ['cm', 'collections']},
min_module_version='1.1.0', catch=(RuntimeError,))
if matplotlib:
assert collections != matplotlib.collections
def test_no_stdlib_collections2():
'''
make sure we get the right collections when it is not part of a
larger list
'''
import collections
matplotlib = import_module('matplotlib',
import_kwargs={'fromlist': ['collections']},
min_module_version='1.1.0', catch=(RuntimeError,))
if matplotlib:
assert collections != matplotlib.collections
def test_no_stdlib_collections3():
'''make sure we get the right collections with no catch'''
import collections
matplotlib = import_module('matplotlib',
import_kwargs={'fromlist': ['cm', 'collections']},
min_module_version='1.1.0')
if matplotlib:
assert collections != matplotlib.collections
def test_min_module_version_python3_basestring_error():
with warns(UserWarning):
import_module('mpmath', min_module_version='1000.0.1')

View File

@ -0,0 +1,307 @@
from itertools import permutations
from sympy.external.ntheory import (bit_scan1, remove, bit_scan0, is_fermat_prp,
is_euler_prp, is_strong_prp, gcdext, _lucas_sequence,
is_fibonacci_prp, is_lucas_prp, is_selfridge_prp,
is_strong_lucas_prp, is_strong_selfridge_prp,
is_bpsw_prp, is_strong_bpsw_prp)
from sympy.testing.pytest import raises
def test_bit_scan1():
assert bit_scan1(0) is None
assert bit_scan1(1) == 0
assert bit_scan1(-1) == 0
assert bit_scan1(2) == 1
assert bit_scan1(7) == 0
assert bit_scan1(-7) == 0
for i in range(100):
assert bit_scan1(1 << i) == i
assert bit_scan1((1 << i) * 31337) == i
for i in range(500):
n = (1 << 500) + (1 << i)
assert bit_scan1(n) == i
assert bit_scan1(1 << 1000001) == 1000001
assert bit_scan1((1 << 273956)*7**37) == 273956
# issue 12709
for i in range(1, 10):
big = 1 << i
assert bit_scan1(-big) == bit_scan1(big)
def test_bit_scan0():
assert bit_scan0(-1) is None
assert bit_scan0(0) == 0
assert bit_scan0(1) == 1
assert bit_scan0(-2) == 0
def test_remove():
raises(ValueError, lambda: remove(1, 1))
assert remove(0, 3) == (0, 0)
for f in range(2, 10):
for y in range(2, 1000):
for z in [1, 17, 101, 1009]:
assert remove(z*f**y, f) == (z, y)
def test_gcdext():
assert gcdext(0, 0) == (0, 0, 0)
assert gcdext(3, 0) == (3, 1, 0)
assert gcdext(0, 4) == (4, 0, 1)
for n in range(1, 10):
assert gcdext(n, 1) == gcdext(-n, 1) == (1, 0, 1)
assert gcdext(n, -1) == gcdext(-n, -1) == (1, 0, -1)
assert gcdext(n, n) == gcdext(-n, n) == (n, 0, 1)
assert gcdext(n, -n) == gcdext(-n, -n) == (n, 0, -1)
for n in range(2, 10):
assert gcdext(1, n) == gcdext(1, -n) == (1, 1, 0)
assert gcdext(-1, n) == gcdext(-1, -n) == (1, -1, 0)
for a, b in permutations([2**5, 3, 5, 7**2, 11], 2):
g, x, y = gcdext(a, b)
assert g == a*x + b*y == 1
def test_is_fermat_prp():
# invalid input
raises(ValueError, lambda: is_fermat_prp(0, 10))
raises(ValueError, lambda: is_fermat_prp(5, 1))
# n = 1
assert not is_fermat_prp(1, 3)
# n is prime
assert is_fermat_prp(2, 4)
assert is_fermat_prp(3, 2)
assert is_fermat_prp(11, 3)
assert is_fermat_prp(2**31-1, 5)
# A001567
pseudorpime = [341, 561, 645, 1105, 1387, 1729, 1905, 2047,
2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681]
for n in pseudorpime:
assert is_fermat_prp(n, 2)
# A020136
pseudorpime = [15, 85, 91, 341, 435, 451, 561, 645, 703, 1105,
1247, 1271, 1387, 1581, 1695, 1729, 1891, 1905]
for n in pseudorpime:
assert is_fermat_prp(n, 4)
def test_is_euler_prp():
# invalid input
raises(ValueError, lambda: is_euler_prp(0, 10))
raises(ValueError, lambda: is_euler_prp(5, 1))
# n = 1
assert not is_euler_prp(1, 3)
# n is prime
assert is_euler_prp(2, 4)
assert is_euler_prp(3, 2)
assert is_euler_prp(11, 3)
assert is_euler_prp(2**31-1, 5)
# A047713
pseudorpime = [561, 1105, 1729, 1905, 2047, 2465, 3277, 4033,
4681, 6601, 8321, 8481, 10585, 12801, 15841]
for n in pseudorpime:
assert is_euler_prp(n, 2)
# A048950
pseudorpime = [121, 703, 1729, 1891, 2821, 3281, 7381, 8401,
8911, 10585, 12403, 15457, 15841, 16531, 18721]
for n in pseudorpime:
assert is_euler_prp(n, 3)
def test_is_strong_prp():
# invalid input
raises(ValueError, lambda: is_strong_prp(0, 10))
raises(ValueError, lambda: is_strong_prp(5, 1))
# n = 1
assert not is_strong_prp(1, 3)
# n is prime
assert is_strong_prp(2, 4)
assert is_strong_prp(3, 2)
assert is_strong_prp(11, 3)
assert is_strong_prp(2**31-1, 5)
# A001262
pseudorpime = [2047, 3277, 4033, 4681, 8321, 15841, 29341,
42799, 49141, 52633, 65281, 74665, 80581]
for n in pseudorpime:
assert is_strong_prp(n, 2)
# A020229
pseudorpime = [121, 703, 1891, 3281, 8401, 8911, 10585, 12403,
16531, 18721, 19345, 23521, 31621, 44287, 47197]
for n in pseudorpime:
assert is_strong_prp(n, 3)
def test_lucas_sequence():
def lucas_u(P, Q, length):
array = [0] * length
array[1] = 1
for k in range(2, length):
array[k] = P * array[k - 1] - Q * array[k - 2]
return array
def lucas_v(P, Q, length):
array = [0] * length
array[0] = 2
array[1] = P
for k in range(2, length):
array[k] = P * array[k - 1] - Q * array[k - 2]
return array
length = 20
for P in range(-10, 10):
for Q in range(-10, 10):
D = P**2 - 4*Q
if D == 0:
continue
us = lucas_u(P, Q, length)
vs = lucas_v(P, Q, length)
for n in range(3, 100, 2):
for k in range(length):
U, V, Qk = _lucas_sequence(n, P, Q, k)
assert U == us[k] % n
assert V == vs[k] % n
assert pow(Q, k, n) == Qk
def test_is_fibonacci_prp():
# invalid input
raises(ValueError, lambda: is_fibonacci_prp(3, 2, 1))
raises(ValueError, lambda: is_fibonacci_prp(3, -5, 1))
raises(ValueError, lambda: is_fibonacci_prp(3, 5, 2))
raises(ValueError, lambda: is_fibonacci_prp(0, 5, -1))
# n = 1
assert not is_fibonacci_prp(1, 3, 1)
# n is prime
assert is_fibonacci_prp(2, 5, 1)
assert is_fibonacci_prp(3, 6, -1)
assert is_fibonacci_prp(11, 7, 1)
assert is_fibonacci_prp(2**31-1, 8, -1)
# A005845
pseudorpime = [705, 2465, 2737, 3745, 4181, 5777, 6721,
10877, 13201, 15251, 24465, 29281, 34561]
for n in pseudorpime:
assert is_fibonacci_prp(n, 1, -1)
def test_is_lucas_prp():
# invalid input
raises(ValueError, lambda: is_lucas_prp(3, 2, 1))
raises(ValueError, lambda: is_lucas_prp(0, 5, -1))
raises(ValueError, lambda: is_lucas_prp(15, 3, 1))
# n = 1
assert not is_lucas_prp(1, 3, 1)
# n is prime
assert is_lucas_prp(2, 5, 2)
assert is_lucas_prp(3, 6, -1)
assert is_lucas_prp(11, 7, 5)
assert is_lucas_prp(2**31-1, 8, -3)
# A081264
pseudorpime = [323, 377, 1891, 3827, 4181, 5777, 6601, 6721,
8149, 10877, 11663, 13201, 13981, 15251, 17119]
for n in pseudorpime:
assert is_lucas_prp(n, 1, -1)
def test_is_selfridge_prp():
# invalid input
raises(ValueError, lambda: is_selfridge_prp(0))
# n = 1
assert not is_selfridge_prp(1)
# n is prime
assert is_selfridge_prp(2)
assert is_selfridge_prp(3)
assert is_selfridge_prp(11)
assert is_selfridge_prp(2**31-1)
# A217120
pseudorpime = [323, 377, 1159, 1829, 3827, 5459, 5777, 9071,
9179, 10877, 11419, 11663, 13919, 14839, 16109]
for n in pseudorpime:
assert is_selfridge_prp(n)
def test_is_strong_lucas_prp():
# invalid input
raises(ValueError, lambda: is_strong_lucas_prp(3, 2, 1))
raises(ValueError, lambda: is_strong_lucas_prp(0, 5, -1))
raises(ValueError, lambda: is_strong_lucas_prp(15, 3, 1))
# n = 1
assert not is_strong_lucas_prp(1, 3, 1)
# n is prime
assert is_strong_lucas_prp(2, 5, 2)
assert is_strong_lucas_prp(3, 6, -1)
assert is_strong_lucas_prp(11, 7, 5)
assert is_strong_lucas_prp(2**31-1, 8, -3)
def test_is_strong_selfridge_prp():
# invalid input
raises(ValueError, lambda: is_strong_selfridge_prp(0))
# n = 1
assert not is_strong_selfridge_prp(1)
# n is prime
assert is_strong_selfridge_prp(2)
assert is_strong_selfridge_prp(3)
assert is_strong_selfridge_prp(11)
assert is_strong_selfridge_prp(2**31-1)
# A217255
pseudorpime = [5459, 5777, 10877, 16109, 18971, 22499, 24569,
25199, 40309, 58519, 75077, 97439, 100127, 113573]
for n in pseudorpime:
assert is_strong_selfridge_prp(n)
def test_is_bpsw_prp():
# invalid input
raises(ValueError, lambda: is_bpsw_prp(0))
# n = 1
assert not is_bpsw_prp(1)
# n is prime
assert is_bpsw_prp(2)
assert is_bpsw_prp(3)
assert is_bpsw_prp(11)
assert is_bpsw_prp(2**31-1)
def test_is_strong_bpsw_prp():
# invalid input
raises(ValueError, lambda: is_strong_bpsw_prp(0))
# n = 1
assert not is_strong_bpsw_prp(1)
# n is prime
assert is_strong_bpsw_prp(2)
assert is_strong_bpsw_prp(3)
assert is_strong_bpsw_prp(11)
assert is_strong_bpsw_prp(2**31-1)

View File

@ -0,0 +1,335 @@
# This testfile tests SymPy <-> NumPy compatibility
# Don't test any SymPy features here. Just pure interaction with NumPy.
# Always write regular SymPy tests for anything, that can be tested in pure
# Python (without numpy). Here we test everything, that a user may need when
# using SymPy with NumPy
from sympy.external.importtools import version_tuple
from sympy.external import import_module
numpy = import_module('numpy')
if numpy:
array, matrix, ndarray = numpy.array, numpy.matrix, numpy.ndarray
else:
#bin/test will not execute any tests now
disabled = True
from sympy.core.numbers import (Float, Integer, Rational)
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.trigonometric import sin
from sympy.matrices.dense import (Matrix, list2numpy, matrix2numpy, symarray)
from sympy.utilities.lambdify import lambdify
import sympy
import mpmath
from sympy.abc import x, y, z
from sympy.utilities.decorator import conserve_mpmath_dps
from sympy.utilities.exceptions import ignore_warnings
from sympy.testing.pytest import raises
# first, systematically check, that all operations are implemented and don't
# raise an exception
def test_systematic_basic():
def s(sympy_object, numpy_array):
_ = [sympy_object + numpy_array,
numpy_array + sympy_object,
sympy_object - numpy_array,
numpy_array - sympy_object,
sympy_object * numpy_array,
numpy_array * sympy_object,
sympy_object / numpy_array,
numpy_array / sympy_object,
sympy_object ** numpy_array,
numpy_array ** sympy_object]
x = Symbol("x")
y = Symbol("y")
sympy_objs = [
Rational(2, 3),
Float("1.3"),
x,
y,
pow(x, y)*y,
Integer(5),
Float(5.5),
]
numpy_objs = [
array([1]),
array([3, 8, -1]),
array([x, x**2, Rational(5)]),
array([x/y*sin(y), 5, Rational(5)]),
]
for x in sympy_objs:
for y in numpy_objs:
s(x, y)
# now some random tests, that test particular problems and that also
# check that the results of the operations are correct
def test_basics():
one = Rational(1)
zero = Rational(0)
assert array(1) == array(one)
assert array([one]) == array([one])
assert array([x]) == array([x])
assert array(x) == array(Symbol("x"))
assert array(one + x) == array(1 + x)
X = array([one, zero, zero])
assert (X == array([one, zero, zero])).all()
assert (X == array([one, 0, 0])).all()
def test_arrays():
one = Rational(1)
zero = Rational(0)
X = array([one, zero, zero])
Y = one*X
X = array([Symbol("a") + Rational(1, 2)])
Y = X + X
assert Y == array([1 + 2*Symbol("a")])
Y = Y + 1
assert Y == array([2 + 2*Symbol("a")])
Y = X - X
assert Y == array([0])
def test_conversion1():
a = list2numpy([x**2, x])
#looks like an array?
assert isinstance(a, ndarray)
assert a[0] == x**2
assert a[1] == x
assert len(a) == 2
#yes, it's the array
def test_conversion2():
a = 2*list2numpy([x**2, x])
b = list2numpy([2*x**2, 2*x])
assert (a == b).all()
one = Rational(1)
zero = Rational(0)
X = list2numpy([one, zero, zero])
Y = one*X
X = list2numpy([Symbol("a") + Rational(1, 2)])
Y = X + X
assert Y == array([1 + 2*Symbol("a")])
Y = Y + 1
assert Y == array([2 + 2*Symbol("a")])
Y = X - X
assert Y == array([0])
def test_list2numpy():
assert (array([x**2, x]) == list2numpy([x**2, x])).all()
def test_Matrix1():
m = Matrix([[x, x**2], [5, 2/x]])
assert (array(m.subs(x, 2)) == array([[2, 4], [5, 1]])).all()
m = Matrix([[sin(x), x**2], [5, 2/x]])
assert (array(m.subs(x, 2)) == array([[sin(2), 4], [5, 1]])).all()
def test_Matrix2():
m = Matrix([[x, x**2], [5, 2/x]])
with ignore_warnings(PendingDeprecationWarning):
assert (matrix(m.subs(x, 2)) == matrix([[2, 4], [5, 1]])).all()
m = Matrix([[sin(x), x**2], [5, 2/x]])
with ignore_warnings(PendingDeprecationWarning):
assert (matrix(m.subs(x, 2)) == matrix([[sin(2), 4], [5, 1]])).all()
def test_Matrix3():
a = array([[2, 4], [5, 1]])
assert Matrix(a) == Matrix([[2, 4], [5, 1]])
assert Matrix(a) != Matrix([[2, 4], [5, 2]])
a = array([[sin(2), 4], [5, 1]])
assert Matrix(a) == Matrix([[sin(2), 4], [5, 1]])
assert Matrix(a) != Matrix([[sin(0), 4], [5, 1]])
def test_Matrix4():
with ignore_warnings(PendingDeprecationWarning):
a = matrix([[2, 4], [5, 1]])
assert Matrix(a) == Matrix([[2, 4], [5, 1]])
assert Matrix(a) != Matrix([[2, 4], [5, 2]])
with ignore_warnings(PendingDeprecationWarning):
a = matrix([[sin(2), 4], [5, 1]])
assert Matrix(a) == Matrix([[sin(2), 4], [5, 1]])
assert Matrix(a) != Matrix([[sin(0), 4], [5, 1]])
def test_Matrix_sum():
M = Matrix([[1, 2, 3], [x, y, x], [2*y, -50, z*x]])
with ignore_warnings(PendingDeprecationWarning):
m = matrix([[2, 3, 4], [x, 5, 6], [x, y, z**2]])
assert M + m == Matrix([[3, 5, 7], [2*x, y + 5, x + 6], [2*y + x, y - 50, z*x + z**2]])
assert m + M == Matrix([[3, 5, 7], [2*x, y + 5, x + 6], [2*y + x, y - 50, z*x + z**2]])
assert M + m == M.add(m)
def test_Matrix_mul():
M = Matrix([[1, 2, 3], [x, y, x]])
with ignore_warnings(PendingDeprecationWarning):
m = matrix([[2, 4], [x, 6], [x, z**2]])
assert M*m == Matrix([
[ 2 + 5*x, 16 + 3*z**2],
[2*x + x*y + x**2, 4*x + 6*y + x*z**2],
])
assert m*M == Matrix([
[ 2 + 4*x, 4 + 4*y, 6 + 4*x],
[ 7*x, 2*x + 6*y, 9*x],
[x + x*z**2, 2*x + y*z**2, 3*x + x*z**2],
])
a = array([2])
assert a[0] * M == 2 * M
assert M * a[0] == 2 * M
def test_Matrix_array():
class matarray:
def __array__(self, dtype=object, copy=None):
if copy is not None and not copy:
raise TypeError("Cannot implement copy=False when converting Matrix to ndarray")
from numpy import array
return array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
matarr = matarray()
assert Matrix(matarr) == Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
def test_matrix2numpy():
a = matrix2numpy(Matrix([[1, x**2], [3*sin(x), 0]]))
assert isinstance(a, ndarray)
assert a.shape == (2, 2)
assert a[0, 0] == 1
assert a[0, 1] == x**2
assert a[1, 0] == 3*sin(x)
assert a[1, 1] == 0
def test_matrix2numpy_conversion():
a = Matrix([[1, 2, sin(x)], [x**2, x, Rational(1, 2)]])
b = array([[1, 2, sin(x)], [x**2, x, Rational(1, 2)]])
assert (matrix2numpy(a) == b).all()
assert matrix2numpy(a).dtype == numpy.dtype('object')
c = matrix2numpy(Matrix([[1, 2], [10, 20]]), dtype='int8')
d = matrix2numpy(Matrix([[1, 2], [10, 20]]), dtype='float64')
assert c.dtype == numpy.dtype('int8')
assert d.dtype == numpy.dtype('float64')
def test_issue_3728():
assert (Rational(1, 2)*array([2*x, 0]) == array([x, 0])).all()
assert (Rational(1, 2) + array(
[2*x, 0]) == array([2*x + Rational(1, 2), Rational(1, 2)])).all()
assert (Float("0.5")*array([2*x, 0]) == array([Float("1.0")*x, 0])).all()
assert (Float("0.5") + array(
[2*x, 0]) == array([2*x + Float("0.5"), Float("0.5")])).all()
@conserve_mpmath_dps
def test_lambdify():
mpmath.mp.dps = 16
sin02 = mpmath.mpf("0.198669330795061215459412627")
f = lambdify(x, sin(x), "numpy")
prec = 1e-15
assert -prec < f(0.2) - sin02 < prec
# if this succeeds, it can't be a numpy function
if version_tuple(numpy.__version__) >= version_tuple('1.17'):
with raises(TypeError):
f(x)
else:
with raises(AttributeError):
f(x)
def test_lambdify_matrix():
f = lambdify(x, Matrix([[x, 2*x], [1, 2]]), [{'ImmutableMatrix': numpy.array}, "numpy"])
assert (f(1) == array([[1, 2], [1, 2]])).all()
def test_lambdify_matrix_multi_input():
M = sympy.Matrix([[x**2, x*y, x*z],
[y*x, y**2, y*z],
[z*x, z*y, z**2]])
f = lambdify((x, y, z), M, [{'ImmutableMatrix': numpy.array}, "numpy"])
xh, yh, zh = 1.0, 2.0, 3.0
expected = array([[xh**2, xh*yh, xh*zh],
[yh*xh, yh**2, yh*zh],
[zh*xh, zh*yh, zh**2]])
actual = f(xh, yh, zh)
assert numpy.allclose(actual, expected)
def test_lambdify_matrix_vec_input():
X = sympy.DeferredVector('X')
M = Matrix([
[X[0]**2, X[0]*X[1], X[0]*X[2]],
[X[1]*X[0], X[1]**2, X[1]*X[2]],
[X[2]*X[0], X[2]*X[1], X[2]**2]])
f = lambdify(X, M, [{'ImmutableMatrix': numpy.array}, "numpy"])
Xh = array([1.0, 2.0, 3.0])
expected = array([[Xh[0]**2, Xh[0]*Xh[1], Xh[0]*Xh[2]],
[Xh[1]*Xh[0], Xh[1]**2, Xh[1]*Xh[2]],
[Xh[2]*Xh[0], Xh[2]*Xh[1], Xh[2]**2]])
actual = f(Xh)
assert numpy.allclose(actual, expected)
def test_lambdify_transl():
from sympy.utilities.lambdify import NUMPY_TRANSLATIONS
for sym, mat in NUMPY_TRANSLATIONS.items():
assert sym in sympy.__dict__
assert mat in numpy.__dict__
def test_symarray():
"""Test creation of numpy arrays of SymPy symbols."""
import numpy as np
import numpy.testing as npt
syms = symbols('_0,_1,_2')
s1 = symarray("", 3)
s2 = symarray("", 3)
npt.assert_array_equal(s1, np.array(syms, dtype=object))
assert s1[0] == s2[0]
a = symarray('a', 3)
b = symarray('b', 3)
assert not(a[0] == b[0])
asyms = symbols('a_0,a_1,a_2')
npt.assert_array_equal(a, np.array(asyms, dtype=object))
# Multidimensional checks
a2d = symarray('a', (2, 3))
assert a2d.shape == (2, 3)
a00, a12 = symbols('a_0_0,a_1_2')
assert a2d[0, 0] == a00
assert a2d[1, 2] == a12
a3d = symarray('a', (2, 3, 2))
assert a3d.shape == (2, 3, 2)
a000, a120, a121 = symbols('a_0_0_0,a_1_2_0,a_1_2_1')
assert a3d[0, 0, 0] == a000
assert a3d[1, 2, 0] == a120
assert a3d[1, 2, 1] == a121
def test_vectorize():
assert (numpy.vectorize(
sin)([1, 2, 3]) == numpy.array([sin(1), sin(2), sin(3)])).all()

View File

@ -0,0 +1,176 @@
"""
test_pythonmpq.py
Test the PythonMPQ class for consistency with gmpy2's mpq type. If gmpy2 is
installed run the same tests for both.
"""
from fractions import Fraction
from decimal import Decimal
import pickle
from typing import Callable, List, Tuple, Type
from sympy.testing.pytest import raises
from sympy.external.pythonmpq import PythonMPQ
#
# If gmpy2 is installed then run the tests for both mpq and PythonMPQ.
# That should ensure consistency between the implementation here and mpq.
#
rational_types: List[Tuple[Callable, Type, Callable, Type]]
rational_types = [(PythonMPQ, PythonMPQ, int, int)]
try:
from gmpy2 import mpq, mpz
rational_types.append((mpq, type(mpq(1)), mpz, type(mpz(1))))
except ImportError:
pass
def test_PythonMPQ():
#
# Test PythonMPQ and also mpq if gmpy/gmpy2 is installed.
#
for Q, TQ, Z, TZ in rational_types:
def check_Q(q):
assert isinstance(q, TQ)
assert isinstance(q.numerator, TZ)
assert isinstance(q.denominator, TZ)
return q.numerator, q.denominator
# Check construction from different types
assert check_Q(Q(3)) == (3, 1)
assert check_Q(Q(3, 5)) == (3, 5)
assert check_Q(Q(Q(3, 5))) == (3, 5)
assert check_Q(Q(0.5)) == (1, 2)
assert check_Q(Q('0.5')) == (1, 2)
assert check_Q(Q(Fraction(3, 5))) == (3, 5)
# https://github.com/aleaxit/gmpy/issues/327
if Q is PythonMPQ:
assert check_Q(Q(Decimal('0.6'))) == (3, 5)
# Invalid types
raises(TypeError, lambda: Q([]))
raises(TypeError, lambda: Q([], []))
# Check normalisation of signs
assert check_Q(Q(2, 3)) == (2, 3)
assert check_Q(Q(-2, 3)) == (-2, 3)
assert check_Q(Q(2, -3)) == (-2, 3)
assert check_Q(Q(-2, -3)) == (2, 3)
# Check gcd calculation
assert check_Q(Q(12, 8)) == (3, 2)
# __int__/__float__
assert int(Q(5, 3)) == 1
assert int(Q(-5, 3)) == -1
assert float(Q(5, 2)) == 2.5
assert float(Q(-5, 2)) == -2.5
# __str__/__repr__
assert str(Q(2, 1)) == "2"
assert str(Q(1, 2)) == "1/2"
if Q is PythonMPQ:
assert repr(Q(2, 1)) == "MPQ(2,1)"
assert repr(Q(1, 2)) == "MPQ(1,2)"
else:
assert repr(Q(2, 1)) == "mpq(2,1)"
assert repr(Q(1, 2)) == "mpq(1,2)"
# __bool__
assert bool(Q(1, 2)) is True
assert bool(Q(0)) is False
# __eq__/__ne__
assert (Q(2, 3) == Q(2, 3)) is True
assert (Q(2, 3) == Q(2, 5)) is False
assert (Q(2, 3) != Q(2, 3)) is False
assert (Q(2, 3) != Q(2, 5)) is True
# __hash__
assert hash(Q(3, 5)) == hash(Fraction(3, 5))
# __reduce__
q = Q(2, 3)
assert pickle.loads(pickle.dumps(q)) == q
# __ge__/__gt__/__le__/__lt__
assert (Q(1, 3) < Q(2, 3)) is True
assert (Q(2, 3) < Q(2, 3)) is False
assert (Q(2, 3) < Q(1, 3)) is False
assert (Q(-2, 3) < Q(1, 3)) is True
assert (Q(1, 3) < Q(-2, 3)) is False
assert (Q(1, 3) <= Q(2, 3)) is True
assert (Q(2, 3) <= Q(2, 3)) is True
assert (Q(2, 3) <= Q(1, 3)) is False
assert (Q(-2, 3) <= Q(1, 3)) is True
assert (Q(1, 3) <= Q(-2, 3)) is False
assert (Q(1, 3) > Q(2, 3)) is False
assert (Q(2, 3) > Q(2, 3)) is False
assert (Q(2, 3) > Q(1, 3)) is True
assert (Q(-2, 3) > Q(1, 3)) is False
assert (Q(1, 3) > Q(-2, 3)) is True
assert (Q(1, 3) >= Q(2, 3)) is False
assert (Q(2, 3) >= Q(2, 3)) is True
assert (Q(2, 3) >= Q(1, 3)) is True
assert (Q(-2, 3) >= Q(1, 3)) is False
assert (Q(1, 3) >= Q(-2, 3)) is True
# __abs__/__pos__/__neg__
assert abs(Q(2, 3)) == abs(Q(-2, 3)) == Q(2, 3)
assert +Q(2, 3) == Q(2, 3)
assert -Q(2, 3) == Q(-2, 3)
# __add__/__radd__
assert Q(2, 3) + Q(5, 7) == Q(29, 21)
assert Q(2, 3) + 1 == Q(5, 3)
assert 1 + Q(2, 3) == Q(5, 3)
raises(TypeError, lambda: [] + Q(1))
raises(TypeError, lambda: Q(1) + [])
# __sub__/__rsub__
assert Q(2, 3) - Q(5, 7) == Q(-1, 21)
assert Q(2, 3) - 1 == Q(-1, 3)
assert 1 - Q(2, 3) == Q(1, 3)
raises(TypeError, lambda: [] - Q(1))
raises(TypeError, lambda: Q(1) - [])
# __mul__/__rmul__
assert Q(2, 3) * Q(5, 7) == Q(10, 21)
assert Q(2, 3) * 1 == Q(2, 3)
assert 1 * Q(2, 3) == Q(2, 3)
raises(TypeError, lambda: [] * Q(1))
raises(TypeError, lambda: Q(1) * [])
# __pow__/__rpow__
assert Q(2, 3) ** 2 == Q(4, 9)
assert Q(2, 3) ** 1 == Q(2, 3)
assert Q(-2, 3) ** 2 == Q(4, 9)
assert Q(-2, 3) ** -1 == Q(-3, 2)
if Q is PythonMPQ:
raises(TypeError, lambda: 1 ** Q(2, 3))
raises(TypeError, lambda: Q(1, 4) ** Q(1, 2))
raises(TypeError, lambda: [] ** Q(1))
raises(TypeError, lambda: Q(1) ** [])
# __div__/__rdiv__
assert Q(2, 3) / Q(5, 7) == Q(14, 15)
assert Q(2, 3) / 1 == Q(2, 3)
assert 1 / Q(2, 3) == Q(3, 2)
raises(TypeError, lambda: [] / Q(1))
raises(TypeError, lambda: Q(1) / [])
raises(ZeroDivisionError, lambda: Q(1, 2) / Q(0))
# __divmod__
if Q is PythonMPQ:
raises(TypeError, lambda: Q(2, 3) // Q(1, 3))
raises(TypeError, lambda: Q(2, 3) % Q(1, 3))
raises(TypeError, lambda: 1 // Q(1, 3))
raises(TypeError, lambda: 1 % Q(1, 3))
raises(TypeError, lambda: Q(2, 3) // 1)
raises(TypeError, lambda: Q(2, 3) % 1)

View File

@ -0,0 +1,35 @@
# This testfile tests SymPy <-> SciPy compatibility
# Don't test any SymPy features here. Just pure interaction with SciPy.
# Always write regular SymPy tests for anything, that can be tested in pure
# Python (without scipy). Here we test everything, that a user may need when
# using SymPy with SciPy
from sympy.external import import_module
scipy = import_module('scipy')
if not scipy:
#bin/test will not execute any tests now
disabled = True
from sympy.functions.special.bessel import jn_zeros
def eq(a, b, tol=1e-6):
for x, y in zip(a, b):
if not (abs(x - y) < tol):
return False
return True
def test_jn_zeros():
assert eq(jn_zeros(0, 4, method="scipy"),
[3.141592, 6.283185, 9.424777, 12.566370])
assert eq(jn_zeros(1, 4, method="scipy"),
[4.493409, 7.725251, 10.904121, 14.066193])
assert eq(jn_zeros(2, 4, method="scipy"),
[5.763459, 9.095011, 12.322940, 15.514603])
assert eq(jn_zeros(3, 4, method="scipy"),
[6.987932, 10.417118, 13.698023, 16.923621])
assert eq(jn_zeros(4, 4, method="scipy"),
[8.182561, 11.704907, 15.039664, 18.301255])