def test_InOutArgument_order(): # can specify the order as (x, y) expr = Equality(x, x**2 + y) name_expr = ("test", expr) result, = codegen(name_expr, "Rust", header=False, empty=False, argument_sequence=(x,y)) source = result[1] expected = ( "fn test(x: f64, y: f64) -> f64 {\n" " let x = x.powi(2) + y;\n" " x\n" "}\n" ) assert source == expected # make sure it gives (x, y) not (y, x) expr = Equality(x, x**2 + y) name_expr = ("test", expr) result, = codegen(name_expr, "Rust", header=False, empty=False) source = result[1] expected = ( "fn test(x: f64, y: f64) -> f64 {\n" " let x = x.powi(2) + y;\n" " x\n" "}\n" ) assert source == expected
def test_global_vars(): x, y, z, t = symbols("x y z t") result = codegen(('f', x*y), "F95", header=False, empty=False, global_vars=(y,)) source = result[0][1] expected = ( "REAL*8 function f(x)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "f = x*y\n" "end function\n" ) assert source == expected result = codegen(('f', x*y+z), "C", header=False, empty=False, global_vars=(z, t)) source = result[0][1] expected = ( '#include "f.h"\n' '#include <math.h>\n' 'double f(double x, double y) {\n' ' double f_result;\n' ' f_result = x*y + z;\n' ' return f_result;\n' '}\n' ) assert source == expected
def test_jl_InOutArgument_order(): # can specify the order as (x, y) expr = Equality(x, x**2 + y) name_expr = ("test", expr) result, = codegen(name_expr, "Julia", header=False, empty=False, argument_sequence=(x,y)) source = result[1] expected = ( "function test(x, y)\n" " x = x.^2 + y\n" " return x\n" "end\n" ) assert source == expected # make sure it gives (x, y) not (y, x) expr = Equality(x, x**2 + y) name_expr = ("test", expr) result, = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ( "function test(x, y)\n" " x = x.^2 + y\n" " return x\n" "end\n" ) assert source == expected
def test_global_vars(): x, y, z, t = symbols("x y z t") result = codegen(('f', x*y), "F95", header=False, empty=False, global_vars=(y,)) source = result[0][1] expected = ( "REAL*8 function f(x)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "f = x*y\n" "end function\n" ) assert source == expected expected = ( '#include "f.h"\n' '#include <math.h>\n' 'double f(double x, double y) {\n' ' double f_result;\n' ' f_result = x*y + z;\n' ' return f_result;\n' '}\n' ) with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=SymPyDeprecationWarning) result = codegen(('f', x*y+z), "C", header=False, empty=False, global_vars=(z, t)) source = result[0][1] assert source == expected
def tensorized_basis_3D(order): total_integration_points = (order + 1) * (order + 1) r,s,t = sym.symbols('r,s,t') r_gll = sym.symbols('r_0:%d' % (order + 1)) s_gll = sym.symbols('s_0:%d' % (order + 1)) t_gll = sym.symbols('t_0:%d' % (order + 1)) # Get N + 1 lagrange polynomials in each direction. generator_r = generating_polynomial_lagrange(order, 'r', r_gll) generator_s = generating_polynomial_lagrange(order, 's', s_gll) generator_t = generating_polynomial_lagrange(order, 't', t_gll) # Get tensorized basis. basis = TensorProduct(generator_t, generator_s, generator_r) gll_coordinates, gll_weights = gauss_lobatto_legendre_quadruature_points_weights(order + 1) basis = basis.subs([(v, c) for v, c in zip(r_gll, gll_coordinates)]) basis = basis.subs([(v, c) for v, c in zip(s_gll, gll_coordinates)]) basis = basis.subs([(v, c) for v, c in zip(t_gll, gll_coordinates)]) # Get gradient of basis functions. basis_gradient_r = sym.Matrix([sym.diff(i, r) for i in basis]) basis_gradient_s = sym.Matrix([sym.diff(i, s) for i in basis]) basis_gradient_t = sym.Matrix([sym.diff(i, t) for i in basis]) routines = [('interpolate_order{}_hex'.format(order),basis), ('interpolate_r_derivative_order{}_hex'.format(order), basis_gradient_r), ('interpolate_s_derivative_order{}_hex'.format(order), basis_gradient_s), ('interpolate_t_derivative_order{}_hex'.format(order), basis_gradient_t)] codegen(routines, "C", "order{}_hex".format(order), to_files=True, project="SALVUS") # fix headers (#include "order4_hex.h" -> #include <Element/HyperCube/Autogen/order3_hex.h>) fixHeader(order,"hex",".")
def __init__(self,init): from numpy import zeros, f2py from sympy.utilities.codegen import codegen import sympy as sp self.type = init.type self.bounding_points = np.array(init.bounding_points) self.bounding_points_xi = None self.boundary_surface = init.boundary_surface self.flow_state = init.flow_state if self.boundary_surface: gradxsrc = codegen( ('gradx'+str(id(self)), sp.diff(sp.sympify(self.boundary_surface.split('=')[1].strip()), sp.Symbol('x'))),'F95','junk')[0] gradysrc = codegen( ('grady'+str(id(self)), sp.diff(sp.sympify(self.boundary_surface.split('=')[1].strip()), sp.Symbol('y'))),'F95','junk')[0] gradzsrc = codegen( ('gradz'+str(id(self)), sp.diff(sp.sympify(self.boundary_surface.split('=')[1].strip()), sp.Symbol('z'))),'F95','junk')[0] self.gradsrc = gradxsrc[1]+'\n'+gradysrc[1]+'\n'+gradzsrc[1]+'\n' try: iftest = bool(self.flow_state) except ValueError: # This means that the truth value is ambiguous (array). iftest = bool(self.flow_state.ndim == 1) if iftest: temp = zeros((points.shape[1],points.shape[2])) for i in range(points.shape[1]): for j in range(points.shape[2]): temp[:,i,j] = self.flow_state self.flow_state = temp
def generate_from_sympy(expr, derivative=False, wrt=None): """ given a SymPy expression 'expr', generates C-code for that expression or its derivative (if 'derivative' == True); if returning derivative, wrt should also be specified """ global _expr_count _expr_count += 1 name = 'expr_%d' % _expr_count if derivative and (wrt is not None): return codegen((name, sympy.diff(expr, wrt)), 'C', name)[0][1] else: return codegen((name, expr), 'C', name)[0][1]
def test_check_case_false_positive(): # The upper case/lower case exception should not be triggered by Sympy # objects that differ only because of assumptions. (It may be useful to # have a check for that as well, but here we only want to test against # false positives with respect to case checking.) x1 = symbols("x") x2 = symbols("x", my_assumption=True) try: codegen(("test", x1 * x2), "f95", "prefix") except CodeGenError, e: if e.args[0][0:21] == "Fortran ignores case.": raise AssertionError("This exception should not be raised!")
def test_check_case_false_positive(): # The upper case/lower case exception should not be triggered by SymPy # objects that differ only because of assumptions. (It may be useful to # have a check for that as well, but here we only want to test against # false positives with respect to case checking.) x1 = symbols('x') x2 = symbols('x', my_assumption=True) try: codegen(('test', x1*x2), 'f95', 'prefix') except CodeGenError as e: if e.args[0].startswith("Fortran ignores case."): raise AssertionError("This exception should not be raised!")
def test_complicated_codegen_f95(): from sympy import sin, cos, tan x, y, z = symbols('x,y,z') name_expr = [ ("test1", ((sin(x) + cos(y) + tan(z))**7).expand()), ("test2", cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))), ] result = codegen(name_expr, "F95", "file", header=False, empty=False) assert result[0][0] == "file.f90" expected = ( 'REAL*8 function test1(x, y, z)\n' 'implicit none\n' 'REAL*8, intent(in) :: x\n' 'REAL*8, intent(in) :: y\n' 'REAL*8, intent(in) :: z\n' 'test1 = sin(x)**7 + 7*sin(x)**6*cos(y) + 7*sin(x)**6*tan(z) + 21*sin(x) &\n' ' **5*cos(y)**2 + 42*sin(x)**5*cos(y)*tan(z) + 21*sin(x)**5*tan(z) &\n' ' **2 + 35*sin(x)**4*cos(y)**3 + 105*sin(x)**4*cos(y)**2*tan(z) + &\n' ' 105*sin(x)**4*cos(y)*tan(z)**2 + 35*sin(x)**4*tan(z)**3 + 35*sin( &\n' ' x)**3*cos(y)**4 + 140*sin(x)**3*cos(y)**3*tan(z) + 210*sin(x)**3* &\n' ' cos(y)**2*tan(z)**2 + 140*sin(x)**3*cos(y)*tan(z)**3 + 35*sin(x) &\n' ' **3*tan(z)**4 + 21*sin(x)**2*cos(y)**5 + 105*sin(x)**2*cos(y)**4* &\n' ' tan(z) + 210*sin(x)**2*cos(y)**3*tan(z)**2 + 210*sin(x)**2*cos(y) &\n' ' **2*tan(z)**3 + 105*sin(x)**2*cos(y)*tan(z)**4 + 21*sin(x)**2*tan &\n' ' (z)**5 + 7*sin(x)*cos(y)**6 + 42*sin(x)*cos(y)**5*tan(z) + 105* &\n' ' sin(x)*cos(y)**4*tan(z)**2 + 140*sin(x)*cos(y)**3*tan(z)**3 + 105 &\n' ' *sin(x)*cos(y)**2*tan(z)**4 + 42*sin(x)*cos(y)*tan(z)**5 + 7*sin( &\n' ' x)*tan(z)**6 + cos(y)**7 + 7*cos(y)**6*tan(z) + 21*cos(y)**5*tan( &\n' ' z)**2 + 35*cos(y)**4*tan(z)**3 + 35*cos(y)**3*tan(z)**4 + 21*cos( &\n' ' y)**2*tan(z)**5 + 7*cos(y)*tan(z)**6 + tan(z)**7\n' 'end function\n' 'REAL*8 function test2(x, y, z)\n' 'implicit none\n' 'REAL*8, intent(in) :: x\n' 'REAL*8, intent(in) :: y\n' 'REAL*8, intent(in) :: z\n' 'test2 = cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))\n' 'end function\n' ) assert result[0][1] == expected assert result[1][0] == "file.h" expected = ( 'interface\n' 'REAL*8 function test1(x, y, z)\n' 'implicit none\n' 'REAL*8, intent(in) :: x\n' 'REAL*8, intent(in) :: y\n' 'REAL*8, intent(in) :: z\n' 'end function\n' 'end interface\n' 'interface\n' 'REAL*8 function test2(x, y, z)\n' 'implicit none\n' 'REAL*8, intent(in) :: x\n' 'REAL*8, intent(in) :: y\n' 'REAL*8, intent(in) :: z\n' 'end function\n' 'end interface\n' ) assert result[1][1] == expected
def test_multifcns_per_file_w_header(): name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] result = codegen(name_expr, "Rust", header=True, empty=False) assert result[0][0] == "foo.rs" source = result[0][1]; version_str = "Code generated with sympy %s" % sympy.__version__ version_line = version_str.center(76).rstrip() expected = ( "/*\n" " *%(version_line)s\n" " *\n" " * See http://www.sympy.org/ for more information.\n" " *\n" " * This file is part of 'project'\n" " */\n" "fn foo(x: f64, y: f64) -> (f64, f64) {\n" " let out1 = 2*x;\n" " let out2 = 3*y;\n" " (out1, out2)\n" "}\n" "fn bar(y: f64) -> (f64, f64) {\n" " let out1 = y.powi(2);\n" " let out2 = 4*y;\n" " (out1, out2)\n" "}\n" ) % {'version_line': version_line} assert source == expected
def test_jl_tensor_loops_multiple_contractions(): # see comments in previous test about vectorizing from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m, o, p = symbols('n m o p', integer=True) A = IndexedBase('A') B = IndexedBase('B') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) k = Idx('k', o) l = Idx('l', p) result, = codegen(('tensorthing', Eq(y[i], B[j, k, l]*A[i, j, k, l])), "Julia", header=False, empty=False) source = result[1] expected = ( 'function tensorthing(y, A, B, m, n, o, p)\n' ' for i = 1:m\n' ' y[i] = 0\n' ' end\n' ' for i = 1:m\n' ' for j = 1:n\n' ' for k = 1:o\n' ' for l = 1:p\n' ' y[i] = y[i] + B[j,k,l].*A[i,j,k,l]\n' ' end\n' ' end\n' ' end\n' ' end\n' ' return y\n' 'end\n' ) assert source == expected
def test_custom_codegen(): from sympy.printing.ccode import C99CodePrinter from sympy.functions.elementary.exponential import exp printer = C99CodePrinter(settings={'user_functions': {'exp': 'fastexp'}}) gen = C99CodeGen(printer=printer) gen.preprocessor_statements.append('#include "fastexp.h"') x, y = symbols('x y') expr = exp(x + y) expected = ( '#include "expr.h"\n' '#include <math.h>\n' '#include "fastexp.h"\n' 'double expr(double x, double y) {\n' ' double expr_result;\n' ' expr_result = fastexp(x + y);\n' ' return expr_result;\n' '}\n' ) result = codegen(('expr', expr), header=False, empty=False, code_gen=gen) source = result[0][1] assert source == expected
def test_fcode_matrix_output(): x, y, z = symbols('x,y,z') e1 = x + y e2 = Matrix([[x, y], [z, 16]]) name_expr = ("test", (e1, e2)) result = codegen(name_expr, "f95", "test", header=False, empty=False) source = result[0][1] expected = ( "REAL*8 function test(x, y, z, out_%(hash)s)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "REAL*8, intent(in) :: y\n" "REAL*8, intent(in) :: z\n" "REAL*8, intent(out), dimension(1:2, 1:2) :: out_%(hash)s\n" "out_%(hash)s(1, 1) = x\n" "out_%(hash)s(2, 1) = z\n" "out_%(hash)s(1, 2) = y\n" "out_%(hash)s(2, 2) = 16\n" "test = x + y\n" "end function\n" ) # look for the magic number a = source.splitlines()[5] b = a.split('_') out = b[1] expected = expected % {'hash': out} assert source == expected
def test_ccode_matrixsymbol_slice(): A = MatrixSymbol('A', 5, 3) B = MatrixSymbol('B', 1, 3) C = MatrixSymbol('C', 1, 3) D = MatrixSymbol('D', 5, 1) name_expr = ("test", [Equality(B, A[0, :]), Equality(C, A[1, :]), Equality(D, A[:, 2])]) result = codegen(name_expr, "c99", "test", header=False, empty=False) source = result[0][1] expected = ( '#include "test.h"\n' '#include <math.h>\n' 'void test(double *A, double *B, double *C, double *D) {\n' ' B[0] = A[0];\n' ' B[1] = A[1];\n' ' B[2] = A[2];\n' ' C[0] = A[3];\n' ' C[1] = A[4];\n' ' C[2] = A[5];\n' ' D[0] = A[2];\n' ' D[1] = A[5];\n' ' D[2] = A[8];\n' ' D[3] = A[11];\n' ' D[4] = A[14];\n' '}\n' ) assert source == expected
def test_jl_loops(): # Note: an Julia programmer would probably vectorize this across one or # more dimensions. Also, size(A) would be used rather than passing in m # and n. Perhaps users would expect us to vectorize automatically here? # Or is it possible to represent such things using IndexedBase? from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols('n m', integer=True) A = IndexedBase('A') x = IndexedBase('x') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) result, = codegen(('mat_vec_mult', Eq(y[i], A[i, j]*x[j])), "Julia", header=False, empty=False) source = result[1] expected = ( 'function mat_vec_mult(y, A, m, n, x)\n' ' for i = 1:m\n' ' y[i] = 0\n' ' end\n' ' for i = 1:m\n' ' for j = 1:n\n' ' y[i] = %(rhs)s + y[i]\n' ' end\n' ' end\n' ' return y\n' 'end\n' ) assert (source == expected % {'rhs': 'A[%s,%s].*x[j]' % (i, j)} or source == expected % {'rhs': 'x[j].*A[%s,%s]' % (i, j)})
def test_complicated_codegen(): from sympy import sin, cos, tan, N x,y,z = symbols('xyz') name_expr = [ ("test1", ((sin(x)+cos(y)+tan(z))**7).expand()), ("test2", cos(cos(cos(cos(cos(cos(cos(cos(x+y+z))))))))), ] result = codegen(name_expr, "C", "file", header=False, empty=False) assert result[0][0] == "file.c" assert result[0][1] == ( '#include "file.h"\n#include <math.h>\n' 'double test1(double x, double y, double z) {\n' ' return ' '7*pow(cos(y), 6)*sin(x) + ' '7*pow(cos(y), 6)*tan(z) + ' '7*pow(sin(x), 6)*cos(y) + ' '7*pow(sin(x), 6)*tan(z) + ' '7*pow(tan(z), 6)*cos(y) + ' '7*pow(tan(z), 6)*sin(x) + ' '42*pow(cos(y), 5)*sin(x)*tan(z) + ' '42*pow(sin(x), 5)*cos(y)*tan(z) + ' '42*pow(tan(z), 5)*cos(y)*sin(x) + ' '105*pow(cos(y), 2)*pow(sin(x), 4)*tan(z) + ' '105*pow(cos(y), 2)*pow(tan(z), 4)*sin(x) + ' '105*pow(cos(y), 4)*pow(sin(x), 2)*tan(z) + ' '105*pow(cos(y), 4)*pow(tan(z), 2)*sin(x) + ' '105*pow(sin(x), 2)*pow(tan(z), 4)*cos(y) + ' '105*pow(sin(x), 4)*pow(tan(z), 2)*cos(y) + ' '140*pow(cos(y), 3)*pow(sin(x), 3)*tan(z) + ' '140*pow(cos(y), 3)*pow(tan(z), 3)*sin(x) + ' '140*pow(sin(x), 3)*pow(tan(z), 3)*cos(y) + ' '21*pow(cos(y), 5)*pow(sin(x), 2) + ' '21*pow(cos(y), 5)*pow(tan(z), 2) + ' '21*pow(sin(x), 5)*pow(tan(z), 2) + ' '210*pow(cos(y), 2)*pow(sin(x), 3)*pow(tan(z), 2) + ' '210*pow(cos(y), 3)*pow(sin(x), 2)*pow(tan(z), 2) + ' '35*pow(cos(y), 4)*pow(sin(x), 3) + ' '35*pow(cos(y), 4)*pow(tan(z), 3) + ' '35*pow(sin(x), 4)*pow(tan(z), 3) + ' '210*pow(cos(y), 2)*pow(sin(x), 2)*pow(tan(z), 3) + ' '35*pow(cos(y), 3)*pow(sin(x), 4) + ' '35*pow(cos(y), 3)*pow(tan(z), 4) + ' '35*pow(sin(x), 3)*pow(tan(z), 4) + ' '21*pow(cos(y), 2)*pow(sin(x), 5) + ' '21*pow(cos(y), 2)*pow(tan(z), 5) + ' '21*pow(sin(x), 2)*pow(tan(z), 5) + ' 'pow(cos(y), 7) + pow(sin(x), 7) + pow(tan(z), 7);\n' '}\n' 'double test2(double x, double y, double z) {\n' ' return cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))));\n' '}\n' ) assert result[1][0] == "file.h" assert result[1][1] == ( '#ifndef PROJECT__FILE__H\n' '#define PROJECT__FILE__H\n' 'double test1(double x, double y, double z);\n' 'double test2(double x, double y, double z);\n' '#endif\n' )
def test_fcode_matrixsymbol_slice(): A = MatrixSymbol('A', 2, 3) B = MatrixSymbol('B', 1, 3) C = MatrixSymbol('C', 1, 3) D = MatrixSymbol('D', 2, 1) name_expr = ("test", [Equality(B, A[0, :]), Equality(C, A[1, :]), Equality(D, A[:, 2])]) result = codegen(name_expr, "f95", "test", header=False, empty=False) source = result[0][1] expected = ( "subroutine test(A, B, C, D)\n" "implicit none\n" "REAL*8, intent(in), dimension(1:2, 1:3) :: A\n" "REAL*8, intent(out), dimension(1:1, 1:3) :: B\n" "REAL*8, intent(out), dimension(1:1, 1:3) :: C\n" "REAL*8, intent(out), dimension(1:2, 1:1) :: D\n" "B(1, 1) = A(1, 1)\n" "B(1, 2) = A(1, 2)\n" "B(1, 3) = A(1, 3)\n" "C(1, 1) = A(2, 1)\n" "C(1, 2) = A(2, 2)\n" "C(1, 3) = A(2, 3)\n" "D(1, 1) = A(1, 3)\n" "D(2, 1) = A(2, 3)\n" "end subroutine\n" ) assert source == expected
def test_ccode_results_named_ordered(): x, y, z = symbols('x,y,z') B, C = symbols('B,C') A = MatrixSymbol('A', 1, 3) expr1 = Equality(A, Matrix([[1, 2, x]])) expr2 = Equality(C, (x + y)*z) expr3 = Equality(B, 2*x) name_expr = ("test", [expr1, expr2, expr3]) expected = ( '#include "test.h"\n' '#include <math.h>\n' 'void test(double x, double *C, double z, double y, double *A, double *B) {\n' ' (*C) = z*(x + y);\n' ' A[0] = 1;\n' ' A[1] = 2;\n' ' A[2] = x;\n' ' (*B) = 2*x;\n' '}\n' ) with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=SymPyDeprecationWarning) result = codegen(name_expr, "c", "test", header=False, empty=False, argument_sequence=(x, C, z, y, A, B)) source = result[0][1] assert source == expected
def test_simple_f_codegen(): x, y, z = symbols('x,y,z') expr = (x + y)*z result = codegen( ("test", expr), "F95", "file", header=False, empty=False) expected = [ ("file.f90", "REAL*8 function test(x, y, z)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "REAL*8, intent(in) :: y\n" "REAL*8, intent(in) :: z\n" "test = z*(x + y)\n" "end function\n"), ("file.h", "interface\n" "REAL*8 function test(x, y, z)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "REAL*8, intent(in) :: y\n" "REAL*8, intent(in) :: z\n" "end function\n" "end interface\n") ] assert result == expected
def test_fcode_results_named_ordered(): x, y, z = symbols('x,y,z') B, C = symbols('B,C') A = MatrixSymbol('A', 1, 3) expr1 = Equality(A, Matrix([[1, 2, x]])) expr2 = Equality(C, (x + y)*z) expr3 = Equality(B, 2*x) name_expr = ("test", [expr1, expr2, expr3]) result = codegen(name_expr, "f95", "test", header=False, empty=False, argument_sequence=(x, z, y, C, A, B)) source = result[0][1] expected = ( "subroutine test(x, z, y, C, A, B)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "REAL*8, intent(in) :: z\n" "REAL*8, intent(in) :: y\n" "REAL*8, intent(out) :: C\n" "REAL*8, intent(out) :: B\n" "REAL*8, intent(out), dimension(1:1, 1:3) :: A\n" "C = z*(x + y)\n" "A(1, 1) = 1\n" "A(1, 2) = 2\n" "A(1, 3) = x\n" "B = 2*x\n" "end subroutine\n" ) assert source == expected
def generate_c_code(fn, expr, use_single_float=True, args=None): from sympy.utilities.codegen import codegen [(c_name, c_code), (h_name, c_header)] = codegen( (fn, expr), "C", "", header=False, empty=False, argument_sequence=args) c_code = re.sub(r'out_[0-9]{19}', 'out', c_code) c_code = clean_c_code(c_code, use_single_float) return c_code
def generate_jacobian_code(segments, label, dest_path): jacobian, var_names = generate_jacobian(segments) c_funcs = [] # Row for X derivatives for i in xrange(len(var_names)): c_funcs.append(('dx_d' + var_names[i], jacobian[0, i])) # Row for Y derivatives for i in xrange(len(var_names)): c_funcs.append(('dy_d' + var_names[i], jacobian[1, i])) # Row for Z derivatives for i in xrange(len(var_names)): c_funcs.append(('dz_d' + var_names[i], jacobian[2, i])) codegen(c_funcs, 'C', dest_path, label+'_jacobian', to_files=True)
def compile(self): #code.interact(local=locals()) # define the render function dist = float('inf') for face in self.faces: dist = sp.Min(dist,face.intersect(None,{})) # print the render function codegen(('distance',dist),'C',to_files=True,prefix='dr_cube/distance',header=True,empty=True) # print the derivitives for var in self.get_syms(): deriv = sp.diff(dist,var) name = 'diff_{0}'.format(var) deriv = deriv.replace(sp.Heaviside,simp_heaviside) codegen((name,deriv),'C',to_files=True,prefix='dr_cube/' + name,header=True,empty=True)
def toCode(expr,enableDouble): [(sourceFilename,source),(headerFilenam,header)]=codegen( ('funName',expr),'C','codeGened',header=False) if enableDouble: code=pow2ToSqr(source) else: code=pow2ToSqr(source).replace('double','float') code=code[code.find('return')+6:] code=code[:code.find(';')] return code
def cse_to_c(replacements, reduced_exprs, indent=2, debug=False): """Converts the return value sympy.cse() to a single C code snippet. """ ccode = "" ws = " " * indent rtn_pattern = re.compile('\s*?return (.*)') equ_pattern = re.compile('\s*?([\w\[\]]+)\s*?=\s*?(\S.*)') repline_template = '{ind}{name} = {expr}\n' redline_template = '{ind}{name} = {expr}\n' redrtnline_template = '{ind}return {expr}\n' debug_template = ws + 'std::cout << "{0} = " << {0} << "\\n";\n' repnames = set() for repsym, repexpr in replacements: repname = str(repsym) repnames.add(repname) gencode = codegen((repname, repexpr), "C", repname, header=False, empty=False) genexpr = gencode[0][1] if repexpr.is_Equality: genexpr = equ_pattern.search(genexpr).group(2) else: genexpr = rtn_pattern.search(genexpr).group(1) genline = repline_template.format(ind=ws, name=repname, expr=genexpr) ccode += genline if debug: ccode += debug_template.format(repname) for redexpr in reduced_exprs: gencode = codegen(("redname", redexpr), "C", "temp", header=False, empty=False) genexpr = gencode[0][1] if redexpr.is_Equality: m = equ_pattern.search(genexpr) genname = m.group(1) genexpr = m.group(2) genline = redline_template.format(ind=ws, name=genname, expr=genexpr) if debug: genline += debug_template.format(genname) else: genexpr = rtn_pattern.search(genexpr).group(1) genline = redrtnline_template.format(ind=ws, expr=genexpr) ccode += genline return ccode, repnames
def test_m_numbersymbol(): name_expr = ("test", pi**Catalan) result, = codegen(name_expr, "Octave", header=False, empty=False) source = result[1] expected = ( "function out1 = test()\n" " out1 = pi^%s;\n" "end\n" ) % Catalan.evalf(17) assert source == expected
def GenCode(exp): # From http://docs.sympy.org/dev/modules/utilities/codegen.html [(c_name, c_code), (h_name, c_header)] = codegen( ("exp", exp), "C", "test", header=False, empty=False) print("c_code = %s" % c_code) print("ccode = %s" % ccode(exp)) #!!!! TODO TODO TODO: we should check if we have symbolic denominator and generate code that takes care to check if the denominator is 0 and if so to abort the compuatation return None
def test_ansi_math1_codegen(): # not included: log10 from sympy import (acos, asin, atan, ceiling, cos, cosh, floor, log, ln, sin, sinh, sqrt, tan, tanh, Abs) x = symbols('x') name_expr = [ ("test_fabs", Abs(x)), ("test_acos", acos(x)), ("test_asin", asin(x)), ("test_atan", atan(x)), ("test_ceil", ceiling(x)), ("test_cos", cos(x)), ("test_cosh", cosh(x)), ("test_floor", floor(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)), ] result = codegen(name_expr, "C89", "file", header=False, empty=False) assert result[0][0] == "file.c" assert result[0][1] == ( '#include "file.h"\n#include <math.h>\n' 'double test_fabs(double x) {\n double test_fabs_result;\n test_fabs_result = fabs(x);\n return test_fabs_result;\n}\n' 'double test_acos(double x) {\n double test_acos_result;\n test_acos_result = acos(x);\n return test_acos_result;\n}\n' 'double test_asin(double x) {\n double test_asin_result;\n test_asin_result = asin(x);\n return test_asin_result;\n}\n' 'double test_atan(double x) {\n double test_atan_result;\n test_atan_result = atan(x);\n return test_atan_result;\n}\n' 'double test_ceil(double x) {\n double test_ceil_result;\n test_ceil_result = ceil(x);\n return test_ceil_result;\n}\n' 'double test_cos(double x) {\n double test_cos_result;\n test_cos_result = cos(x);\n return test_cos_result;\n}\n' 'double test_cosh(double x) {\n double test_cosh_result;\n test_cosh_result = cosh(x);\n return test_cosh_result;\n}\n' 'double test_floor(double x) {\n double test_floor_result;\n test_floor_result = floor(x);\n return test_floor_result;\n}\n' 'double test_log(double x) {\n double test_log_result;\n test_log_result = log(x);\n return test_log_result;\n}\n' 'double test_ln(double x) {\n double test_ln_result;\n test_ln_result = log(x);\n return test_ln_result;\n}\n' 'double test_sin(double x) {\n double test_sin_result;\n test_sin_result = sin(x);\n return test_sin_result;\n}\n' 'double test_sinh(double x) {\n double test_sinh_result;\n test_sinh_result = sinh(x);\n return test_sinh_result;\n}\n' 'double test_sqrt(double x) {\n double test_sqrt_result;\n test_sqrt_result = sqrt(x);\n return test_sqrt_result;\n}\n' 'double test_tan(double x) {\n double test_tan_result;\n test_tan_result = tan(x);\n return test_tan_result;\n}\n' 'double test_tanh(double x) {\n double test_tanh_result;\n test_tanh_result = tanh(x);\n return test_tanh_result;\n}\n' ) assert result[1][0] == "file.h" assert result[1][1] == ( '#ifndef PROJECT__FILE__H\n#define PROJECT__FILE__H\n' 'double test_fabs(double x);\ndouble test_acos(double x);\n' 'double test_asin(double x);\ndouble test_atan(double x);\n' 'double test_ceil(double x);\ndouble test_cos(double x);\n' 'double test_cosh(double x);\ndouble test_floor(double x);\n' 'double test_log(double x);\ndouble test_ln(double x);\n' 'double test_sin(double x);\ndouble test_sinh(double x);\n' 'double test_sqrt(double x);\ndouble test_tan(double x);\n' 'double test_tanh(double x);\n#endif\n' )
def test_jl_numbersymbol(): name_expr = ("test", pi**Catalan) result, = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ( "function test()\n" " out1 = pi^catalan\n" " return out1\n" "end\n" ) assert source == expected
def test_m_matrix_output_autoname_2(): e1 = (x + y) e2 = Matrix([[2 * x, 2 * y, 2 * z]]) e3 = Matrix([[x], [y], [z]]) e4 = Matrix([[x, y], [z, 16]]) name_expr = ("test", (e1, e2, e3, e4)) result, = codegen(name_expr, "Octave", header=False, empty=False) source = result[1] expected = ("function [out1, out2, out3, out4] = test(x, y, z)\n" " out1 = x + y;\n" " out2 = [2*x 2*y 2*z];\n" " out3 = [x; y; z];\n" " out4 = [x y; z 16];\n" "end\n") assert source == expected
def test_results_named_unordered(): # Here output order is based on name_expr A, B, C = symbols('A,B,C') expr1 = Equality(C, (x + y) * z) expr2 = Equality(A, (x - y) * z) expr3 = Equality(B, 2 * x) name_expr = ("test", [expr1, expr2, expr3]) result, = codegen(name_expr, "Octave", header=False, empty=False) source = result[1] expected = ("function [C, A, B] = test(x, y, z)\n" " C = z.*(x + y);\n" " A = z.*(x - y);\n" " B = 2*x;\n" "end\n") assert source == expected
def test_multiple_results_rust(): # Here the output order is the input order expr1 = (x + y)*z expr2 = (x - y)*z name_expr = ("test", [expr1, expr2]) result, = codegen(name_expr, "Rust", header=False, empty=False) source = result[1] expected = ( "fn test(x: f64, y: f64, z: f64) -> (f64, f64) {\n" " let out1 = z*(x + y);\n" " let out2 = z*(x - y);\n" " (out1, out2)\n" "}\n" ) assert source == expected
def test_not_supported(): f = Function('f') name_expr = ("test", [f(x).diff(x), S.ComplexInfinity]) result, = codegen(name_expr, "Rust", header=False, empty=False) source = result[1] expected = ( "fn test(x: f64) -> (f64, f64) {\n" " // unsupported: Derivative(f(x), x)\n" " // unsupported: zoo\n" " let out1 = Derivative(f(x), x);\n" " let out2 = zoo;\n" " (out1, out2)\n" "}\n" ) assert source == expected
def test_jl_simple_code_with_header(): name_expr = ("test", (x + y) * z) result, = codegen(name_expr, "Julia", header=True, empty=False) assert result[0] == "test.jl" source = result[1] expected = ("# Code generated with sympy " + sympy.__version__ + "\n" "#\n" "# See http://www.sympy.org/ for more information.\n" "#\n" "# This file is part of 'project'\n" "function test(x, y, z)\n" " out1 = z.*(x + y)\n" " return out1\n" "end\n") assert source == expected
def test_m_simple_code_with_header(): name_expr = ("test", (x + y) * z) result, = codegen(name_expr, "Octave", header=True, empty=False) assert result[0] == "test.m" source = result[1] expected = ("function out1 = test(x, y, z)\n" " %TEST Autogenerated by sympy\n" " % Code generated with sympy " + sympy.__version__ + "\n" " %\n" " % See http://www.sympy.org/ for more information.\n" " %\n" " % This file is part of 'project'\n" " out1 = z.*(x + y);\n" "end\n") assert source == expected
def test_m_matrixsymbol_slice_autoname(): A = MatrixSymbol('A', 2, 3) B = MatrixSymbol('B', 1, 3) name_expr = ("test", [Equality(B, A[0,:]), A[1,:], A[:,0], A[:,1]]) result, = codegen(name_expr, "Octave", header=False, empty=False) source = result[1] expected = ( "function [B, out2, out3, out4] = test(A)\n" " B = A(1, :);\n" " out2 = A(2, :);\n" " out3 = A(:, 1);\n" " out4 = A(:, 2);\n" "end\n" ) assert source == expected
def test_m_numbersymbol_no_inline(): # FIXME: how to pass inline=False to the OctaveCodePrinter? name_expr = ("test", [pi**Catalan, EulerGamma]) result, = codegen(name_expr, "Octave", header=False, empty=False, inline=False) source = result[1] expected = ( "function [out1, out2] = test()\n" " Catalan = 0.915965594177219; % constant\n" " EulerGamma = 0.5772156649015329; % constant\n" " out1 = pi^Catalan;\n" " out2 = EulerGamma;\n" "end\n" ) assert source == expected
def test_m_InOutArgument_order(): # can specify the order as (x, y) expr = Equality(x, x**2 + y) name_expr = ("test", expr) result, = codegen(name_expr, "Octave", header=False, empty=False, argument_sequence=(x,y)) source = result[1] expected = ( "function x = test(x, y)\n" " x = x.^2 + y;\n" "end\n" ) assert source == expected # make sure it gives (x, y) not (y, x) expr = Equality(x, x**2 + y) name_expr = ("test", expr) result, = codegen(name_expr, "Octave", header=False, empty=False) source = result[1] expected = ( "function x = test(x, y)\n" " x = x.^2 + y;\n" "end\n" ) assert source == expected
def test_piecewise_inline(): # FIXME: how to pass inline to the RustCodePrinter? pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True)) name_expr = ("pwtest", pw) result, = codegen(name_expr, "Rust", header=False, empty=False, inline=True) source = result[1] expected = ( "fn pwtest(x: f64) -> f64 {\n" " let out1 = if (x < -1) { 0 } else if (x <= 1) { x.powi(2) }" " else if (x > 1) { -x + 2 } else { 1 };\n" " out1\n" "}\n" ) assert source == expected
def test_multiple_results_m(): # Here the output order is the input order expr1 = (x + y)*z expr2 = (x - y)*z name_expr = ("test", [expr1, expr2]) result, = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ( "function test(x, y, z)\n" " out1 = z.*(x + y)\n" " out2 = z.*(x - y)\n" " return out1, out2\n" "end\n" ) assert source == expected
def test_m_matrixsymbol_slice3(): A = MatrixSymbol('A', 8, 7) B = MatrixSymbol('B', 2, 2) C = MatrixSymbol('C', 4, 2) name_expr = ("test", [Equality(B, A[6:, 1::3]), Equality(C, A[::2, ::3])]) result, = codegen(name_expr, "Octave", header=False, empty=False) source = result[1] expected = ( "function [B, C] = test(A)\n" " B = A(7:end, 2:3:end);\n" " C = A(1:2:end, 1:3:end);\n" "end\n" ) assert source == expected
def test_jl_not_supported(): f = Function('f') name_expr = ("test", [f(x).diff(x), S.ComplexInfinity]) result, = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ( "function test(x)\n" " # unsupported: Derivative(f(x), x)\n" " # unsupported: zoo\n" " out1 = Derivative(f(x), x)\n" " out2 = zoo\n" " return out1, out2\n" "end\n" ) assert source == expected
def test_loops(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols('n,m', integer=True) A, x, y = map(IndexedBase, 'Axy') i = Idx('i', m) j = Idx('j', n) (f1, code), (f2, interface) = codegen( ('matrix_vector', Eq(y[i], A[i, j]*x[j])), "F95", "file", header=False, empty=False) assert f1 == 'file.f90' expected = ( 'subroutine matrix_vector(A, m, n, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'INTEGER*4, intent(in) :: n\n' 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' 'REAL*8, intent(in), dimension(1:n) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'INTEGER*4 :: j\n' 'do i = 1, m\n' ' y(i) = 0\n' 'end do\n' 'do i = 1, m\n' ' do j = 1, n\n' ' y(i) = y(i) + %(rhs)s\n' ' end do\n' 'end do\n' 'end subroutine\n' ) % {'rhs': 'A(i, j)*x(j)'} assert expected == code assert f2 == 'file.h' assert interface == ( 'interface\n' 'subroutine matrix_vector(A, m, n, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'INTEGER*4, intent(in) :: n\n' 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' 'REAL*8, intent(in), dimension(1:n) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'end subroutine\n' 'end interface\n' )
def test_loops_InOut(): from sympy.tensor import IndexedBase, Idx from sympy import symbols i, j, n, m = symbols('i j n m', integer=True) A, x, y = symbols('A x y') A = IndexedBase(A)[Idx(i, m), Idx(j, n)] x = IndexedBase(x)[Idx(j, n)] y = IndexedBase(y)[Idx(i, m)] (f1, code), (f2, interface) = codegen(('matrix_vector', Eq(y, y + A * x)), "F95", "file", header=False, empty=False) assert f1 == 'file.f90' expected = ('subroutine matrix_vector(A, m, n, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'INTEGER*4, intent(in) :: n\n' 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' 'REAL*8, intent(in), dimension(1:n) :: x\n' 'REAL*8, intent(inout), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'INTEGER*4 :: j\n' 'do i = 1, m\n' ' do j = 1, n\n' ' y(i) = %(rhs)s + y(i)\n' ' end do\n' 'end do\n' 'end subroutine\n') assert (code == expected % { 'rhs': 'A(i, j)*x(j)' } or code == expected % { 'rhs': 'x(j)*A(i, j)' }) assert f2 == 'file.h' assert interface == ('interface\n' 'subroutine matrix_vector(A, m, n, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'INTEGER*4, intent(in) :: n\n' 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' 'REAL*8, intent(in), dimension(1:n) :: x\n' 'REAL*8, intent(inout), dimension(1:m) :: y\n' 'end subroutine\n' 'end interface\n')
def test_results_named_unordered(): # Here output order is based on name_expr A, B, C = symbols("A,B,C") expr1 = Equality(C, (x + y) * z) expr2 = Equality(A, (x - y) * z) expr3 = Equality(B, 2 * x) name_expr = ("test", [expr1, expr2, expr3]) (result, ) = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ("function test(x, y, z)\n" " C = z.*(x + y)\n" " A = z.*(x - y)\n" " B = 2*x\n" " return C, A, B\n" "end\n") assert source == expected
def test_jl_matrixsymbol_slice_autoname(): A = MatrixSymbol('A', 2, 3) B = MatrixSymbol('B', 1, 3) name_expr = ("test", [Equality(B, A[0,:]), A[1,:], A[:,0], A[:,1]]) result, = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ( "function test(A)\n" " B = A[1,:]\n" " out2 = A[2,:]\n" " out3 = A[:,1]\n" " out4 = A[:,2]\n" " return B, out2, out3, out4\n" "end\n" ) assert source == expected
def test_simple_c_codegen(): x, y, z = symbols('x,y,z') expr = (x + y) * z result = codegen(("test", expr), "C", "file", header=False, empty=False) expected = [("file.c", "#include \"file.h\"\n" "#include <math.h>\n" "double test(double x, double y, double z) {\n" " double test_result;\n" " test_result = z*(x + y);\n" " return test_result;\n" "}\n"), ("file.h", "#ifndef PROJECT__FILE__H\n" "#define PROJECT__FILE__H\n" "double test(double x, double y, double z);\n" "#endif\n")] assert result == expected
def test_m_multifcns_per_file(): name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] result = codegen(name_expr, "Octave", header=False, empty=False) assert result[0][0] == "foo.m" source = result[0][1]; expected = ( "function [out1, out2] = foo(x, y)\n" " out1 = 2*x;\n" " out2 = 3*y;\n" "end\n" "function [out1, out2] = bar(y)\n" " out1 = y.^2;\n" " out2 = 4*y;\n" "end\n" ) assert source == expected
def test_jl_multifcns_per_file(): name_expr = [("foo", [2 * x, 3 * y]), ("bar", [y**2, 4 * y])] result = codegen(name_expr, "Julia", header=False, empty=False) assert result[0][0] == "foo.jl" source = result[0][1] expected = ("function foo(x, y)\n" " out1 = 2*x\n" " out2 = 3*y\n" " return out1, out2\n" "end\n" "function bar(y)\n" " out1 = y.^2\n" " out2 = 4*y\n" " return out1, out2\n" "end\n") assert source == expected
def test_numbersymbol_inline(): # FIXME: how to pass inline to the RustCodePrinter? name_expr = ("test", [pi**Catalan, EulerGamma]) result, = codegen(name_expr, "Rust", header=False, empty=False, inline=True) source = result[1] expected = ( "fn test() -> (f64, f64) {\n" " const Catalan: f64 = %s;\n" " const EulerGamma: f64 = %s;\n" " let out1 = PI.powf(Catalan);\n" " let out2 = EulerGamma);\n" " (out1, out2)\n" "}\n" ) % (Catalan.evalf(17), EulerGamma.evalf(17)) assert source == expected
def test_jl_numbersymbol_no_inline(): # FIXME: how to pass inline=False to the JuliaCodePrinter? name_expr = ("test", [pi**Catalan, EulerGamma]) result, = codegen(name_expr, "Julia", header=False, empty=False, inline=False) source = result[1] expected = ( "function test()\n" " Catalan = 0.915965594177219\n" " EulerGamma = 0.5772156649015329\n" " out1 = pi^Catalan\n" " out2 = EulerGamma\n" " return out1, out2\n" "end\n" ) assert source == expected
def test_jl_matrixsymbol_slice3(): A = MatrixSymbol('A', 8, 7) B = MatrixSymbol('B', 2, 2) C = MatrixSymbol('C', 4, 2) name_expr = ("test", [Equality(B, A[6:, 1::3]), Equality(C, A[::2, ::3])]) result, = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ( "function test(A)\n" " B = A[7:end,2:3:end]\n" " C = A[1:2:end,1:3:end]\n" " return B, C\n" "end\n" ) assert source == expected
def test_results_named_unordered(): # Here output order is based on name_expr A, B, C = symbols('A,B,C') expr1 = Equality(C, (x + y) * z) expr2 = Equality(A, (x - y) * z) expr3 = Equality(B, 2 * x) name_expr = ("test", [expr1, expr2, expr3]) result, = codegen(name_expr, "Rust", header=False, empty=False) source = result[1] expected = ("fn test(x: f64, y: f64, z: f64) -> (f64, f64, f64) {\n" " let C = z*(x + y);\n" " let A = z*(x - y);\n" " let B = 2*x;\n" " (C, A, B)\n" "}\n") assert source == expected
def test_complicated_m_codegen(): from sympy import sin, cos, tan name_expr = ("testlong", [((sin(x) + cos(y) + tan(z))**3).expand(), cos(cos(cos(cos(cos(cos(cos(cos(x + y + z)))))))) ]) result = codegen(name_expr, "Octave", header=False, empty=False) assert result[0][0] == "testlong.m" source = result[0][1] expected = ( "function [out1, out2] = testlong(x, y, z)\n" " out1 = sin(x).^3 + 3*sin(x).^2.*cos(y) + 3*sin(x).^2.*tan(z)" " + 3*sin(x).*cos(y).^2 + 6*sin(x).*cos(y).*tan(z) + 3*sin(x).*tan(z).^2" " + cos(y).^3 + 3*cos(y).^2.*tan(z) + 3*cos(y).*tan(z).^2 + tan(z).^3;\n" " out2 = cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))));\n" "end\n") assert source == expected
def test_multifcns_per_file(): name_expr = [("foo", [2 * x, 3 * y]), ("bar", [y**2, 4 * y])] result = codegen(name_expr, "Rust", header=False, empty=False) assert result[0][0] == "foo.rs" source = result[0][1] expected = ("fn foo(x: f64, y: f64) -> (f64, f64) {\n" " let out1 = 2*x;\n" " let out2 = 3*y;\n" " (out1, out2)\n" "}\n" "fn bar(y: f64) -> (f64, f64) {\n" " let out1 = y.powi(2);\n" " let out2 = 4*y;\n" " (out1, out2)\n" "}\n") assert source == expected
def test_partial_loops_f(): # check that loop boundaries are determined by Idx, and array strides # determined by shape of IndexedBase object. from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m, o, p = symbols('n m o p', integer=True) A = IndexedBase('A', shape=(m, p)) x = IndexedBase('x') y = IndexedBase('y') i = Idx('i', (o, m - 5)) # Note: bounds are inclusive j = Idx('j', n) # dimension n corresponds to bounds (0, n - 1) (f1, code), (f2, interface) = codegen( ('matrix_vector', Eq(y[i], A[i, j] * x[j])), "F95", "file", header=False, empty=False) expected = ('subroutine matrix_vector(A, m, n, o, p, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'INTEGER*4, intent(in) :: n\n' 'INTEGER*4, intent(in) :: o\n' 'INTEGER*4, intent(in) :: p\n' 'REAL*8, intent(in), dimension(1:m, 1:p) :: A\n' 'REAL*8, intent(in), dimension(1:n) :: x\n' 'REAL*8, intent(out), dimension(1:%(iup-ilow)s) :: y\n' 'INTEGER*4 :: i\n' 'INTEGER*4 :: j\n' 'do i = %(ilow)s, %(iup)s\n' ' y(i) = 0\n' 'end do\n' 'do i = %(ilow)s, %(iup)s\n' ' do j = 1, n\n' ' y(i) = %(rhs)s + y(i)\n' ' end do\n' 'end do\n' 'end subroutine\n') % { 'rhs': '%(rhs)s', 'iup': str(m - 4), 'ilow': str(1 + o), 'iup-ilow': str(m - 4 - o) } assert code == expected % {'rhs': 'A(i, j)*x(j)'} or\ code == expected % {'rhs': 'x(j)*A(i, j)'}
def test_loops_c(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols('n m', integer=True) A = IndexedBase('A') x = IndexedBase('x') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) (f1, code), (f2, interface) = codegen( ('matrix_vector', Eq(y[i], A[i, j] * x[j])), "C", "file", header=False, empty=False) assert f1 == 'file.c' expected = ( '#include "file.h"\n' '#include <math.h>\n' 'void matrix_vector(double *A, int m, int n, double *x, double *y) {\n' ' for (int i=0; i<m; i++){\n' ' y[i] = 0;\n' ' }\n' ' for (int i=0; i<m; i++){\n' ' for (int j=0; j<n; j++){\n' ' y[i] = %(rhs)s + y[i];\n' ' }\n' ' }\n' '}\n') assert (code == expected % { 'rhs': 'A[%s]*x[j]' % (i * n + j) } or code == expected % { 'rhs': 'A[%s]*x[j]' % (j + i * n) } or code == expected % { 'rhs': 'x[j]*A[%s]' % (i * n + j) } or code == expected % { 'rhs': 'x[j]*A[%s]' % (j + i * n) }) assert f2 == 'file.h' assert interface == ( '#ifndef PROJECT__FILE__H\n' '#define PROJECT__FILE__H\n' 'void matrix_vector(double *A, int m, int n, double *x, double *y);\n' '#endif\n')
def test_jl_matrix_output_autoname_2(): e1 = x + y e2 = Matrix([[2 * x, 2 * y, 2 * z]]) e3 = Matrix([[x], [y], [z]]) e4 = Matrix([[x, y], [z, 16]]) name_expr = ("test", (e1, e2, e3, e4)) (result, ) = codegen(name_expr, "Julia", header=False, empty=False) source = result[1] expected = ("function test(x, y, z)\n" " out1 = x + y\n" " out2 = [2*x 2*y 2*z]\n" " out3 = [x, y, z]\n" " out4 = [x y;\n" " z 16]\n" " return out1, out2, out3, out4\n" "end\n") assert source == expected
def test_m_output_arg_mixed_unordered(): # named outputs are alphabetical, unnamed output appear in the given order from sympy import sin, cos, tan a = symbols("a") name_expr = ("foo", [cos(2*x), Equality(y, sin(x)), cos(x), Equality(a, sin(2*x))]) result, = codegen(name_expr, "Octave", header=False, empty=False) assert result[0] == "foo.m" source = result[1]; expected = ( 'function [out1, y, out3, a] = foo(x)\n' ' out1 = cos(2*x);\n' ' y = sin(x);\n' ' out3 = cos(x);\n' ' a = sin(2*x);\n' 'end\n' ) assert source == expected