def test_m_code_argument_order(): expr = x + y routine = make_routine('test', expr, argument_sequence=[z, x, y], language='octave') code_gen = OctaveCodeGen() output = io.StringIO() code_gen.dump_m([routine], output, 'test', header=False, empty=False) source = output.getvalue() expected = ('function out1 = test(z, x, y)\n' ' out1 = x + y;\n' 'end\n') assert source == expected pytest.raises( CodeGenArgumentListError, lambda: make_routine( 'test', expr, argument_sequence=[x], language='octave'))
def test_multiple_results_f(): expr1 = (x + y)*z expr2 = (x - y)*z routine = make_routine( "test", [expr1, expr2] ) code_gen = FCodeGen() pytest.raises(CodeGenError, lambda: get_string(code_gen.dump_h, [routine]))
def test_erf_f_code(): routine = make_routine("test", erf(x) - erf(-2 * x)) code_gen = FCodeGen() source = get_string(code_gen.dump_f95, [routine]) expected = ( "REAL*8 function test(x)\n" "implicit none\n" "REAL*8, intent(in) :: x\n" "test = erf(x) + erf(2.0d0*x)\n" "end function\n" ) assert source == expected, source
def test_cython_wrapper_scalar_function(): expr = (x + y) * z routine = make_routine('test', expr) code_gen = CythonCodeWrapper(CCodeGen()) source = get_string(code_gen.dump_pyx, [routine]) expected = ("cdef extern from 'file.h':\n" ' double test(double x, double y, double z)\n' '\n' 'def test_c(double x, double y, double z):\n' '\n' ' return test(x, y, z)') assert source == expected
def test_cython_wrapper_inoutarg(): code_gen = CythonCodeWrapper(CCodeGen()) routine = make_routine('test', Eq(z, x + y + z)) source = get_string(code_gen.dump_pyx, [routine]) expected = ("cdef extern from 'file.h':\n" ' void test(double x, double y, double *z)\n' '\n' 'def test_c(double x, double y, double z):\n' '\n' ' test(x, y, &z)\n' ' return z') assert source == expected
def test_m_code_argument_order(): expr = x + y routine = make_routine("test", expr, argument_sequence=[z, x, y], language="octave") code_gen = OctaveCodeGen() output = StringIO() code_gen.dump_m([routine], output, "test", header=False, empty=False) source = output.getvalue() expected = ("function out1 = test(z, x, y)\n" " out1 = x + y;\n" "end\n") assert source == expected
def test_simple_c_header(): expr = (x + y)*z routine = make_routine("test", expr) code_gen = CCodeGen() source = get_string(code_gen.dump_h, [routine]) expected = ( "#ifndef PROJECT__FILE__H\n" "#define PROJECT__FILE__H\n" "double test(double x, double y, double z);\n" "#endif\n" ) assert source == expected
def is_feasible(language, commands): # This test should always work, otherwise the compiler is not present. routine = make_routine("test", x) numerical_tests = [ ("test", ( 1.0,), 1.0, 1e-15), ("test", (-1.0,), -1.0, 1e-15), ] try: run_test("is_feasible", [routine], numerical_tests, language, commands, friendly=False) return True except AssertionError: return False
def test_cython_wrapper_scalar_function(): x, y, z = symbols('x,y,z') expr = (x + y) * z routine = make_routine("test", expr) code_gen = CythonCodeWrapper(CCodeGen()) source = get_string(code_gen.dump_pyx, [routine]) expected = ("cdef extern from 'file.h':\n" " double test(double x, double y, double z)\n" "\n" "def test_c(double x, double y, double z):\n" "\n" " return test(x, y, z)") assert source == expected
def test_numbersymbol_f_code(): routine = make_routine("test", pi**Catalan) code_gen = FCodeGen() source = get_string(code_gen.dump_f95, [routine]) expected = ( "REAL*8 function test()\n" "implicit none\n" "REAL*8, parameter :: Catalan = 0.915965594177219d0\n" "REAL*8, parameter :: pi = 3.14159265358979d0\n" "test = pi**Catalan\n" "end function\n" ) assert source == expected
def test_cython_wrapper_inoutarg(): code_gen = CythonCodeWrapper(CCodeGen()) routine = make_routine("test", Eq(z, x + y + z)) source = get_string(code_gen.dump_pyx, [routine]) expected = ( "cdef extern from 'file.h':\n" " void test(double x, double y, double *z)\n" "\n" "def test_c(double x, double y, double z):\n" "\n" " test(x, y, &z)\n" " return z") assert source == expected
def test_m_code_argument_order(): expr = x + y routine = make_routine("test", expr, argument_sequence=[z, x, y], language="octave") code_gen = OctaveCodeGen() output = StringIO() code_gen.dump_m([routine], output, "test", header=False, empty=False) source = output.getvalue() expected = ( "function out1 = test(z, x, y)\n" " out1 = x + y;\n" "end\n" ) assert source == expected
def test_cython_wrapper_scalar_function(): expr = (x + y)*z routine = make_routine("test", expr) code_gen = CythonCodeWrapper(CCodeGen()) source = get_string(code_gen.dump_pyx, [routine]) expected = ( "cdef extern from 'file.h':\n" " double test(double x, double y, double z)\n" "\n" "def test_c(double x, double y, double z):\n" "\n" " return test(x, y, z)") assert source == expected
def test_output_arg_f(): r = make_routine("foo", [Equality(y, sin(x)), cos(x)]) c = FCodeGen() result = c.write([r], "test", header=False, empty=False) assert result[0][0] == "test.f90" assert result[0][1] == ( 'REAL*8 function foo(x, y)\n' 'implicit none\n' 'REAL*8, intent(in) :: x\n' 'REAL*8, intent(out) :: y\n' 'y = sin(x)\n' 'foo = cos(x)\n' 'end function\n' )
def test_cython_wrapper_outarg(): code_gen = CythonCodeWrapper(CCodeGen()) routine = make_routine("test", Eq(z, x + y)) source = get_string(code_gen.dump_pyx, [routine]) expected = ("cdef extern from 'file.h':\n" " void test(double x, double y, double *z)\n" "\n" "def test_c(double x, double y):\n" "\n" " cdef double z = 0\n" " test(x, y, &z)\n" " return z") assert source == expected
def test_cython_wrapper_inoutarg(): from diofant import Equality x, y, z = symbols('x,y,z') code_gen = CythonCodeWrapper(CCodeGen()) routine = make_routine("test", Equality(z, x + y + z)) source = get_string(code_gen.dump_pyx, [routine]) expected = ("cdef extern from 'file.h':\n" " void test(double x, double y, double *z)\n" "\n" "def test_c(double x, double y, double z):\n" "\n" " test(x, y, &z)\n" " return z") assert source == expected
def test_simple_f_code(): expr = (x + y)*z routine = make_routine("test", expr) code_gen = FCodeGen() source = get_string(code_gen.dump_f95, [routine]) expected = ( "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" ) assert source == expected
def test_simple_c_code(): expr = (x + y)*z routine = make_routine("test", expr) code_gen = CCodeGen() source = get_string(code_gen.dump_c, [routine]) expected = ( "#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" ) assert source == expected
def test_numbersymbol_c_code(): routine = make_routine("test", pi**Catalan) code_gen = CCodeGen() source = get_string(code_gen.dump_c, [routine]) expected = ( "#include \"file.h\"\n" "#include <math.h>\n" "double test() {\n" " double test_result;\n" " double const Catalan = 0.915965594177219;\n" " test_result = pow(M_PI, Catalan);\n" " return test_result;\n" "}\n" ) assert source == expected
def test_f_code_argument_order(): expr = x + y routine = make_routine("test", expr, argument_sequence=[z, x, y]) code_gen = FCodeGen() source = get_string(code_gen.dump_f95, [routine]) expected = ( "REAL*8 function test(z, x, y)\n" "implicit none\n" "REAL*8, intent(in) :: z\n" "REAL*8, intent(in) :: x\n" "REAL*8, intent(in) :: y\n" "test = x + y\n" "end function\n" ) assert source == expected
def test_c_code_argument_order(): expr = x + y routine = make_routine("test", expr, argument_sequence=[z, x, y]) code_gen = CCodeGen() source = get_string(code_gen.dump_c, [routine]) expected = ( "#include \"file.h\"\n" "#include <math.h>\n" "double test(double z, double x, double y) {\n" " double test_result;\n" " test_result = x + y;\n" " return test_result;\n" "}\n" ) assert source == expected
def test_c_code_reserved_words(): if_, typedef_, while_ = symbols('if, typedef, while') expr = (if_ + typedef_) * while_ routine = make_routine("test", expr) code_gen = CCodeGen() source = get_string(code_gen.dump_c, [routine]) expected = ( "#include \"file.h\"\n" "#include <math.h>\n" "double test(double if_, double typedef_, double while_) {\n" " double test_result;\n" " test_result = while_*(if_ + typedef_);\n" " return test_result;\n" "}\n" ) assert source == expected
def test_output_arg_c(): r = make_routine("foo", [Equality(y, sin(x)), cos(x)]) c = CCodeGen() result = c.write([r], "test", header=False, empty=False) assert result[0][0] == "test.c" expected = ( '#include "test.h"\n' '#include <math.h>\n' 'double foo(double x, double *y) {\n' ' (*y) = sin(x);\n' ' double foo_result;\n' ' foo_result = cos(x);\n' ' return foo_result;\n' '}\n' ) assert result[0][1] == expected
def test_output_arg_c_reserved_words(): if_, while_ = symbols("if, while") r = make_routine("foo", [Equality(while_, sin(if_)), cos(if_)]) c = CCodeGen() result = c.write([r], "test", header=False, empty=False) assert result[0][0] == "test.c" expected = ( '#include "test.h"\n' '#include <math.h>\n' 'double foo(double if_, double *while_) {\n' ' (*while_) = sin(if_);\n' ' double foo_result;\n' ' foo_result = cos(if_);\n' ' return foo_result;\n' '}\n' ) assert result[0][1] == expected
def test_dummy_loops_c(): i, m = symbols('i m', integer=True, cls=Dummy) x = IndexedBase('x') y = IndexedBase('y') i = Idx(i, m) expected = ( '#include "file.h"\n' '#include <math.h>\n' 'void test_dummies(int m_%(mno)i, double *x, double *y) {\n' ' for (int i_%(ino)i=0; i_%(ino)i<m_%(mno)i; i_%(ino)i++){\n' ' y[i_%(ino)i] = x[i_%(ino)i];\n' ' }\n' '}\n' ) % {'ino': i.label.dummy_index, 'mno': m.dummy_index} r = make_routine('test_dummies', Eq(y[i], x[i])) c = CCodeGen() code = get_string(c.dump_c, [r]) assert code == expected
def test_dummy_loops_f95(): i, m = symbols('i m', integer=True, cls=Dummy) x = IndexedBase('x') y = IndexedBase('y') i = Idx(i, m) expected = ( 'subroutine test_dummies(m_%(mcount)i, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m_%(mcount)i\n' 'REAL*8, intent(in), dimension(1:m_%(mcount)i) :: x\n' 'REAL*8, intent(out), dimension(1:m_%(mcount)i) :: y\n' 'INTEGER*4 :: i_%(icount)i\n' 'do i_%(icount)i = 1, m_%(mcount)i\n' ' y(i_%(icount)i) = x(i_%(icount)i)\n' 'end do\n' 'end subroutine\n' ) % {'icount': i.label.dummy_index, 'mcount': m.dummy_index} r = make_routine('test_dummies', Eq(y[i], x[i])) c = FCodeGen() code = get_string(c.dump_f95, [r]) assert code == expected
def test_f_code_call_signature_wrap(): # Issue sympy/sympy#7934 x = symbols('x:20') expr = 0 for sym in x: expr += sym routine = make_routine("test", expr) code_gen = FCodeGen() source = get_string(code_gen.dump_f95, [routine]) expected = """\ REAL*8 function test(x0, x1, x10, x11, x12, x13, x14, x15, x16, x17, x18, & x19, x2, x3, x4, x5, x6, x7, x8, x9) implicit none REAL*8, intent(in) :: x0 REAL*8, intent(in) :: x1 REAL*8, intent(in) :: x10 REAL*8, intent(in) :: x11 REAL*8, intent(in) :: x12 REAL*8, intent(in) :: x13 REAL*8, intent(in) :: x14 REAL*8, intent(in) :: x15 REAL*8, intent(in) :: x16 REAL*8, intent(in) :: x17 REAL*8, intent(in) :: x18 REAL*8, intent(in) :: x19 REAL*8, intent(in) :: x2 REAL*8, intent(in) :: x3 REAL*8, intent(in) :: x4 REAL*8, intent(in) :: x5 REAL*8, intent(in) :: x6 REAL*8, intent(in) :: x7 REAL*8, intent(in) :: x8 REAL*8, intent(in) :: x9 test = x0 + x1 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + & x19 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 end function """ assert source == expected
def test_inline_function(): n, m = symbols('n m', integer=True) A, x, y = map(IndexedBase, 'Axy') i = Idx('i', m) p = FCodeGen() func = implemented_function('func', Lambda(n, n*(n + 1))) routine = make_routine('test_inline', Eq(y[i], func(x[i]))) code = get_string(p.dump_f95, [routine]) expected = ( 'subroutine test_inline(m, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'REAL*8, intent(in), dimension(1:m) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'do i = 1, m\n' ' y(i) = %s*%s\n' 'end do\n' 'end subroutine\n' ) args = ('x(i)', '(x(i) + 1)') assert code == expected % args or\ code == expected % args[::-1]
def test_Routine_argument_order(): expr = (x + y)*z pytest.raises(CodeGenArgumentListError, lambda: make_routine("test", expr, argument_sequence=[z, x])) pytest.raises(CodeGenArgumentListError, lambda: make_routine("test", Eq(a, expr), argument_sequence=[z, x, y])) r = make_routine('test', Eq(a, expr), argument_sequence=[z, x, a, y]) assert [ arg.name for arg in r.arguments ] == [z, x, a, y] assert [ type(arg) for arg in r.arguments ] == [ InputArgument, InputArgument, OutputArgument, InputArgument ] r = make_routine('test', Eq(z, expr), argument_sequence=[z, x, y]) assert [ type(arg) for arg in r.arguments ] == [ InOutArgument, InputArgument, InputArgument ] A, B = map(IndexedBase, ['A', 'B']) m = symbols('m', integer=True) i = Idx('i', m) r = make_routine('test', Eq(A[i], B[i]), argument_sequence=[B, A, m]) assert [ arg.name for arg in r.arguments ] == [B.label, A.label, m] expr = Integral(x*y*z, (x, 1, 2), (y, 1, 3)) r = make_routine('test', Eq(a, expr), argument_sequence=[z, x, a, y]) assert [ arg.name for arg in r.arguments ] == [z, x, a, y]
def test_no_results_f(): pytest.raises(ValueError, lambda: make_routine("test", []))
def autowrap(expr, language=None, backend='f2py', tempdir=None, args=None, flags=None, verbose=False, helpers=None): """Generates python callable binaries based on the math expression. Parameters ---------- expr The Diofant expression that should be wrapped as a binary routine. language : string, optional If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If ``None`` [default], the language is inferred based upon the specified backend. backend : string, optional Backend used to wrap the generated code. Either 'f2py' [default], or 'cython'. tempdir : string, optional Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path. args : iterable, optional An iterable of symbols. Specifies the argument sequence for the function. flags : iterable, optional Additional option flags that will be passed to the backend. verbose : bool, optional If True, autowrap will not mute the command line backends. This can be helpful for debugging. helpers : iterable, optional Used to define auxillary expressions needed for the main expr. If the main expression needs to call a specialized function it should be put in the ``helpers`` iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be tuples with (<funtion_name>, <diofant_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines. Examples -------- >>> from diofant.abc import x, y, z >>> from diofant.utilities.autowrap import autowrap >>> expr = ((x - y + z)**(13)).expand() >>> binary_func = autowrap(expr) >>> binary_func(1, 4, 2) -1.0 """ if language: _validate_backend_language(backend, language) else: language = _infer_language(backend) helpers = [helpers] if helpers else () flags = flags if flags else () code_generator = get_code_generator(language, "autowrap") CodeWrapperClass = _get_code_wrapper_class(backend) code_wrapper = CodeWrapperClass(code_generator, tempdir, flags, verbose) helps = [] for name_h, expr_h, args_h in helpers: helps.append(make_routine(name_h, expr_h, args_h)) for name_h, expr_h, args_h in helpers: if expr.has(expr_h): name_h = binary_function(name_h, expr_h, backend='dummy') expr = expr.subs(expr_h, name_h(*args_h)) try: routine = make_routine('autofunc', expr, args) except CodeGenArgumentListError as e: # if all missing arguments are for pure output, we simply attach them # at the end and try again, because the wrappers will silently convert # them to return values anyway. new_args = [] for missing in e.missing_args: if not isinstance(missing, OutputArgument): raise new_args.append(missing.name) routine = make_routine('autofunc', expr, list(args) + new_args) return code_wrapper.wrap_code(routine, helpers=helps)
def ufuncify(args, expr, language=None, backend='numpy', tempdir=None, flags=None, verbose=False, helpers=None): """ Generates a binary function that supports broadcasting on numpy arrays. Parameters ---------- args : iterable Either a Symbol or an iterable of symbols. Specifies the argument sequence for the function. expr A Diofant expression that defines the element wise operation. language : string, optional If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If ``None`` [default], the language is inferred based upon the specified backend. backend : string, optional Backend used to wrap the generated code. Either 'numpy' [default], 'cython', or 'f2py'. tempdir : string, optional Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path. flags : iterable, optional Additional option flags that will be passed to the backend verbose : bool, optional If True, autowrap will not mute the command line backends. This can be helpful for debugging. helpers : iterable, optional Used to define auxillary expressions needed for the main expr. If the main expression needs to call a specialized function it should be put in the ``helpers`` iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be tuples with (<funtion_name>, <diofant_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines. Notes ----- The default backend ('numpy') will create actual instances of ``numpy.ufunc``. These support ndimensional broadcasting, and implicit type conversion. Use of the other backends will result in a "ufunc-like" function, which requires equal length 1-dimensional arrays for all arguments, and will not perform any type conversions. References ---------- .. [1] http://docs.scipy.org/doc/numpy/reference/ufuncs.html Examples -------- >>> from diofant.utilities.autowrap import ufuncify >>> from diofant.abc import x, y >>> import numpy as np >>> f = ufuncify((x, y), y + x**2) >>> type(f) is np.ufunc True >>> f([1, 2, 3], 2) array([ 3., 6., 11.]) >>> f(np.arange(5), 3) array([ 3., 4., 7., 12., 19.]) For the F2Py and Cython backends, inputs are required to be equal length 1-dimensional arrays. The F2Py backend will perform type conversion, but the Cython backend will error if the inputs are not of the expected type. >>> f_fortran = ufuncify((x, y), y + x**2, backend='F2Py') >>> f_fortran(1, 2) 3 >>> f_fortran(numpy.array([1, 2, 3]), numpy.array([1.0, 2.0, 3.0])) array([2., 6., 12.]) >>> f_cython = ufuncify((x, y), y + x**2, backend='Cython') >>> f_cython(1, 2) Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(numpy.array([1.0]), numpy.array([2.0])) array([ 3.]) """ if isinstance(args, (Dummy, Symbol)): args = (args, ) else: args = tuple(args) if language: _validate_backend_language(backend, language) else: language = _infer_language(backend) helpers = helpers if helpers else () flags = flags if flags else () if backend.upper() == 'NUMPY': routine = make_routine('autofunc', expr, args) helps = [] for name, expr, args in helpers: helps.append(make_routine(name, expr, args)) code_wrapper = UfuncifyCodeWrapper(CCodeGen("ufuncify"), tempdir, flags, verbose) return code_wrapper.wrap_code(routine, helpers=helps) else: # Dummies are used for all added expressions to prevent name clashes # within the original expression. y = IndexedBase(Dummy()) m = Dummy(integer=True) i = Idx(Dummy(integer=True), m) f = implemented_function(Dummy().name, Lambda(args, expr)) # For each of the args create an indexed version. indexed_args = [IndexedBase(Dummy(str(a))) for a in args] # Order the arguments (out, args, dim) args = [y] + indexed_args + [m] args_with_indices = [a[i] for a in indexed_args] return autowrap(Eq(y[i], f(*args_with_indices)), language, backend, tempdir, tuple(args), flags, verbose, helpers)
def test_ufuncify_source(): code_wrapper = UfuncifyCodeWrapper(CCodeGen("ufuncify")) routine = make_routine("test", x + y + z) source = get_string(code_wrapper.dump_c, [routine]) expected = """\ #include "Python.h" #include "math.h" #include "numpy/ndarraytypes.h" #include "numpy/ufuncobject.h" #include "numpy/halffloat.h" #include "file.h" static PyMethodDef wrapper_module_%(num)sMethods[] = { {NULL, NULL, 0, NULL} }; static void test_ufunc(char **args, npy_intp *dimensions, npy_intp* steps, void* data) { npy_intp i; npy_intp n = dimensions[0]; char *in0 = args[0]; char *in1 = args[1]; char *in2 = args[2]; char *out1 = args[3]; npy_intp in0_step = steps[0]; npy_intp in1_step = steps[1]; npy_intp in2_step = steps[2]; npy_intp out1_step = steps[3]; for (i = 0; i < n; i++) { *((double *)out1) = test(*(double *)in0, *(double *)in1, *(double *)in2); in0 += in0_step; in1 += in1_step; in2 += in2_step; out1 += out1_step; } } PyUFuncGenericFunction test_funcs[1] = {&test_ufunc}; static char test_types[4] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; static void *test_data[1] = {NULL}; #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "wrapper_module_%(num)s", NULL, -1, wrapper_module_%(num)sMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_wrapper_module_%(num)s(void) { PyObject *m, *d; PyObject *ufunc0; m = PyModule_Create(&moduledef); if (!m) { return NULL; } import_array(); import_umath(); d = PyModule_GetDict(m); ufunc0 = PyUFunc_FromFuncAndData(test_funcs, test_data, test_types, 1, 3, 1, PyUFunc_None, "wrapper_module_%(num)s", "Created in Diofant with Ufuncify", 0); PyDict_SetItemString(d, "test", ufunc0); Py_DECREF(ufunc0); return m; } #else PyMODINIT_FUNC initwrapper_module_%(num)s(void) { PyObject *m, *d; PyObject *ufunc0; m = Py_InitModule("wrapper_module_%(num)s", wrapper_module_%(num)sMethods); if (m == NULL) { return; } import_array(); import_umath(); d = PyModule_GetDict(m); ufunc0 = PyUFunc_FromFuncAndData(test_funcs, test_data, test_types, 1, 3, 1, PyUFunc_None, "wrapper_module_%(num)s", "Created in Diofant with Ufuncify", 0); PyDict_SetItemString(d, "test", ufunc0); Py_DECREF(ufunc0); } #endif""" % {'num': CodeWrapper._module_counter} assert source == expected
def test_ufuncify_source(): code_wrapper = UfuncifyCodeWrapper(CCodeGen('ufuncify')) routine = make_routine('test', x + y + z) source = get_string(code_wrapper.dump_c, [routine]) expected = """\ #include "Python.h" #include "math.h" #include "numpy/ndarraytypes.h" #include "numpy/ufuncobject.h" #include "numpy/halffloat.h" #include "file.h" static PyMethodDef wrapper_module_%(num)sMethods[] = { {NULL, NULL, 0, NULL} }; static void test_ufunc(char **args, npy_intp *dimensions, npy_intp* steps, void* data) { npy_intp i; npy_intp n = dimensions[0]; char *in0 = args[0]; char *in1 = args[1]; char *in2 = args[2]; char *out1 = args[3]; npy_intp in0_step = steps[0]; npy_intp in1_step = steps[1]; npy_intp in2_step = steps[2]; npy_intp out1_step = steps[3]; for (i = 0; i < n; i++) { *((double *)out1) = test(*(double *)in0, *(double *)in1, *(double *)in2); in0 += in0_step; in1 += in1_step; in2 += in2_step; out1 += out1_step; } } PyUFuncGenericFunction test_funcs[1] = {&test_ufunc}; static char test_types[4] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; static void *test_data[1] = {NULL}; #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "wrapper_module_%(num)s", NULL, -1, wrapper_module_%(num)sMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_wrapper_module_%(num)s(void) { PyObject *m, *d; PyObject *ufunc0; m = PyModule_Create(&moduledef); if (!m) { return NULL; } import_array(); import_umath(); d = PyModule_GetDict(m); ufunc0 = PyUFunc_FromFuncAndData(test_funcs, test_data, test_types, 1, 3, 1, PyUFunc_None, "wrapper_module_%(num)s", "Created in Diofant with Ufuncify", 0); PyDict_SetItemString(d, "test", ufunc0); Py_DECREF(ufunc0); return m; } #else PyMODINIT_FUNC initwrapper_module_%(num)s(void) { PyObject *m, *d; PyObject *ufunc0; m = Py_InitModule("wrapper_module_%(num)s", wrapper_module_%(num)sMethods); if (m == NULL) { return; } import_array(); import_umath(); d = PyModule_GetDict(m); ufunc0 = PyUFunc_FromFuncAndData(test_funcs, test_data, test_types, 1, 3, 1, PyUFunc_None, "wrapper_module_%(num)s", "Created in Diofant with Ufuncify", 0); PyDict_SetItemString(d, "test", ufunc0); Py_DECREF(ufunc0); } #endif""" % { 'num': CodeWrapper._module_counter } # noqa: SFS101 assert source == expected