def test_implemented_function_evalf(): f = Function('f') f = implemented_function(f, lambda x: x + 1) assert str(f(x)) == "f(x)" assert str(f(2)) == "f(2)" assert f(2).evalf(strict=False) == 3 assert f(x).evalf(strict=False) == f(x) f = implemented_function(Function('sin'), lambda x: x + 1) assert f(2).evalf() != sin(2) del f._imp_ # XXX: due to caching _imp_ would influence all other tests
def test_implemented_function_evalf(): f = Function('f') f = implemented_function(f, lambda x: x + 1) assert str(f(x)) == "f(x)" assert str(f(2)) == "f(2)" assert f(2).evalf(strict=False) == 3 assert f(x).evalf(strict=False) == f(x) f = implemented_function(Function('sin'), lambda x: x + 1) assert f(2).evalf() != sin(2) del f._imp_ # XXX: due to caching _imp_ would influence all other tests
def test_ccode_inline_function(): g = implemented_function('g', Lambda(x, 2 * x)) assert ccode(g(x)) == '2*x' g = implemented_function('g', Lambda(x, 2 * x / Catalan)) assert ccode( g(x)) == 'double const Catalan = %s;\n2*x/Catalan' % Catalan.evalf() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x * (1 + x) * (2 + x))) assert ccode(g(A[i]), assign_to=A[i]) == ('for (int i=0; i<n; i++){\n' ' A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n' '}')
def test_jscode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert jscode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert jscode(g(x)) == "var Catalan = %s;\n2*x/Catalan" % Catalan.n() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert jscode(g(A[i]), assign_to=A[i]) == ( "for (var i=0; i<n; i++){\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}" )
def test_inline_function(): g = implemented_function('g', Lambda(x, 2 * x)) assert fcode(g(x)) == ' 2*x' g = implemented_function('g', Lambda(x, 2 * pi / x)) assert fcode(g(x)) == (' parameter (pi = 3.14159265358979d0)\n' ' 2*pi/x') A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x * (1 + x) * (2 + x))) assert fcode( g(A[i]), assign_to=A[i]) == (' do i = 1, n\n' ' A(i) = (A(i) + 1)*(A(i) + 2)*A(i)\n' ' end do')
def test_ccode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert ccode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert ccode( g(x)) == "double const Catalan = %s;\n2*x/Catalan" % Catalan.evalf() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert ccode(g(A[i]), assign_to=A[i]) == ( "for (int i=0; i<n; i++){\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}" )
def test_jscode_Pow(): g = implemented_function('g', Lambda(x, 2*x)) assert jscode(x**3) == "Math.pow(x, 3)" assert jscode(x**(y**3)) == "Math.pow(x, Math.pow(y, 3))" assert jscode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "Math.pow(3.5*2*x, -x + Math.pow(y, x))/(Math.pow(x, 2) + y)" assert jscode(x**-1.0) == '1/x'
def test_inline_function(): g = implemented_function('g', Lambda(x, 2*x)) assert fcode(g(x)) == " 2*x" g = implemented_function('g', Lambda(x, 2*pi/x)) assert fcode(g(x)) == ( " parameter (pi = 3.14159265358979d0)\n" " 2*pi/x" ) A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert fcode(g(A[i]), assign_to=A[i]) == ( " do i = 1, n\n" " A(i) = (A(i) + 1)*(A(i) + 2)*A(i)\n" " end do" )
def test_lambdify_imps(): # Test lambdify with implemented functions # first test basic (diofant) lambdify f = diofant.cos assert lambdify(x, f(x))(0) == 1 assert lambdify(x, 1 + f(x))(0) == 2 assert lambdify((x, y), y + f(x))(0, 1) == 2 # make an implemented function and test f = implemented_function("f", lambda x: x + 100) assert lambdify(x, f(x))(0) == 100 assert lambdify(x, 1 + f(x))(0) == 101 assert lambdify((x, y), y + f(x))(0, 1) == 101 # Can also handle tuples, lists, dicts as expressions lam = lambdify(x, (f(x), x)) assert lam(3) == (103, 3) lam = lambdify(x, [f(x), x]) assert lam(3) == [103, 3] lam = lambdify(x, [f(x), (f(x), x)]) assert lam(3) == [103, (103, 3)] lam = lambdify(x, {f(x): x}) assert lam(3) == {103: 3} lam = lambdify(x, {f(x): x}) assert lam(3) == {103: 3} lam = lambdify(x, {x: f(x)}) assert lam(3) == {3: 103} # Check that imp preferred to other namespaces by default d = {'f': lambda x: x + 99} lam = lambdify(x, f(x), d) assert lam(3) == 103 # Unless flag passed lam = lambdify(x, f(x), d, use_imps=False) assert lam(3) == 102
def test_lambdify_imps(): # Test lambdify with implemented functions # first test basic (diofant) lambdify f = diofant.cos assert lambdify(x, f(x))(0) == 1 assert lambdify(x, 1 + f(x))(0) == 2 assert lambdify((x, y), y + f(x))(0, 1) == 2 # make an implemented function and test f = implemented_function("f", lambda x: x + 100) assert lambdify(x, f(x))(0) == 100 assert lambdify(x, 1 + f(x))(0) == 101 assert lambdify((x, y), y + f(x))(0, 1) == 101 # Can also handle tuples, lists, dicts as expressions lam = lambdify(x, (f(x), x)) assert lam(3) == (103, 3) lam = lambdify(x, [f(x), x]) assert lam(3) == [103, 3] lam = lambdify(x, [f(x), (f(x), x)]) assert lam(3) == [103, (103, 3)] lam = lambdify(x, {f(x): x}) assert lam(3) == {103: 3} lam = lambdify(x, {f(x): x}) assert lam(3) == {103: 3} lam = lambdify(x, {x: f(x)}) assert lam(3) == {3: 103} # Check that imp preferred to other namespaces by default d = {'f': lambda x: x + 99} lam = lambdify(x, f(x), d) assert lam(3) == 103 # Unless flag passed lam = lambdify(x, f(x), d, use_imps=False) assert lam(3) == 102
def test_Pow(): assert octave_code(x**3) == 'x.^3' assert octave_code(x**(y**3)) == 'x.^(y.^3)' assert octave_code(x**Rational(2, 3)) == 'x.^(2/3)' g = implemented_function('g', Lambda(x, 2 * x)) assert octave_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ '(3.5*2*x).^(-x + y.^x)./(x.^2 + y)'
def test_Pow(): assert mcode(x**3) == "x.^3" assert mcode(x**(y**3)) == "x.^(y.^3)" assert mcode(x**Rational(2, 3)) == 'x.^(2/3)' g = implemented_function('g', Lambda(x, 2*x)) assert mcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)"
def test_imps(): # Here we check if the default returned functions are anonymous - in # the sense that we can have more than one function with the same name f = implemented_function('f', lambda x: 2*x) g = implemented_function('f', lambda x: math.sqrt(x)) l1 = lambdify(x, f(x)) l2 = lambdify(x, g(x)) assert str(f(x)) == str(g(x)) assert l1(3) == 6 assert l2(3) == math.sqrt(3) # check that we can pass in a Function as input func = diofant.Function('myfunc') assert not hasattr(func, '_imp_') my_f = implemented_function(func, lambda x: 2*x) assert hasattr(func, '_imp_') and hasattr(my_f, '_imp_') # Error for functions with same name and different implementation f2 = implemented_function("f", lambda x: x + 101) pytest.raises(ValueError, lambda: lambdify(x, f(f2(x))))
def test_implemented_function_evalf(): from diofant.utilities.lambdify import implemented_function f = Function('f') f = implemented_function(f, lambda x: x + 1) assert str(f(x)) == "f(x)" assert str(f(2)) == "f(2)" assert f(2).evalf() == 3 assert f(x).evalf() == f(x) del f._imp_ # XXX: due to caching _imp_ would influence all other tests
def test_numexpr_userfunctions(): a, b = numpy.random.randn(2, 10) uf = type('uf', (Function, ), {'eval': classmethod(lambda x, y: y**2 + 1)}) func = lambdify(x, 1 - uf(x), modules='numexpr') assert numpy.allclose(func(a), -(a**2)) uf = implemented_function(Function('uf'), lambda x, y: 2 * x * y + 1) func = lambdify((x, y), uf(x, y), modules='numexpr') assert numpy.allclose(func(a, b), 2 * a * b + 1)
def test_imps(): # Here we check if the default returned functions are anonymous - in # the sense that we can have more than one function with the same name f = implemented_function('f', lambda x: 2*x) g = implemented_function('f', lambda x: math.sqrt(x)) l1 = lambdify(x, f(x)) l2 = lambdify(x, g(x)) assert str(f(x)) == str(g(x)) assert l1(3) == 6 assert l2(3) == math.sqrt(3) # check that we can pass in a Function as input func = diofant.Function('myfunc') assert not hasattr(func, '_imp_') my_f = implemented_function(func, lambda x: 2*x) assert hasattr(func, '_imp_') # Error for functions with same name and different implementation f2 = implemented_function("f", lambda x: x + 101) pytest.raises(ValueError, lambda: lambdify(x, f(f2(x))))
def test_numexpr_userfunctions(): a, b = numpy.random.randn(2, 10) uf = type('uf', (Function, ), {'eval': classmethod(lambda x, y: y**2+1)}) func = lambdify(x, 1-uf(x), modules='numexpr') assert numpy.allclose(func(a), -(a**2)) uf = implemented_function(Function('uf'), lambda x, y: 2*x*y+1) func = lambdify((x, y), uf(x, y), modules='numexpr') assert numpy.allclose(func(a, b), 2*a*b+1)
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" g = implemented_function('g', Lambda(x, 2 * x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)'
def test_imps_errors(): # Test errors that implemented functions can return, and still be # able to form expressions. See issue sympy/sympy#10810. for val, error_class in product((0, 0., 2, 2.0), (AttributeError, TypeError, ValueError)): def myfunc(a): if a == 0: raise error_class return 1 f = implemented_function('f', myfunc) expr = f(val) assert expr == f(val)
def test_imps_errors(): # Test errors that implemented functions can return, and still be # able to form expressions. See issue sympy/sympy#10810. for val, error_class in product((0, 0., 2, 2.0), (AttributeError, TypeError, ValueError)): def myfunc(a): if a == 0: raise error_class return 1 f = implemented_function('f', myfunc) expr = f(val) assert expr == f(val)
def test_numexprprinter(): p = NumExprPrinter() M = MatrixSymbol('M', 1, 2) pytest.raises(TypeError, lambda: p.doprint(M)) pytest.raises(TypeError, lambda: p.doprint([x, y])) assert p.doprint(I) == "evaluate('1j')" assert p.doprint(sin(x)) == "evaluate('sin(x)')" assert p.doprint(asinh(x)) == "evaluate('arcsinh(x)')" f = implemented_function('f', lambda x: 2 * x) assert p.doprint(f(x)) == "evaluate('(2*x)')" g = Function('g') pytest.raises(TypeError, lambda: p.doprint(g(x)))
def test_numexprprinter(): p = NumExprPrinter() M = MatrixSymbol('M', 1, 2) pytest.raises(TypeError, lambda: p.doprint(M)) pytest.raises(TypeError, lambda: p.doprint([x, y])) assert p.doprint(I) == "evaluate('1j')" assert p.doprint(sin(x)) == "evaluate('sin(x)')" assert p.doprint(asinh(x)) == "evaluate('arcsinh(x)')" f = implemented_function('f', lambda x: 2*x) assert p.doprint(f(x)) == "evaluate('(2*x)')" g = Function('g') pytest.raises(TypeError, lambda: p.doprint(g(x)))
def test_ccode_Pow(): assert ccode(x**3) == 'pow(x, 3)' assert ccode(x**(y**3)) == 'pow(x, pow(y, 3))' g = implemented_function('g', Lambda(x, 2*x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ 'pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)' assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, 'dpowi'), (lambda base, exp: not exp.is_integer, 'pow')] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)' _cond_cfunc2 = [(lambda base, exp: base == 2, lambda base, exp: f'exp2({exp})'), (lambda base, exp: base != 2, 'pow')] # Related to sympy/sympy#11353 assert ccode(2**x, user_functions={'Pow': _cond_cfunc2}) == 'exp2(x)' assert ccode(x**2, user_functions={'Pow': _cond_cfunc2}) == 'pow(x, 2)'
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" g = implemented_function('g', Lambda(x, 2*x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)' _cond_cfunc2 = [(lambda base, exp: base == 2, lambda base, exp: 'exp2(%s)' % exp), (lambda base, exp: base != 2, 'pow')] # Related to sympy/sympy#11353 assert ccode(2**x, user_functions={'Pow': _cond_cfunc2}) == 'exp2(x)' assert ccode(x**2, user_functions={'Pow': _cond_cfunc2}) == 'pow(x, 2)'
def binary_function(symfunc, expr, **kwargs): """Returns a diofant function with expr as binary implementation This is a convenience function that automates the steps needed to autowrap the Diofant expression and attaching it to a Function object with implemented_function(). >>> from diofant.abc import x, y >>> from diofant.utilities.autowrap import binary_function >>> expr = ((x - y)**(25)).expand() >>> f = binary_function('f', expr) >>> type(f) <class 'diofant.core.function.UndefinedFunction'> >>> 2*f(x, y) 2*f(x, y) >>> f(x, y).evalf(2, subs={x: 1, y: 2}) -1.0 """ binary = autowrap(expr, **kwargs) return implemented_function(symfunc, binary)
def test_inline_function(): n, m = symbols('n m', integer=True) A, x, y = map(IndexedBase, 'Axy') i = Idx('i', m) p = FCodeGen() func = implemented_function('func', Lambda(n, n*(n + 1))) routine = make_routine('test_inline', Eq(y[i], func(x[i]))) code = get_string(p.dump_f95, [routine]) expected = ( 'subroutine test_inline(m, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'REAL*8, intent(in), dimension(1:m) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'do i = 1, m\n' ' y(i) = %s*%s\n' 'end do\n' 'end subroutine\n' ) args = ('x(i)', '(x(i) + 1)') assert code == expected % args or\ code == expected % args[::-1]
def test_imps_wrong_args(): pytest.raises(ValueError, lambda: implemented_function(sin, lambda x: x))
def test_imps_wrong_args(): pytest.raises(ValueError, lambda: implemented_function(sin, lambda x: x))
def ufuncify(args, expr, language=None, backend='numpy', tempdir=None, flags=None, verbose=False, helpers=None): """ Generates a binary function that supports broadcasting on numpy arrays. Parameters ---------- args : iterable Either a Symbol or an iterable of symbols. Specifies the argument sequence for the function. expr A Diofant expression that defines the element wise operation. language : string, optional If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If ``None`` [default], the language is inferred based upon the specified backend. backend : string, optional Backend used to wrap the generated code. Either 'numpy' [default], 'cython', or 'f2py'. tempdir : string, optional Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path. flags : iterable, optional Additional option flags that will be passed to the backend verbose : bool, optional If True, autowrap will not mute the command line backends. This can be helpful for debugging. helpers : iterable, optional Used to define auxillary expressions needed for the main expr. If the main expression needs to call a specialized function it should be put in the ``helpers`` iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be tuples with (<funtion_name>, <diofant_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines. Notes ----- The default backend ('numpy') will create actual instances of ``numpy.ufunc``. These support ndimensional broadcasting, and implicit type conversion. Use of the other backends will result in a "ufunc-like" function, which requires equal length 1-dimensional arrays for all arguments, and will not perform any type conversions. References ---------- .. [1] http://docs.scipy.org/doc/numpy/reference/ufuncs.html Examples -------- >>> from diofant.utilities.autowrap import ufuncify >>> from diofant.abc import x, y >>> import numpy as np >>> f = ufuncify((x, y), y + x**2) >>> type(f) is np.ufunc True >>> f([1, 2, 3], 2) array([ 3., 6., 11.]) >>> f(np.arange(5), 3) array([ 3., 4., 7., 12., 19.]) For the F2Py and Cython backends, inputs are required to be equal length 1-dimensional arrays. The F2Py backend will perform type conversion, but the Cython backend will error if the inputs are not of the expected type. >>> f_fortran = ufuncify((x, y), y + x**2, backend='F2Py') >>> f_fortran(1, 2) 3 >>> f_fortran(numpy.array([1, 2, 3]), numpy.array([1.0, 2.0, 3.0])) array([2., 6., 12.]) >>> f_cython = ufuncify((x, y), y + x**2, backend='Cython') >>> f_cython(1, 2) Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(numpy.array([1.0]), numpy.array([2.0])) array([ 3.]) """ if isinstance(args, (Dummy, Symbol)): args = (args, ) else: args = tuple(args) if language: _validate_backend_language(backend, language) else: language = _infer_language(backend) helpers = helpers if helpers else () flags = flags if flags else () if backend.upper() == 'NUMPY': routine = make_routine('autofunc', expr, args) helps = [] for name, expr, args in helpers: helps.append(make_routine(name, expr, args)) code_wrapper = UfuncifyCodeWrapper(CCodeGen("ufuncify"), tempdir, flags, verbose) return code_wrapper.wrap_code(routine, helpers=helps) else: # Dummies are used for all added expressions to prevent name clashes # within the original expression. y = IndexedBase(Dummy()) m = Dummy(integer=True) i = Idx(Dummy(integer=True), m) f = implemented_function(Dummy().name, Lambda(args, expr)) # For each of the args create an indexed version. indexed_args = [IndexedBase(Dummy(str(a))) for a in args] # Order the arguments (out, args, dim) args = [y] + indexed_args + [m] args_with_indices = [a[i] for a in indexed_args] return autowrap(Eq(y[i], f(*args_with_indices)), language, backend, tempdir, tuple(args), flags, verbose, helpers)
def test_sympyissue_12092(): f = implemented_function('f', lambda x: x**2) assert f(f(2)).evalf() == Float(16)