def test_function(): c_src1 = "void fun1()" + "\n" + "{" + "\n" + "int a;" + "\n" + "}" c_src2 = ("int fun2()" + "\n" + "{" + "\n" + "int a;" + "\n" + "return a;" + "\n" + "}") c_src3 = ("float fun3()" + "\n" + "{" + "\n" + "float b;" + "\n" + "return b;" + "\n" + "}") c_src4 = "float fun4()" + "\n" + "{}" res1 = SymPyExpression(c_src1, "c").return_expr() res2 = SymPyExpression(c_src2, "c").return_expr() res3 = SymPyExpression(c_src3, "c").return_expr() res4 = SymPyExpression(c_src4, "c").return_expr() assert res1[0] == FunctionDefinition( NoneToken(), name=String("fun1"), parameters=(), body=CodeBlock( Declaration( Variable( Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0), ))), ) assert res2[0] == FunctionDefinition( IntBaseType(String("integer")), name=String("fun2"), parameters=(), body=CodeBlock( Declaration( Variable( Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0), )), Return("a"), ), ) assert res3[0] == FunctionDefinition( FloatBaseType(String("real")), name=String("fun3"), parameters=(), body=CodeBlock( Declaration( Variable( Symbol("b"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), )), Return("b"), ), ) assert res4[0] == FunctionPrototype(FloatBaseType(String("real")), name=String("fun4"), parameters=())
def test_parameters(): c_src1 = ('void fun1( int a)' + '\n' + '{' + '\n' + 'int i;' + '\n' + '}') c_src2 = ('int fun2(float x, float y)' + '\n' + '{' + '\n' + 'int a;' + '\n' + 'return a;' + '\n' + '}') c_src3 = ('float fun3(int p, float q, int r)' + '\n' + '{' + '\n' + 'float b;' + '\n' + 'return b;' + '\n' + '}') res1 = SymPyExpression(c_src1, 'c').return_expr() res2 = SymPyExpression(c_src2, 'c').return_expr() res3 = SymPyExpression(c_src3, 'c').return_expr() assert res1[0] == FunctionDefinition( NoneToken(), name=String('fun1'), parameters=(Variable(Symbol('a'), type=IntBaseType(String('integer')), value=Integer(0)), ), body=CodeBlock( Declaration( Variable(Symbol('i'), type=IntBaseType(String('integer')), value=Integer(0))))) assert res2[0] == FunctionDefinition( IntBaseType(String('integer')), name=String('fun2'), parameters=(Variable(Symbol('x'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53)), Variable(Symbol('y'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53))), body=CodeBlock( Declaration( Variable(Symbol('a'), type=IntBaseType(String('integer')), value=Integer(0))), Return('a'))) assert res3[0] == FunctionDefinition( FloatBaseType(String('real')), name=String('fun3'), parameters=(Variable(Symbol('p'), type=IntBaseType(String('integer')), value=Integer(0)), Variable(Symbol('q'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53)), Variable(Symbol('r'), type=IntBaseType(String('integer')), value=Integer(0))), body=CodeBlock( Declaration( Variable(Symbol('b'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53))), Return('b')))
def test_size_assumed_shape(): if not has_fortran(): skip("No fortran compiler found.") a = Symbol("a", real=True) body = [Return((sum_(a**2) / size(a))**0.5)] arr = array(a, dim=[":"], intent="in") fd = FunctionDefinition(real, "rms", [arr], body) render_as_module([fd], "mod_rms") (stdout, stderr), info = compile_run_strings( [ ("rms.f90", render_as_module([fd], "mod_rms")), ( "main.f90", ("program myprog\n" "use mod_rms, only: rms\n" "real*8, dimension(4), parameter :: x = [4, 2, 2, 2]\n" "print *, dsqrt(7d0) - rms(x)\n" "end program\n"), ), ], clean=True, ) assert "0.00000" in stdout assert stderr == "" assert info["exit_status"] == os.EX_OK
def newtons_method_function(expr, wrt, params=None, func_name="newton", attrs=Tuple(), **kwargs): """ Generates an AST for a function implementing the Newton-Raphson method. Parameters ========== expr : expression wrt : Symbol With respect to, i.e. what is the variable params : iterable of symbols Symbols appearing in expr that are taken as constants during the iterations (these will be accepted as parameters to the generated function). func_name : str Name of the generated function. attrs : Tuple Attribute instances passed as ``attrs`` to ``FunctionDefinition``. \\*\\*kwargs : Keyword arguments passed to :func:`sympy.codegen.algorithms.newtons_method`. Examples ======== >>> from sympy import symbols, cos >>> from sympy.codegen.algorithms import newtons_method_function >>> from sympy.codegen.pyutils import render_as_module >>> from sympy.core.compatibility import exec_ >>> x = symbols('x') >>> expr = cos(x) - x**3 >>> func = newtons_method_function(expr, x) >>> py_mod = render_as_module(func) # source code as string >>> namespace = {} >>> exec_(py_mod, namespace, namespace) >>> res = eval('newton(0.5)', namespace) >>> abs(res - 0.865474033102) < 1e-12 True See Also ======== sympy.codegen.algorithms.newtons_method """ if params is None: params = (wrt,) pointer_subs = {p.symbol: Symbol('(*%s)' % p.symbol.name) for p in params if isinstance(p, Pointer)} delta = kwargs.pop('delta', None) if delta is None: delta = Symbol('d_' + wrt.name) if expr.has(delta): delta = None # will use Dummy algo = newtons_method(expr, wrt, delta=delta, **kwargs).xreplace(pointer_subs) if isinstance(algo, Scope): algo = algo.body not_in_params = expr.free_symbols.difference(set(_symbol_of(p) for p in params)) if not_in_params: raise ValueError("Missing symbols in params: %s" % ', '.join(map(str, not_in_params))) declars = tuple(Variable(p, real) for p in params) body = CodeBlock(algo, Return(wrt)) return FunctionDefinition(real, func_name, declars, body, attrs=attrs)
def test_FunctionPrototype_and_FunctionDefinition(): vx = Variable(x, type=real) vn = Variable(n, type=integer) fp1 = FunctionPrototype(real, 'power', [vx, vn]) assert fp1.return_type == real assert fp1.name == String('power') assert fp1.parameters == Tuple(vx, vn) assert fp1 == FunctionPrototype(real, 'power', [vx, vn]) assert fp1 != FunctionPrototype(real, 'power', [vn, vx]) assert fp1.func(*fp1.args) == fp1 body = [Assignment(x, x**n), Return(x)] fd1 = FunctionDefinition(real, 'power', [vx, vn], body) assert fd1.return_type == real assert str(fd1.name) == 'power' assert fd1.parameters == Tuple(vx, vn) assert fd1.body == CodeBlock(*body) assert fd1 == FunctionDefinition(real, 'power', [vx, vn], body) assert fd1 != FunctionDefinition(real, 'power', [vx, vn], body[::-1]) assert fd1.func(*fd1.args) == fd1 fp2 = FunctionPrototype.from_FunctionDefinition(fd1) assert fp2 == fp1 fd2 = FunctionDefinition.from_FunctionPrototype(fp1, body) assert fd2 == fd1
def test_bind_C(): if not has_fortran(): skip("No fortran compiler found.") if not cython: skip("Cython not found.") if not np: skip("NumPy not found.") a = Symbol('a', real=True) s = Symbol('s', integer=True) body = [Return((sum_(a**2) / s)**.5)] arr = array(a, dim=[s], intent='in') fd = FunctionDefinition(real, 'rms', [arr, s], body, attrs=[bind_C('rms')]) f_mod = render_as_module([fd], 'mod_rms') with TemporaryDirectory() as folder: mod, info = compile_link_import_strings( [('rms.f90', f_mod), ('_rms.pyx', ("#cython: language_level={}\n".format("3") + "cdef extern double rms(double*, int*)\n" "def py_rms(double[::1] x):\n" " cdef int s = x.size\n" " return rms(&x[0], &s)\n"))], build_dir=folder) assert abs(mod.py_rms(np.array([2., 4., 2., 2.])) - 7**0.5) < 1e-14
def test_ccode_codegen_ast(): assert ccode(Comment("this is a comment")) == "// this is a comment" assert ccode(While(abs(x) > 1, [aug_assign(x, '-', 1)])) == ('while (fabs(x) > 1) {\n' ' x -= 1;\n' '}') assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ('{\n' ' x += 1;\n' '}') inp_x = Declaration(Variable(x, type=real)) assert ccode(FunctionPrototype(real, 'pwer', [inp_x])) == 'double pwer(double x)' assert ccode( FunctionDefinition( real, 'pwer', [inp_x], [Assignment(x, x**2)])) == ('double pwer(double x){\n' ' x = pow(x, 2);\n' '}') # Elements of CodeBlock are formatted as statements: block = CodeBlock( x, Print([x, y], "%d %d"), FunctionCall('pwer', [x]), Return(x), ) assert ccode(block) == '\n'.join([ 'x;', 'printf("%d %d", x, y);', 'pwer(x);', 'return x;', ])
def test_function(): c_src1 = ('void fun1()' + '\n' + '{' + '\n' + 'int a;' + '\n' + '}') c_src2 = ('int fun2()' + '\n' + '{' + '\n' + 'int a;' + '\n' + 'return a;' + '\n' + '}') c_src3 = ('float fun3()' + '\n' + '{' + '\n' + 'float b;' + '\n' + 'return b;' + '\n' + '}') c_src4 = ('float fun4()' + '\n' + '{}') res1 = SymPyExpression(c_src1, 'c').return_expr() res2 = SymPyExpression(c_src2, 'c').return_expr() res3 = SymPyExpression(c_src3, 'c').return_expr() res4 = SymPyExpression(c_src4, 'c').return_expr() assert res1[0] == FunctionDefinition( NoneToken(), name=String('fun1'), parameters=(), body=CodeBlock( Declaration( Variable(Symbol('a'), type=IntBaseType(String('integer')), value=Integer(0))))) assert res2[0] == FunctionDefinition( IntBaseType(String('integer')), name=String('fun2'), parameters=(), body=CodeBlock( Declaration( Variable(Symbol('a'), type=IntBaseType(String('integer')), value=Integer(0))), Return('a'))) assert res3[0] == FunctionDefinition( FloatBaseType(String('real')), name=String('fun3'), parameters=(), body=CodeBlock( Declaration( Variable(Symbol('b'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53))), Return('b'))) assert res4[0] == FunctionPrototype(FloatBaseType(String('real')), name=String('fun4'), parameters=())
def test_FunctionDefinition_print(): x = symbols('x') n = symbols('n', integer=True) vx = Variable(x, type=real) vn = Variable(n, type=integer) body = [Assignment(x, x**n), Return(x)] fd1 = FunctionDefinition(real, 'power', [vx, vn], body) # Should be changed to proper test once multi-line generation is working # see https://github.com/sympy/sympy/issues/15824 raises(NotImplementedError, lambda: fcode(fd1))
def test_function(): src1 = """\ integer function f(a,b) integer :: x, y f = x + y end function """ expr1.convert_to_expr(src1, "f") for iter in expr1.return_expr(): assert isinstance(iter, FunctionDefinition) assert iter == FunctionDefinition( IntBaseType(String("integer")), name=String("f"), parameters=(Variable(Symbol("a")), Variable(Symbol("b"))), body=CodeBlock( Declaration( Variable( Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0), ) ), Declaration( Variable( Symbol("b"), type=IntBaseType(String("integer")), value=Integer(0), ) ), Declaration( Variable( Symbol("f"), type=IntBaseType(String("integer")), value=Integer(0), ) ), Declaration( Variable( Symbol("x"), type=IntBaseType(String("integer")), value=Integer(0), ) ), Declaration( Variable( Symbol("y"), type=IntBaseType(String("integer")), value=Integer(0), ) ), Assignment(Variable(Symbol("f")), Add(Symbol("x"), Symbol("y"))), Return(Variable(Symbol("f"))), ), )
def test_ccode_codegen_ast(): assert ccode(Comment("this is a comment")) == "// this is a comment" assert ccode(While(abs(x) > 1, [aug_assign(x, "-", 1)])) == ( "while (fabs(x) > 1) {\n" " x -= 1;\n" "}" ) assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ("{\n" " x += 1;\n" "}") inp_x = Declaration(Variable(x, type=real)) assert ccode(FunctionPrototype(real, "pwer", [inp_x])) == "double pwer(double x)" assert ccode( FunctionDefinition(real, "pwer", [inp_x], [Assignment(x, x ** 2)]) ) == ("double pwer(double x){\n" " x = pow(x, 2);\n" "}") # Elements of CodeBlock are formatted as statements: block = CodeBlock(x, Print([x, y], "%d %d"), FunctionCall("pwer", [x]), Return(x),) assert ccode(block) == "\n".join( ["x;", 'printf("%d %d", x, y);', "pwer(x);", "return x;",] )
def test_numexpr(): # test ITE rewrite as Piecewise from sympy.logic.boolalg import ITE expr = ITE(x > 0, True, False, evaluate=False) assert NumExprPrinter().doprint(expr) == \ "numexpr.evaluate('where((x > 0), True, False)', truediv=True)" from sympy.codegen.ast import Return, FunctionDefinition, Variable, Assignment func_def = FunctionDefinition( None, 'foo', [Variable(x)], [Assignment(y, x), Return(y**2)]) print("") print(NumExprPrinter().doprint(func_def)) expected = "def foo(x):\n"\ " y = numexpr.evaluate('x', truediv=True)\n"\ " return numexpr.evaluate('y**2', truediv=True)" print(expected) assert NumExprPrinter().doprint(func_def) == expected
def visit_Function(self, node): """Visitor Function for function Definitions Visits each function definition present in the ASR and creates a function definition node in the Python AST with all the elements of the given function The functions declare all the variables required as SymPy symbols in the function before the function definition This function also the call_visior_function to parse the contents of the function body """ # TODO: Return statement, variable declaration fn_args = [] fn_body = [] fn_name = node.name for arg_iter in node.args: fn_args.append(Variable(arg_iter.name)) for i in node.body: fn_ast = call_visitor(i) try: fn_body_expr = fn_ast except UnboundLocalError: fn_body_expr = [] for sym in node.symtab.symbols: decl = call_visitor(node.symtab.symbols[sym]) for symbols in decl: fn_body.append(symbols) for elem in fn_body_expr: fn_body.append(elem) fn_body.append(Return(Variable(node.return_var.name))) if isinstance(node.return_var.type, asr.Integer): ret_type = IntBaseType(String('integer')) elif isinstance(node.return_var.type, asr.Real): ret_type = FloatBaseType(String('real')) else: raise NotImplementedError("Data type not supported") new_node = FunctionDefinition(return_type=ret_type, name=fn_name, parameters=fn_args, body=fn_body) self._py_ast.append(new_node)
def test_Module(): x = Symbol('x', real=True) v_x = Variable.deduced(x) sq = FunctionDefinition(real, 'sqr', [v_x], [Return(x**2)]) mod_sq = Module('mod_sq', [], [sq]) sq_call = FunctionCall('sqr', [42.]) prg_sq = Program( 'foobar', [use('mod_sq', only=['sqr']), Print(['"Square of 42 = "', sq_call])]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings( [('mod_sq.f90', fcode(mod_sq, standard=90)), ('main.f90', fcode(prg_sq, standard=90))], clean=True) assert '42' in stdout assert str(42**2) in stdout assert stderr == ''
def test_size_assumed_shape(): if not has_fortran(): skip("No fortran compiler found.") a = Symbol('a', real=True) body = [Return((sum_(a**2) / size(a))**.5)] arr = array(a, dim=[':'], intent='in') fd = FunctionDefinition(real, 'rms', [arr], body) render_as_module([fd], 'mod_rms') (stdout, stderr), info = compile_run_strings( [('rms.f90', render_as_module([fd], 'mod_rms')), ('main.f90', ('program myprog\n' 'use mod_rms, only: rms\n' 'real*8, dimension(4), parameter :: x = [4, 2, 2, 2]\n' 'print *, dsqrt(7d0) - rms(x)\n' 'end program\n'))], clean=True) assert '0.00000' in stdout assert stderr == '' assert info['exit_status'] == os.EX_OK
def test_Module(): x = Symbol("x", real=True) v_x = Variable.deduced(x) sq = FunctionDefinition(real, "sqr", [v_x], [Return(x**2)]) mod_sq = Module("mod_sq", [], [sq]) sq_call = FunctionCall("sqr", [42.0]) prg_sq = Program( "foobar", [use("mod_sq", only=["sqr"]), Print(['"Square of 42 = "', sq_call])]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings( [ ("mod_sq.f90", fcode(mod_sq, standard=90)), ("main.f90", fcode(prg_sq, standard=90)), ], clean=True, ) assert "42" in stdout assert str(42**2) in stdout assert stderr == ""
def test_ccode_codegen_ast(): # Note that C only allows comments of the form /* ... */, double forward # slash is not standard C, and some C compilers will grind to a halt upon # encountering them. assert ccode( Comment("this is a comment")) == "/* this is a comment */" # not // assert ccode(While(abs(x) > 1, [aug_assign(x, '-', 1)])) == ('while (fabs(x) > 1) {\n' ' x -= 1;\n' '}') assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ('{\n' ' x += 1;\n' '}') inp_x = Declaration(Variable(x, type=real)) assert ccode(FunctionPrototype(real, 'pwer', [inp_x])) == 'double pwer(double x)' assert ccode( FunctionDefinition( real, 'pwer', [inp_x], [Assignment(x, x**2)])) == ('double pwer(double x){\n' ' x = pow(x, 2);\n' '}') # Elements of CodeBlock are formatted as statements: block = CodeBlock( x, Print([x, y], "%d %d"), FunctionCall('pwer', [x]), Return(x), ) assert ccode(block) == '\n'.join([ 'x;', 'printf("%d %d", x, y);', 'pwer(x);', 'return x;', ])
def test_parameters(): c_src1 = "void fun1( int a)" + "\n" + "{" + "\n" + "int i;" + "\n" + "}" c_src2 = ("int fun2(float x, float y)" + "\n" + "{" + "\n" + "int a;" + "\n" + "return a;" + "\n" + "}") c_src3 = ("float fun3(int p, float q, int r)" + "\n" + "{" + "\n" + "float b;" + "\n" + "return b;" + "\n" + "}") res1 = SymPyExpression(c_src1, "c").return_expr() res2 = SymPyExpression(c_src2, "c").return_expr() res3 = SymPyExpression(c_src3, "c").return_expr() assert res1[0] == FunctionDefinition( NoneToken(), name=String("fun1"), parameters=(Variable(Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0)), ), body=CodeBlock( Declaration( Variable( Symbol("i"), type=IntBaseType(String("integer")), value=Integer(0), ))), ) assert res2[0] == FunctionDefinition( IntBaseType(String("integer")), name=String("fun2"), parameters=( Variable( Symbol("x"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), ), Variable( Symbol("y"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), ), ), body=CodeBlock( Declaration( Variable( Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0), )), Return("a"), ), ) assert res3[0] == FunctionDefinition( FloatBaseType(String("real")), name=String("fun3"), parameters=( Variable(Symbol("p"), type=IntBaseType(String("integer")), value=Integer(0)), Variable( Symbol("q"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), ), Variable(Symbol("r"), type=IntBaseType(String("integer")), value=Integer(0)), ), body=CodeBlock( Declaration( Variable( Symbol("b"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), )), Return("b"), ), )
def test_Return(): rs = Return(x) assert rs.args == (x, ) assert rs == Return(x) assert rs != Return(y) assert rs.func(*rs.args) == rs
def transform_return_stmt(self, node): """Returns the Return Node for a return statement""" return Return(next(node.get_children()).spelling)
def test_Return(): rs = Return(x) assert rs.args == (x,) assert rs == Return(x) assert rs != Return(y) assert rs.func(*rs.args) == rs