def test_FunctionCall(): fc = FunctionCall('power', (x, 3)) assert fc.function_args[0] == x assert fc.function_args[1] == 3 assert isinstance(fc.function_args[1], Integer) assert fc == FunctionCall('power', (x, 3)) assert fc != FunctionCall('power', (3, x)) assert fc != FunctionCall('Power', (x, 3)) assert fc.func(*fc.args) == fc
def ubound(array, dim=None, kind=None): return FunctionCall( 'ubound', [_printable(array)] + ([_printable(dim)] if dim else []) + ([_printable(kind)] if kind else []) )
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 lbound(array, dim=None, kind=None): """ Creates an AST node for a function call to Fortran's "lbound(...)" Parameters ========== array : Symbol or String dim : expr kind : expr Examples ======== >>> from sympy.printing import fcode >>> from sympy.codegen.fnodes import lbound >>> lb = lbound('arr', dim=2) >>> fcode(lb, source_format='free') 'lbound(arr, 2)' """ return FunctionCall( 'lbound', [_printable(array)] + ([_printable(dim)] if dim else []) + ([_printable(kind)] if kind else []) )
def size(array, dim=None, kind=None): """ Creates an AST node for a function call to Fortran's "size(...)" Examples ======== >>> from sympy import Symbol >>> from sympy.printing import fcode >>> from sympy.codegen.ast import FunctionDefinition, real, Return, Variable >>> from sympy.codegen.fnodes import array, sum_, size >>> 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) >>> print(fcode(fd, source_format='free', standard=2003)) real*8 function rms(a) real*8, dimension(:), intent(in) :: a rms = sqrt(sum(a**2)*1d0/size(a)) end function """ return FunctionCall( 'size', [_printable(array)] + ([_printable(dim)] if dim else []) + ([_printable(kind)] if kind else []) )
def allocated(array): """ Creates an AST node for a function call to Fortran's "allocated(...)" Examples ======== >>> from sympy.printing import fcode >>> from sympy.codegen.fnodes import allocated >>> alloc = allocated('x') >>> fcode(alloc, source_format='free') 'allocated(x)' """ return FunctionCall('allocated', [_printable(array)])
def sizeof(arg): """ Generate of FunctionCall instance for calling 'sizeof' Examples ======== >>> from sympy.codegen.ast import real >>> from sympy.codegen.cnodes import sizeof >>> from sympy.printing.ccode import ccode >>> ccode(sizeof(real)) 'sizeof(double)' """ return FunctionCall('sizeof', [String(arg) if isinstance(arg, string_types) else arg])
def reshape(source, shape, pad=None, order=None): """ Creates an AST node for a function call to Fortran's "reshape(...)" Parameters ========== source : Symbol or String shape : ArrayExpr """ return FunctionCall( 'reshape', [_printable(source), _printable(shape)] + ([_printable(pad)] if pad else []) + ([_printable(order)] if pad else []))
def setup_codegen(self): args_var = Pointer("Args") block = self.kernel_arg_local_assign(args_var) if self._kernel_dims == 1: last_first = Variable("Sz", type=uint32) block.append( AssignmentEx(Declaration(last_first), Symbol("W") * Symbol("H"))) elif self._kernel_dims == 2: last_first = Variable("H", type=uint32) elif self._kernel_dims == 3: last_first = Variable("InFeatures", type=uint32) else: raise ValueError("expression has too many dimensions") var_chunk = Variable("Chunk", type=uint32) var_first = Variable("First", type=uint32) var_last = Variable("Last", type=uint32) var_coreid = Variable("CoreId", type=uint32) # unsigned int CoreId = gap_coreid(); block.append( AssignmentEx(Declaration(var_coreid), FunctionCall("gap_coreid", []))) # unsigned int Chunk = ChunkSize(OutFeatures); block.append( AssignmentEx(Declaration(var_chunk), FunctionCall("ChunkSize", [last_first]))) # unsigned int First = Chunk*CoreId; block.append( AssignmentEx(Declaration(var_first), Symbol("Chunk") * Symbol("CoreId"))) # unsigned int Last = Min(First+Chunk, OutFeatures); block.append( AssignmentEx( Declaration(var_last), FunctionCall("gap_min", [Symbol("First") + Symbol("Chunk"), last_first]))) return block
def test_FunctionCall(): fc = FunctionCall('power', (x, 3)) assert fc.function_args[0] == x assert fc.function_args[1] == 3 assert isinstance(fc.function_args[1], Integer) assert fc == FunctionCall('power', (x, 3)) assert fc != FunctionCall('power', (3, x)) assert fc != FunctionCall('Power', (x, 3)) assert fc.func(*fc.args) == fc
def transform_call_expr(self, node): """Transformation function for a call expression Used to create function call nodes for the function calls present in the C code Returns ======= FunctionCall : Codegen AST Node FunctionCall node with parameters if any parameters are present """ param = [] children = node.get_children() child = next(children) while child.kind == cin.CursorKind.NAMESPACE_REF: child = next(children) while child.kind == cin.CursorKind.TYPE_REF: child = next(children) first_child = self.transform(child) try: for child in children: arg = self.transform(child) if (child.kind == cin.CursorKind.INTEGER_LITERAL): param.append(Integer(arg)) elif (child.kind == cin.CursorKind.FLOATING_LITERAL): param.append(Float(arg)) else: param.append(arg) return FunctionCall(first_child, param) except StopIteration: return FunctionCall(first_child)
def gen_kernel_model(self, kernel_name, kernel_arg_type_name): member_types = { "int32": lambda x: (QuotedString("int"), QuotedString(x)), "uint32": lambda x: (QuotedString("unsigned int"), QuotedString(x)), "pint8": lambda x: (QuotedString("signed char *"), QuotedString(x)) } kernel_args = self.kernel_args code_block = CodeBlock( FunctionCall("LibKernelTemplate", (QuotedString(kernel_arg_type_name), FunctionCall( "CArgs", tuple([Integer(len(kernel_args))] + [ FunctionCall( "TCArg", member_types[kernel_arg[1]] (kernel_arg[0])) for kernel_arg in kernel_args ])))), FunctionCall( "LibKernel", (QuotedString(kernel_name), String("CALL_PARALLEL"), Integer(0), QuotedString(kernel_arg_type_name), Integer(0)))) return ccode(code_block, contract=False, type_mappings=TYPE_MAPPINGS)
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_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 shape(source, kind=None): """ Creates an AST node for a function call to Fortran's "shape(...)" Parameters ========== source : Symbol or String kind : expr Examples ======== >>> from sympy.printing import fcode >>> from sympy.codegen.fnodes import shape >>> shp = shape('x') >>> fcode(shp, source_format='free') 'shape(x)' """ return FunctionCall('shape', [_printable(source)] + ([_printable(kind)] if kind else []))
def test_ast_replace(): x = Variable('x', real) y = Variable('y', real) n = Variable('n', integer) pwer = FunctionDefinition(real, 'pwer', [x, n], [pow(x.symbol, n.symbol)]) pname = pwer.name pcall = FunctionCall('pwer', [y, 3]) tree1 = CodeBlock(pwer, pcall) assert str(tree1.args[0].name) == 'pwer' assert str(tree1.args[1].name) == 'pwer' for a, b in zip(tree1, [pwer, pcall]): assert a == b tree2 = tree1.replace(pname, String('power')) assert str(tree1.args[0].name) == 'pwer' assert str(tree1.args[1].name) == 'pwer' assert str(tree2.args[0].name) == 'power' assert str(tree2.args[1].name) == 'power'
def test_FunctionCall(): fc = FunctionCall('power', (x, 3)) assert fc.function_args[0] == x assert fc.function_args[1] == 3 assert len(fc.function_args) == 2 assert isinstance(fc.function_args[1], Integer) assert fc == FunctionCall('power', (x, 3)) assert fc != FunctionCall('power', (3, x)) assert fc != FunctionCall('Power', (x, 3)) assert fc.func(*fc.args) == fc fc2 = FunctionCall('fma', [2, 3, 4]) assert len(fc2.function_args) == 3 assert fc2.function_args[0] == 2 assert fc2.function_args[1] == 3 assert fc2.function_args[2] == 4 assert str(fc2) in ( # not sure if QuotedString is a better default... 'FunctionCall(fma, function_args=(2, 3, 4))', 'FunctionCall("fma", function_args=(2, 3, 4))', )
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_function_call(): c_src1 = "x = fun1(2);" c_src2 = "y = fun2(2, 3, 4);" c_src3 = "int p, q, r;" + "\n" + "z = fun3(p, q, r);" c_src4 = "float x, y;" + "\n" + "int z;" + "\n" + "i = fun4(x, y, z)" c_src5 = "a = fun()" 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() res5 = SymPyExpression(c_src5, "c").return_expr() assert res1[0] == Declaration( Variable(Symbol("x"), value=FunctionCall(String("fun1"), function_args=([ 2, ])))) assert res2[0] == Declaration( Variable( Symbol("y"), value=FunctionCall(String("fun2"), function_args=([2, 3, 4])), )) assert res3[0] == Declaration( Variable(Symbol("p"), type=IntBaseType(String("integer")), value=Integer(0))) assert res3[1] == Declaration( Variable(Symbol("q"), type=IntBaseType(String("integer")), value=Integer(0))) assert res3[2] == Declaration( Variable(Symbol("r"), type=IntBaseType(String("integer")), value=Integer(0))) assert res3[3] == Declaration( Variable( Symbol("z"), value=FunctionCall( String("fun3"), function_args=([Symbol("p"), Symbol("q"), Symbol("r")]), ), )) assert res4[0] == Declaration( Variable( Symbol("x"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), )) assert res4[1] == Declaration( Variable( Symbol("y"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), )) assert res4[2] == Declaration( Variable(Symbol("z"), type=IntBaseType(String("integer")), value=Integer(0))) assert res4[3] == Declaration( Variable( Symbol("i"), value=FunctionCall( String("fun4"), function_args=([Symbol("x"), Symbol("y"), Symbol("z")]), ), )) assert res5[0] == Declaration( Variable(Symbol("a"), value=FunctionCall(String("fun"), function_args=())))
def test_function_call(): c_src1 = 'x = fun1(2);' c_src2 = 'y = fun2(2, 3, 4);' c_src3 = ('int p, q, r;' + '\n' + 'z = fun3(p, q, r);') c_src4 = ('float x, y;' + '\n' + 'int z;' + '\n' + 'i = fun4(x, y, z)') c_src5 = 'a = fun()' 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() res5 = SymPyExpression(c_src5, 'c').return_expr() assert res1[0] == Declaration( Variable(Symbol('x'), value=FunctionCall(String('fun1'), function_args=([ 2, ])))) assert res2[0] == Declaration( Variable(Symbol('y'), value=FunctionCall(String('fun2'), function_args=([2, 3, 4])))) assert res3[0] == Declaration( Variable(Symbol('p'), type=IntBaseType(String('integer')), value=Integer(0))) assert res3[1] == Declaration( Variable(Symbol('q'), type=IntBaseType(String('integer')), value=Integer(0))) assert res3[2] == Declaration( Variable(Symbol('r'), type=IntBaseType(String('integer')), value=Integer(0))) assert res3[3] == Declaration( Variable(Symbol('z'), value=FunctionCall(String('fun3'), function_args=([ Symbol('p'), Symbol('q'), Symbol('r') ])))) assert res4[0] == Declaration( Variable(Symbol('x'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53))) assert res4[1] == Declaration( Variable(Symbol('y'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53))) assert res4[2] == Declaration( Variable(Symbol('z'), type=IntBaseType(String('integer')), value=Integer(0))) assert res4[3] == Declaration( Variable(Symbol('i'), value=FunctionCall(String('fun4'), function_args=([ Symbol('x'), Symbol('y'), Symbol('z') ])))) assert res5[0] == Declaration( Variable(Symbol('a'), value=FunctionCall(String('fun'), function_args=())))
def alignof(arg): """ Generate of FunctionCall instance for calling 'alignof' """ return FunctionCall("alignof", [String(arg) if isinstance(arg, str) else arg])
def gen_function(self, kernel_name, kernel_arg_type_name): main_block = [] main_block.append( Comment( "Output iteration space %s reduced to %s iteration spaces" % (self._max_shape, len(self._indexes)))) # dereference all symbols that are not indexed dereference = [ symbol for symbol in self._symbol_indexes if not self._symbol_indexes[symbol] ] for expr_state in self._expr_states: free_symbols = [ symbol for symbol in expr_state.expr.free_symbols if not symbol in self._temporaries ] # create substitutions for symbols that are indexed subs = [(symbol, indexed_symbol(symbol, [ self._indexes[idx][1] for idx in self._symbol_indexes[symbol] ], [ self._indexes[idx][0] for idx in self._symbol_indexes[symbol] ])) for symbol in free_symbols if self._symbol_indexes[symbol]] # indexed results. non indexed temps if not expr_state.is_intermediate: main_block.append( Comment("Produce output symbol %s" % expr_state.symbol)) res_symbol = IndexedBase( expr_state.symbol, shape=tuple(tuple(index[1] for index in self._indexes))) res_symbol = res_symbol[tuple(index[0] for index in self._indexes)] else: main_block.append( Comment("Produce intermediate symbol %s" % expr_state.symbol)) res_symbol = expr_state.symbol main_block.append( Assignment(res_symbol, expr_state.expr.subs(subs))) # create all the for loops def func(block, idx): return [ VarFor(Declaration(Variable(Symbol(idx[0]), type=uint32)), VarRange(idx[2][0], idx[2][1], Integer(1)), block) ] for_block = reduce(func, self._indexes[::-1], main_block)[0] # Create the initial code with args assignments and paralellization calcluation ast = self.setup_codegen() # declare temporaries ast.extend([ Declaration(Variable(symbol, type=int32)) for symbol in self._temporaries ]) ast.append(for_block) ast.append(FunctionCall("gap_waitbarrier", (Integer(0), ))) # create function definition func_def = FunctionDefinition( VOID, kernel_name, [Pointer("Args", type=Type(kernel_arg_type_name))], ast) # generate code return ccode(func_def, contract=False, dereference=dereference, user_functions=CFUNC_DEFS, type_mappings=TYPE_MAPPINGS)