示例#1
0
def autowrap(
    expr, language='F95', backend='f2py', tempdir=None, args=None, flags=[],
        verbose=False, helpers=[]):
    """Generates python callable binaries based on the math expression.

    expr
        The SymPy expression that should be wrapped as a binary routine

    :Optional arguments:

    language
        The programming language to use, currently 'C' or 'F95'
    backend
        The wrapper backend to use, currently f2py or Cython
    tempdir
        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
        Sequence of the formal parameters of the generated code, if ommited the
        function signature is determined by the code generator.
    flags
        Additional option flags that will be passed to the backend
    verbose
        If True, autowrap will not mute the command line backends.  This can be
        helpful for debugging.
    helpers
        Used to define auxillary expressions needed for the main expr.  If the
        main expression need to do call a specialized function it should be put
        in the ``helpers`` list.  Autowrap will then make sure that the compiled
        main expression can link to the helper routine.  Items should be tuples
        with (<funtion_name>, <sympy_expression>, <arguments>).  It is
        mandatory to supply an argument sequence to helper routines.

    >>> from sympy.abc import x, y, z
    >>> from sympy.utilities.autowrap import autowrap
    >>> expr = ((x - y + z)**(13)).expand()
    >>> binary_func = autowrap(expr)               # doctest: +SKIP
    >>> binary_func(1, 4, 2)                       # doctest: +SKIP
    -1.0

    """

    code_generator = get_code_generator(language, "autowrap")
    CodeWrapperClass = _get_code_wrapper_class(backend)
    code_wrapper = CodeWrapperClass(code_generator, tempdir, flags, verbose)
    try:
        routine = Routine('autofunc', expr, args)
    except CodeGenArgumentListError, 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 = Routine('autofunc', expr, args + new_args)
示例#2
0
def generate_c_func(name, expr, in_args, column_major_storage=True, **kwargs):
    """ generates C function code for a sympy exrpession
        name is the name of the function
        expr is the matrix expression
        in_args is a list of tuples containing a variable-name string and the
        variable symbol. The symbol can be a matrix or a scalar.
        The sequence of the arguments will be the sequence of in_args and the
        output (called 'out') is last
    """
    if column_major_storage:
        # generated C code matrix access is in row-major order
        # [source: sympy/printing/ccode.py:215, _print_MatrixElement()]
        # this is why we transpose the matrices in column-major mode
        expr = expr.transpose()

    subs_tab = []
    arg_list = []

    for argname, arg_sym in in_args:
        if isinstance(arg_sym, sp.Matrix):
            if column_major_storage:
                arg_sym = arg_sym.transpose()
            new_sym = sp.MatrixSymbol('__in__' + argname, *arg_sym.shape)
            subs_tab += sympy_util.matrix_subs(arg_sym, new_sym)
            arg_list.append(cg.InputArgument(new_sym, dimensions=new_sym.shape))
        else:
            new_sym = sp.symbols(argname)
            subs_tab.append((arg_sym, new_sym))
            arg_list.append(cg.InputArgument(new_sym))

    out_sym = sp.MatrixSymbol('out', expr.shape[0], expr.shape[1])
    out_arg = cg.OutputArgument(out_sym, out_sym, expr.subs(subs_tab), dimensions=out_sym.shape)
    arg_list.append(out_arg)

    no_return_val = []
    no_local_vars = []
    no_global_vars = []

    code_gen = cg.get_code_generator("C", "projectname")
    routines = [cg.Routine(name, arg_list, no_return_val, no_local_vars, no_global_vars)]
    [(c_name, c_code), (h_name, c_header)] = code_gen.write(routines, "prefix", header=False)

    c_code = unused_param_warn_suppr(c_code, [argname for argname, _sym in in_args])
    c_code = clean_c_code(c_code, **kwargs)

    return c_code
