def test_ccode_Piecewise_deep(): p = ccode(2 * Piecewise((x, x < 1), (x + 1, x < 2), (x**2, True))) assert p == ("2*((x < 1) ? (\n" " x\n" ")\n" ": ((x < 2) ? (\n" " x + 1\n" ")\n" ": (\n" " pow(x, 2)\n" ")))") expr = x * y * z + x**2 + y**2 + Piecewise((0, x < 0.5), (1, True)) + cos(z) - 1 assert ccode(expr) == ("pow(x, 2) + x*y*z + pow(y, 2) + ((x < 0.5) ? (\n" " 0\n" ")\n" ": (\n" " 1\n" ")) + cos(z) - 1") assert ccode(expr, assign_to='c') == ( "c = pow(x, 2) + x*y*z + pow(y, 2) + ((x < 0.5) ? (\n" " 0\n" ")\n" ": (\n" " 1\n" ")) + cos(z) - 1;")
def test_ccode_Indexed(): s, n, m, o = symbols('s n m o', integer=True) i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) x = IndexedBase('x')[j] A = IndexedBase('A')[i, j] B = IndexedBase('B')[i, j, k] p = C99CodePrinter() assert p._print_Indexed(x) == 'x[j]' assert p._print_Indexed(A) == 'A[%s]' % (m * i + j) assert p._print_Indexed(B) == 'B[%s]' % (i * o * m + j * o + k) A = IndexedBase('A', shape=(5, 3))[i, j] assert p._print_Indexed(A) == 'A[%s]' % (3 * i + j) A = IndexedBase('A', shape=(5, 3), strides='F')[i, j] assert ccode(A) == 'A[%s]' % (i + 5 * j) A = IndexedBase('A', shape=(29, 29), strides=(1, s), offset=o)[i, j] assert ccode(A) == 'A[o + s*j + i]' Abase = IndexedBase('A', strides=(s, m, n), offset=o) assert ccode(Abase[i, j, k]) == 'A[m*j + n*k + o + s*i]' assert ccode(Abase[2, 3, k]) == 'A[3*m + n*k + o + 2*s]'
def test_ccode_reserved_words(): x, y = symbols('x, if') with raises(ValueError): ccode(y**2, error_on_reserved=True, standard='C99') assert ccode(y**2) == 'pow(if_, 2)' assert ccode(x * y**2, dereference=[y]) == 'pow((*if_), 2)*x' assert ccode(y**2, reserved_word_suffix='_unreserved') == 'pow(if_unreserved, 2)'
def test_ccode_exceptions(): assert ccode(gamma(x), standard='C99') == "tgamma(x)" gamma_c89 = ccode(gamma(x), standard='C89') assert 'not supported in c' in gamma_c89.lower() gamma_c89 = ccode(gamma(x), standard='C89', allow_unknown_functions=False) assert 'not supported in c' in gamma_c89.lower() gamma_c89 = ccode(gamma(x), standard='C89', allow_unknown_functions=True) assert 'not supported in c' not in gamma_c89.lower()
def test_ccode_sign(): expr1, ref1 = sign(x) * y, 'y*(((x) > 0) - ((x) < 0))' expr2, ref2 = sign(cos(x)), '(((cos(x)) > 0) - ((cos(x)) < 0))' expr3, ref3 = sign( 2 * x + x**2 ) * x + x**2, 'pow(x, 2) + x*(((pow(x, 2) + 2*x) > 0) - ((pow(x, 2) + 2*x) < 0))' assert ccode(expr1) == ref1 assert ccode(expr1, 'z') == 'z = %s;' % ref1 assert ccode(expr2) == ref2 assert ccode(expr3) == ref3
def test_ccode_constants_other(): assert ccode( 2 * GoldenRatio ) == "const double GoldenRatio = %s;\n2*GoldenRatio" % GoldenRatio.evalf( 17) assert ccode( 2 * Catalan) == "const double Catalan = %s;\n2*Catalan" % Catalan.evalf(17) assert ccode( 2 * EulerGamma ) == "const double EulerGamma = %s;\n2*EulerGamma" % EulerGamma.evalf(17)
def test_MatrixElement_printing(): # test cases for issue #11821 A = MatrixSymbol("A", 1, 3) B = MatrixSymbol("B", 1, 3) C = MatrixSymbol("C", 1, 3) assert (ccode(A[0, 0]) == "A[0]") assert (ccode(3 * A[0, 0]) == "3*A[0]") F = C[0, 0].subs(C, A - B) assert (ccode(F) == "(A - B)[0]")
def test_ccode_UnevaluatedExpr(): assert ccode(UnevaluatedExpr(y * x) + z) == "z + x*y" assert ccode(UnevaluatedExpr(y + x) + z) == "z + (x + y)" # gh-21955 w = symbols('w') assert ccode(UnevaluatedExpr(y + x) + UnevaluatedExpr(z + w)) == "(w + z) + (x + y)" p, q, r = symbols("p q r", real=True) q_r = UnevaluatedExpr(q + r) expr = abs(exp(p + q_r)) assert ccode(expr) == "exp(p + (q + r))"
def test_ccode_user_functions(): x = symbols('x', integer=False) n = symbols('n', integer=True) custom_functions = { "ceiling": "ceil", "Abs": [(lambda x: not x.is_integer, "fabs"), (lambda x: x.is_integer, "abs")], } assert ccode(ceiling(x), user_functions=custom_functions) == "ceil(x)" assert ccode(Abs(x), user_functions=custom_functions) == "fabs(x)" assert ccode(Abs(n), user_functions=custom_functions) == "abs(n)"
def test_compiled_ccode_with_rewriting(): if not cython: skip("cython not installed.") if not has_c(): skip("No C compiler found.") x = Symbol('x') about_two = 2**(58 / S(117)) * 3**(97 / S(117)) * 5**(4 / S(39)) * 7**( 92 / S(117)) / S(30) * pi # about_two: 1.999999999999581826 unchanged = 2 * exp(x) - about_two xval = S(10)**-11 ref = unchanged.subs(x, xval).n(19) # 2.0418173913673213e-11 rewritten = optimize(2 * exp(x) - about_two, [expm1_opt]) # Unfortunately, we need to call ``.n()`` on our expressions before we hand them # to ``ccode``, and we need to request a large number of significant digits. # In this test, results converged for double precision when the following number # of significant digits were chosen: NUMBER_OF_DIGITS = 25 # TODO: this should ideally be automatically handled. func_c = ''' #include <math.h> double func_unchanged(double x) { return %(unchanged)s; } double func_rewritten(double x) { return %(rewritten)s; } ''' % dict(unchanged=ccode(unchanged.n(NUMBER_OF_DIGITS)), rewritten=ccode(rewritten.n(NUMBER_OF_DIGITS))) func_pyx = ''' #cython: language_level=3 cdef extern double func_unchanged(double) cdef extern double func_rewritten(double) def py_unchanged(x): return func_unchanged(x) def py_rewritten(x): return func_rewritten(x) ''' with tempfile.TemporaryDirectory() as folder: mod, info = compile_link_import_strings([('func.c', func_c), ('_func.pyx', func_pyx)], build_dir=folder, compile_kwargs=dict(std='c99')) err_rewritten = abs(mod.py_rewritten(1e-11) - ref) err_unchanged = abs(mod.py_unchanged(1e-11) - ref) assert 1e-27 < err_rewritten < 1e-25 # highly accurate. assert 1e-19 < err_unchanged < 1e-16 # quite poor.
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)) == "const double Catalan = %s;\n2*x/Catalan" % Catalan.evalf(17) 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_ccode_loops_addfactor(): n, m, o, p = symbols('n m o p', integer=True) a = IndexedBase('a') b = IndexedBase('b') c = IndexedBase('c') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) k = Idx('k', o) l = Idx('l', p) s = ( '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' ' for (int k=0; k<o; k++){\n' ' for (int l=0; l<p; l++){\n' ' y[i] = (a[%s] + b[%s])*c[%s] + y[i];\n' % (i*n*o*p + j*o*p + k*p + l, i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\ ' }\n' ' }\n' ' }\n' '}' ) assert ccode((a[i, j, k, l] + b[i, j, k, l]) * c[j, k, l], assign_to=y[i]) == s
def test_sizeof(): typename = 'unsigned int' sz = sizeof(typename) assert ccode(sz) == 'sizeof(%s)' % typename assert sz.func(*sz.args) == sz assert not sz.is_Atom assert sz.atoms() == {String('unsigned int'), String('sizeof')}
def test_ccode_Max(): # Test for gh-11926 assert ccode(Max(x, x * x), user_functions={ "Max": "my_max", "Pow": "my_pow" }) == 'my_max(x, my_pow(x, 2))'
def test_ccode_loops_multiple_contractions(): 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) s = ( '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' ' for (int k=0; k<o; k++){\n' ' for (int l=0; l<p; l++){\n' ' y[i] = a[%s]*b[%s] + y[i];\n' % (i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\ ' }\n' ' }\n' ' }\n' '}' ) assert ccode(b[j, k, l] * a[i, j, k, l], assign_to=y[i]) == s
def test_ccode_ITE(): expr = ITE(x < 1, y, z) assert ccode(expr) == ("((x < 1) ? (\n" " y\n" ")\n" ": (\n" " z\n" "))")
def test_ccode_Indexed_without_looking_for_contraction(): len_y = 5 y = IndexedBase('y', shape=(len_y, )) x = IndexedBase('x', shape=(len_y, )) Dy = IndexedBase('Dy', shape=(len_y - 1, )) i = Idx('i', len_y - 1) e = Eq(Dy[i], (y[i + 1] - y[i]) / (x[i + 1] - x[i])) code0 = ccode(e.rhs, assign_to=e.lhs, contract=False) assert code0 == 'Dy[i] = (y[%s] - y[i])/(x[%s] - x[i]);' % (i + 1, i + 1)
def test_ccode_sinc(): from sympy.functions.elementary.trigonometric import sinc expr = sinc(x) assert ccode(expr) == ("((x != 0) ? (\n" " sin(x)/x\n" ")\n" ": (\n" " 1\n" "))")
def test_ccode_constants_mathh(): assert ccode(exp(1)) == "M_E" assert ccode(pi) == "M_PI" assert ccode(oo, standard='c89') == "HUGE_VAL" assert ccode(-oo, standard='c89') == "-HUGE_VAL" assert ccode(oo) == "INFINITY" assert ccode(-oo, standard='c99') == "-INFINITY" assert ccode(pi, type_aliases={real: float80}) == "M_PIl"
def test_create_expand_pow_optimization(): cc = lambda x: ccode(optimize(x, [create_expand_pow_optimization(4)])) x = Symbol('x') assert cc(x**4) == 'x*x*x*x' assert cc(x**4 + x**2) == 'x*x + x*x*x*x' assert cc(x**5 + x**4) == 'pow(x, 5) + x*x*x*x' assert cc(sin(x)**4) == 'pow(sin(x), 4)' # gh issue 15335 assert cc(x**(-4)) == '1.0/(x*x*x*x)' assert cc(x**(-5)) == 'pow(x, -5)' assert cc(-x**4) == '-x*x*x*x' assert cc(x**4 - x**2) == '-x*x + x*x*x*x' i = Symbol('i', integer=True) assert cc(x**i - x**2) == 'pow(x, i) - x*x' # gh issue 20753 cc2 = lambda x: ccode( optimize(x, [ create_expand_pow_optimization(4, base_req=lambda b: b.is_Function) ])) assert cc2(x**3 + sin(x)**3) == "pow(x, 3) + sin(x)*sin(x)*sin(x)"
def test_union(): vx, vy = Variable(x, type=float64), Variable(y, type=int64) u = union('dualuse', [vx, vy]) assert u.func(*u.args) == u assert u == union('dualuse', (vx, vy)) assert str(u.name) == 'dualuse' assert len(u.declarations) == 2 assert all(isinstance(arg, Declaration) for arg in u.declarations) assert ccode(u) == ("union dualuse {\n" " double x;\n" " int64_t y;\n" "}")
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_ccode_Declaration(): i = symbols('i', integer=True) var1 = Variable(i, type=Type.from_expr(i)) dcl1 = Declaration(var1) assert ccode(dcl1) == 'int i' var2 = Variable(x, type=float32, attrs={value_const}) dcl2a = Declaration(var2) assert ccode(dcl2a) == 'const float x' dcl2b = var2.as_Declaration(value=pi) assert ccode(dcl2b) == 'const float x = M_PI' var3 = Variable(y, type=Type('bool')) dcl3 = Declaration(var3) printer = C89CodePrinter() assert 'stdbool.h' not in printer.headers assert printer.doprint(dcl3) == 'bool y' assert 'stdbool.h' in printer.headers u = symbols('u', real=True) ptr4 = Pointer.deduced(u, attrs={pointer_const, restrict}) dcl4 = Declaration(ptr4) assert ccode(dcl4) == 'double * const restrict u' var5 = Variable(x, Type('__float128'), attrs={value_const}) dcl5a = Declaration(var5) assert ccode(dcl5a) == 'const __float128 x' var5b = Variable(var5.symbol, var5.type, pi, attrs=var5.attrs) dcl5b = Declaration(var5b) assert ccode(dcl5b) == 'const __float128 x = M_PI'
def test_ccode_Relational(): assert ccode(Eq(x, y)) == "x == y" assert ccode(Ne(x, y)) == "x != y" assert ccode(Le(x, y)) == "x <= y" assert ccode(Lt(x, y)) == "x < y" assert ccode(Gt(x, y)) == "x > y" assert ccode(Ge(x, y)) == "x >= y"
def test_struct(): vx, vy = Variable(x, type=float64), Variable(y, type=float64) s = struct('vec2', [vx, vy]) assert s.func(*s.args) == s assert s == struct('vec2', (vx, vy)) assert s != struct('vec2', (vy, vx)) assert str(s.name) == 'vec2' assert len(s.declarations) == 2 assert all(isinstance(arg, Declaration) for arg in s.declarations) assert ccode(s) == ("struct vec2 {\n" " double x;\n" " double y;\n" "}")
def test_goto_Label(): s = 'early_exit' g = goto(s) assert g.func(*g.args) == g assert g != goto('foobar') assert ccode(g) == 'goto early_exit' l1 = Label(s) assert ccode(l1) == 'early_exit:' assert l1 == Label('early_exit') assert l1 != Label('foobar') body = [PreIncrement(x)] l2 = Label(s, body) assert l2.name == String("early_exit") assert l2.body == CodeBlock(PreIncrement(x)) assert ccode(l2) == ("early_exit:\n" "++(x);") body = [PreIncrement(x), PreDecrement(y)] l2 = Label(s, body) assert l2.name == String("early_exit") assert l2.body == CodeBlock(PreIncrement(x), PreDecrement(y)) assert ccode(l2) == ("early_exit:\n" "{\n ++(x);\n --(y);\n}")
def test_Matrix_printing(): # Test returning a Matrix mat = Matrix([x * y, Piecewise((2 + x, y > 0), (y, True)), sin(z)]) A = MatrixSymbol('A', 3, 1) assert ccode(mat, A) == ("A[0] = x*y;\n" "if (y > 0) {\n" " A[1] = x + 2;\n" "}\n" "else {\n" " A[1] = y;\n" "}\n" "A[2] = sin(z);") # Test using MatrixElements in expressions expr = Piecewise((2 * A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0] assert ccode(expr) == ("((x > 0) ? (\n" " 2*A[2]\n" ")\n" ": (\n" " A[2]\n" ")) + sin(A[1]) + A[0]") # Test using MatrixElements in a Matrix q = MatrixSymbol('q', 5, 1) M = MatrixSymbol('M', 3, 3) m = Matrix([[sin(q[1, 0]), 0, cos(q[2, 0])], [q[1, 0] + q[2, 0], q[3, 0], 5], [2 * q[4, 0] / q[1, 0], sqrt(q[0, 0]) + 4, 0]]) assert ccode(m, M) == ("M[0] = sin(q[1]);\n" "M[1] = 0;\n" "M[2] = cos(q[2]);\n" "M[3] = q[1] + q[2];\n" "M[4] = q[3];\n" "M[5] = 5;\n" "M[6] = 2*q[4]/q[1];\n" "M[7] = sqrt(q[0]) + 4;\n" "M[8] = 0;")
def test_ccode_Piecewise(): expr = Piecewise((x, x < 1), (x**2, True)) assert ccode(expr) == ("((x < 1) ? (\n" " x\n" ")\n" ": (\n" " pow(x, 2)\n" "))") assert ccode(expr, assign_to="c") == ("if (x < 1) {\n" " c = x;\n" "}\n" "else {\n" " c = pow(x, 2);\n" "}") expr = Piecewise((x, x < 1), (x + 1, x < 2), (x**2, True)) assert ccode(expr) == ("((x < 1) ? (\n" " x\n" ")\n" ": ((x < 2) ? (\n" " x + 1\n" ")\n" ": (\n" " pow(x, 2)\n" ")))") assert ccode(expr, assign_to='c') == ("if (x < 1) {\n" " c = x;\n" "}\n" "else if (x < 2) {\n" " c = x + 1;\n" "}\n" "else {\n" " c = pow(x, 2);\n" "}") # Check that Piecewise without a True (default) condition error expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) raises(ValueError, lambda: ccode(expr))
def test_dummy_loops(): i, m = symbols('i m', integer=True, cls=Dummy) x = IndexedBase('x') y = IndexedBase('y') i = Idx(i, m) expected = ( 'for (int i_%(icount)i=0; i_%(icount)i<m_%(mcount)i; i_%(icount)i++){\n' ' y[i_%(icount)i] = x[i_%(icount)i];\n' '}') % { 'icount': i.label.dummy_index, 'mcount': m.dummy_index } assert ccode(x[i], assign_to=y[i]) == expected
def test_ccode_loops_matrix_vector(): n, m = symbols('n m', integer=True) A = IndexedBase('A') x = IndexedBase('x') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) s = ( '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] = A[%s]*x[j] + y[i];\n' % (i*n + j) +\ ' }\n' '}' ) assert ccode(A[i, j] * x[j], assign_to=y[i]) == s