Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
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)