示例#3
0
def run_test(label, routines, numerical_tests, language, commands, friendly=True):
    """A driver for the codegen tests.

       This driver assumes that a compiler ifort is present in the PATH and that
       ifort is (at least) a Fortran 90 compiler. The generated code is written in
       a temporary directory, together with a main program that validates the
       generated code. The test passes when the compilation and the validation
       run correctly.
    """

    # Check input arguments before touching the file system
    language = language.upper()
    assert language in main_template
    assert language in numerical_test_template

    # Check that evironment variable makes sense
    clean = os.getenv('SYMPY_TEST_CLEAN_TEMP', 'always').lower()
    if clean not in ('always', 'success', 'never'):
        raise ValueError("SYMPY_TEST_CLEAN_TEMP must be one of the following: 'always', 'success' or 'never'.")

    # Do all the magic to compile, run and validate the test code
    # 1) prepare the temporary working directory, switch to that dir
    work = tempfile.mkdtemp("_sympy_%s_test" % language, "%s_" % label)
    oldwork = os.getcwd()
    os.chdir(work)

    # 2) write the generated code
    if friendly:
        # interpret the routines as a name_expr list and call the friendly
        # function codegen
        codegen(routines, language, "codegen", to_files=True)
    else:
        code_gen = get_code_generator(language, "codegen")
        code_gen.write(routines, "codegen", to_files=True)

    # 3) write a simple main program that links to the generated code, and that
    #    includes the numerical tests
    test_strings = []
    for fn_name, args, expected, threshold in numerical_tests:
        call_string = "%s(%s)-(%s)" % (fn_name, ",".join(str(arg) for arg in args), expected)
        if language == "F95":
            call_string = fortranize_double_constants(call_string)
            threshold = fortranize_double_constants(str(threshold))
        test_strings.append(numerical_test_template[language] % {
            "call": call_string,
            "threshold": threshold,
        })

    if language == "F95":
        f = file("main.f90", "w")
    elif language == "C":
        f = file("main.c", "w")
    else:
        raise NotImplemented(
                "FIXME: filename extension unknown for language: %s"%language)
    f.write(main_template[language] % {'statements': "".join(test_strings)})
    f.close()

    # 4) Compile and link
    compiled = try_run(commands)

    # 5) Run if compiled
    if compiled:
        executed = try_run(["./test.exe"])
    else:
        executed = False

    # 6) Clean up stuff
    if clean == 'always' or (clean == 'success' and compiled and executed):
        def safe_remove(filename):
            if os.path.isfile(filename):
                os.remove(filename)
        safe_remove("codegen.f90")
        safe_remove("codegen.c")
        safe_remove("codegen.h")
        safe_remove("codegen.o")
        safe_remove("main.f90")
        safe_remove("main.c")
        safe_remove("main.o")
        safe_remove("test.exe")
        os.chdir(oldwork)
        os.rmdir(work)
    else:
        print >> sys.stderr, "TEST NOT REMOVED: %s" % work
        os.chdir(oldwork)

    # 7) Do the assertions in the end
    assert compiled, "failed to compile %s code with:\n%s" %(language, "\n".join(commands))
    assert executed, "failed to execute %s code from:\n%s" %(language, "\n".join(commands))
示例#4
0
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 SymPy 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 ordered 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>, <sympy_expression>, <arguments>). It
        is mandatory to supply an argument sequence to helper routines.

    >>> from sympy.abc import x, y, z
    >>> from sympy.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 ()
    args = list(args) if iterable(args, exclude=set) else args

    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, args + new_args)

    return code_wrapper.wrap_code(routine, helpers=helps)
示例#5
0
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 SymPy 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>, <sympy_expression>, <arguments>). It
        is mandatory to supply an argument sequence to helper routines.

    >>> from sympy.abc import x, y, z
    >>> from sympy.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)
    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, args + new_args)

    helps = []
    for name, expr, args in helpers:
        helps.append(make_routine(name, expr, args))

    return code_wrapper.wrap_code(routine, helpers=helps)
示例#6
0
文件: autowrap.py 项目: cklb/sympy
def autowrap(expr, language=None, backend='f2py', tempdir=None, args=None,
             flags=None, verbose=False, helpers=None, code_gen=None, **kwargs):
    """Generates python callable binaries based on the math expression.

    Parameters
    ==========

    expr
        The SymPy 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 ordered 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 : 3-tuple or iterable of 3-tuples, optional
        Used to define auxiliary expressions needed for the main expr. If the
        main expression needs to call a specialized function it should be
        passed in via ``helpers``. Autowrap will then make sure that the
        compiled main expression can link to the helper routine. Items should
        be 3-tuples with (<function_name>, <sympy_expression>,
        <argument_tuple>). It is mandatory to supply an argument sequence to
        helper routines.
    code_gen : CodeGen instance
        An instance of a CodeGen subclass. Overrides ``language``.
    include_dirs : [string]
        A list of directories to search for C/C++ header files (in Unix form
        for portability).
    library_dirs : [string]
        A list of directories to search for C/C++ libraries at link time.
    libraries : [string]
        A list of library names (not filenames or paths) to link against.
    extra_compile_args : [string]
        Any extra platform- and compiler-specific information to use when
        compiling the source files in 'sources'.  For platforms and compilers
        where "command line" makes sense, this is typically a list of
        command-line arguments, but for other platforms it could be anything.
    extra_link_args : [string]
        Any extra platform- and compiler-specific information to use when
        linking object files together to create the extension (or to create a
        new static Python interpreter).  Similar interpretation as for
        'extra_compile_args'.

    Examples
    ========

    >>> from sympy.abc import x, y, z
    >>> from sympy.utilities.autowrap import autowrap
    >>> expr = ((x - y + z)**(13)).expand()
    >>> binary_func = autowrap(expr)
    >>> binary_func(1, 4, 2)
    -1.0

    """
    if language:
        if not isinstance(language, type):
            _validate_backend_language(backend, language)
    else:
        language = _infer_language(backend)

    # two cases 1) helpers is an iterable of 3-tuples and 2) helpers is a
    # 3-tuple
    if iterable(helpers) and len(helpers) != 0 and iterable(helpers[0]):
        helpers = helpers if helpers else ()
    else:
        helpers = [helpers] if helpers else ()
    args = list(args) if iterable(args, exclude=set) else args

    if code_gen is None:
        code_gen = get_code_generator(language, "autowrap")

    CodeWrapperClass = {
        'F2PY': F2PyCodeWrapper,
        'CYTHON': CythonCodeWrapper,
        'DUMMY': DummyWrapper
    }[backend.upper()]
    code_wrapper = CodeWrapperClass(code_gen, tempdir, flags if flags else (),
                                    verbose, **kwargs)

    helps = []
    for name_h, expr_h, args_h in helpers:
        helps.append(code_gen.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 = code_gen.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 = code_gen.routine('autofunc', expr, args + new_args)

    return code_wrapper.wrap_code(routine, helpers=helps)
示例#7
0
def run_test(label, routines, numerical_tests, language, commands, friendly=True):
    """A driver for the codegen tests.

       This driver assumes that a compiler ifort is present in the PATH and that
       ifort is (at least) a Fortran 90 compiler. The generated code is written in
       a temporary directory, together with a main program that validates the
       generated code. The test passes when the compilation and the validation
       run correctly.
    """

    # Check input arguments before touching the file system
    language = language.upper()
    assert language in main_template
    assert language in numerical_test_template

    # Check that environment variable makes sense
    clean = os.getenv('SYMPY_TEST_CLEAN_TEMP', 'always').lower()
    if clean not in ('always', 'success', 'never'):
        raise ValueError("SYMPY_TEST_CLEAN_TEMP must be one of the following: 'always', 'success' or 'never'.")

    # Do all the magic to compile, run and validate the test code
    # 1) prepare the temporary working directory, switch to that dir
    work = tempfile.mkdtemp("_sympy_%s_test" % language, "%s_" % label)
    oldwork = os.getcwd()
    os.chdir(work)

    # 2) write the generated code
    if friendly:
        # interpret the routines as a name_expr list and call the friendly
        # function codegen
        codegen(routines, language, "codegen", to_files=True)
    else:
        code_gen = get_code_generator(language, "codegen")
        code_gen.write(routines, "codegen", to_files=True)

    # 3) write a simple main program that links to the generated code, and that
    #    includes the numerical tests
    test_strings = []
    for fn_name, args, expected, threshold in numerical_tests:
        call_string = "%s(%s)-(%s)" % (
            fn_name, ",".join(str(arg) for arg in args), expected)
        if language == "F95":
            call_string = fortranize_double_constants(call_string)
            threshold = fortranize_double_constants(str(threshold))
        test_strings.append(numerical_test_template[language] % {
            "call": call_string,
            "threshold": threshold,
        })

    if language == "F95":
        f_name = "main.f90"
    elif language.startswith("C"):
        f_name = "main.c"
    else:
        raise NotImplementedError(
            "FIXME: filename extension unknown for language: %s" % language)

    with open(f_name, "w") as f:
        f.write(
            main_template[language] % {'statements': "".join(test_strings)})

    # 4) Compile and link
    compiled = try_run(commands)

    # 5) Run if compiled
    if compiled:
        executed = try_run(["./test.exe"])
    else:
        executed = False

    # 6) Clean up stuff
    if clean == 'always' or (clean == 'success' and compiled and executed):
        def safe_remove(filename):
            if os.path.isfile(filename):
                os.remove(filename)
        safe_remove("codegen.f90")
        safe_remove("codegen.c")
        safe_remove("codegen.h")
        safe_remove("codegen.o")
        safe_remove("main.f90")
        safe_remove("main.c")
        safe_remove("main.o")
        safe_remove("test.exe")
        os.chdir(oldwork)
        os.rmdir(work)
    else:
        print("TEST NOT REMOVED: %s" % work, file=sys.stderr)
        os.chdir(oldwork)

    # 7) Do the assertions in the end
    assert compiled, "failed to compile %s code with:\n%s" % (
        language, "\n".join(commands))
    assert executed, "failed to execute %s code from:\n%s" % (
        language, "\n".join(commands))
示例#8
0
def autowrap(expr,
             language=None,
             backend='f2py',
             tempdir=None,
             args=None,
             flags=None,
             verbose=False,
             helpers=None,
             code_gen=None,
             **kwargs):
    """Generates python callable binaries based on the math expression.

    Parameters
    ==========

    expr
        The SymPy 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 ordered 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 : 3-tuple or iterable of 3-tuples, optional
        Used to define auxiliary expressions needed for the main expr. If the
        main expression needs to call a specialized function it should be
        passed in via ``helpers``. Autowrap will then make sure that the
        compiled main expression can link to the helper routine. Items should
        be 3-tuples with (<function_name>, <sympy_expression>,
        <argument_tuple>). It is mandatory to supply an argument sequence to
        helper routines.
    code_gen : CodeGen instance
        An instance of a CodeGen subclass. Overrides ``language``.
    include_dirs : [string]
        A list of directories to search for C/C++ header files (in Unix form
        for portability).
    library_dirs : [string]
        A list of directories to search for C/C++ libraries at link time.
    libraries : [string]
        A list of library names (not filenames or paths) to link against.
    extra_compile_args : [string]
        Any extra platform- and compiler-specific information to use when
        compiling the source files in 'sources'.  For platforms and compilers
        where "command line" makes sense, this is typically a list of
        command-line arguments, but for other platforms it could be anything.
    extra_link_args : [string]
        Any extra platform- and compiler-specific information to use when
        linking object files together to create the extension (or to create a
        new static Python interpreter).  Similar interpretation as for
        'extra_compile_args'.

    Examples
    ========

    >>> from sympy.abc import x, y, z
    >>> from sympy.utilities.autowrap import autowrap
    >>> expr = ((x - y + z)**(13)).expand()
    >>> binary_func = autowrap(expr)
    >>> binary_func(1, 4, 2)
    -1.0

    """
    if language:
        if not isinstance(language, type):
            _validate_backend_language(backend, language)
    else:
        language = _infer_language(backend)

    # two cases 1) helpers is an iterable of 3-tuples and 2) helpers is a
    # 3-tuple
    if iterable(helpers) and len(helpers) != 0 and iterable(helpers[0]):
        helpers = helpers if helpers else ()
    else:
        helpers = [helpers] if helpers else ()
    args = list(args) if iterable(args, exclude=set) else args

    if code_gen is None:
        code_gen = get_code_generator(language, "autowrap")

    CodeWrapperClass = {
        'F2PY': F2PyCodeWrapper,
        'CYTHON': CythonCodeWrapper,
        'DUMMY': DummyWrapper
    }[backend.upper()]
    code_wrapper = CodeWrapperClass(code_gen, tempdir, flags if flags else (),
                                    verbose, **kwargs)

    helps = []
    for name_h, expr_h, args_h in helpers:
        helps.append(code_gen.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 = code_gen.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 = code_gen.routine('autofunc', expr, args + new_args)

    return code_wrapper.wrap_code(routine, helpers=helps)
示例#9
0
文件: autowrap.py 项目: vperic/sympy
def autowrap(expr,
             language='F95',
             backend='f2py',
             tempdir=None,
             args=None,
             flags=[],
             verbose=False,
             helpers=[]):
    """Generates python callable binaries based on the math expression.

    expr
        The SymPy expression that should be wrapped as a binary routine

    :Optional arguments:

    language
        The programming language to use, currently 'C' or 'F95'
    backend
        The wrapper backend to use, currently f2py or Cython
    tempdir
        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
        Sequence of the formal parameters of the generated code, if ommited the
        function signature is determined by the code generator.
    flags
        Additional option flags that will be passed to the backend
    verbose
        If True, autowrap will not mute the command line backends.  This can be
        helpful for debugging.
    helpers
        Used to define auxillary expressions needed for the main expr.  If the
        main expression need to do call a specialized function it should be put
        in the ``helpers`` list.  Autowrap will then make sure that the compiled
        main expression can link to the helper routine.  Items should be tuples
        with (<funtion_name>, <sympy_expression>, <arguments>).  It is
        mandatory to supply an argument sequence to helper routines.

    >>> from sympy.abc import x, y, z
    >>> from sympy.utilities.autowrap import autowrap
    >>> expr = ((x - y + z)**(13)).expand()
    >>> binary_func = autowrap(expr)               # doctest: +SKIP
    >>> binary_func(1, 4, 2)                       # doctest: +SKIP
    -1.0

    """

    code_generator = get_code_generator(language, "autowrap")
    CodeWrapperClass = _get_code_wrapper_class(backend)
    code_wrapper = CodeWrapperClass(code_generator, tempdir, flags, verbose)
    try:
        routine = Routine('autofunc', expr, args)
    except CodeGenArgumentListError, 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 = Routine('autofunc', expr, args + new_args)
def ekf_generate_c_code(f, F, h, H, x, u, f_additional_in=[], h_additional_in=[]):

    # generated C code matrix access is in row-major order
    # [source: sympy/printing/ccode.py:215, _print_MatrixElement()]
    # Since Eigen uses column-major by default we transpose the matrices before
    # generating the C code
    H = H.transpose()
    F = F.transpose()

    f_additional_in_sym = [sp.symbols('in{}_{}'.format(i+2, var.name)) for i, var in enumerate(f_additional_in)]
    f_add_subs_tab = list(zip(f_additional_in, f_additional_in_sym))
    h_additional_in_sym = [sp.symbols('in{}_{}'.format(i+1, var.name)) for i, var in enumerate(h_additional_in)]
    h_add_subs_tab = list(zip(h_additional_in, h_additional_in_sym))
    x_sym = sp.MatrixSymbol('in0_x', len(x), 1)
    x_subs_tab = [(elem_sym, x_sym[i, 0]) for i, elem_sym in enumerate(x)]
    u_sym = sp.MatrixSymbol('in1_u', len(u), 1)
    u_subs_tab = [(elem_sym, u_sym[i, 0]) for i, elem_sym in enumerate(u)]

    subs_tab = x_subs_tab + u_subs_tab + f_add_subs_tab + h_add_subs_tab

    # c_code  = generate_c_code('f', f.subs(subs_tab)) + '\n'
    # c_code += generate_c_code('F', F.subs(subs_tab)) + '\n'
    # c_code += generate_c_code('h', h.subs(subs_tab)) + '\n'
    # c_code += generate_c_code('H', H.subs(subs_tab)) + '\n'

    no_return_val = []
    no_local_vars = []

    f_additional_in_arg = [cg.InputArgument(sym) for sym in f_additional_in_sym]
    h_additional_in_arg = [cg.InputArgument(sym) for sym in h_additional_in_sym]

    f_out_sym = sp.MatrixSymbol('f_out', len(x), 1)
    f_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape),
                  cg.InputArgument(u_sym, dimensions=u_sym.shape)]
    f_arg_list += f_additional_in_arg
    f_arg_list += [cg.OutputArgument(f_out_sym, f_out_sym, f.subs(subs_tab), dimensions=f_out_sym.shape)]

    F_out_sym = sp.MatrixSymbol('F_out', F.shape[0], F.shape[1])
    F_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape),
                  cg.InputArgument(u_sym, dimensions=u_sym.shape)]
    F_arg_list += f_additional_in_arg
    F_arg_list += [cg.OutputArgument(F_out_sym, F_out_sym, F.subs(subs_tab), dimensions=F_out_sym.shape)]

    h_out_sym = sp.MatrixSymbol('h_out', len(h), 1)
    h_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape)]
    h_arg_list += h_additional_in_arg
    h_arg_list += [cg.OutputArgument(h_out_sym, h_out_sym, h.subs(subs_tab), dimensions=h_out_sym.shape)]

    H_out_sym = sp.MatrixSymbol('H_out', H.shape[0], H.shape[1])
    H_arg_list = [cg.InputArgument(x_sym, dimensions=x_sym.shape)]
    H_arg_list += h_additional_in_arg
    H_arg_list += [cg.OutputArgument(H_out_sym, H_out_sym, H.subs(subs_tab), dimensions=H_out_sym.shape)]

    routines = [cg.Routine("f", f_arg_list, no_return_val, no_local_vars),
                cg.Routine("F", F_arg_list, no_return_val, no_local_vars),
                cg.Routine("h", h_arg_list, no_return_val, no_local_vars),
                cg.Routine("H", H_arg_list, no_return_val, no_local_vars)]
    code_gen = cg.get_code_generator("C", "projectname")
    [(c_name, c_code), (h_name, c_header)] = code_gen.write(routines, "prefix", header=False)

    c_code = clean_c_code(c_code, use_single_float=True)

    c_code_head = '// This file has been automatically generated\n'
    c_code_head += '// DO NOT EDIT!\n\n'
    c_code_head += '#include <math.h>\n\n'
    c_code_head += 'const int STATE_DIM = {};\n'.format(len(x))
    c_code_head += 'const int CONTROL_DIM = {};\n'.format(len(u))
    c_code_head += 'const int MEASURE_DIM = {};\n'.format(len(h))
    c_code_head += '\n\n'

    return c_code_head + c_code