def define_constructor(py_class, struct_typeclass, fields):
    """Define the jit-code constructor for `struct_typeclass` using the
    Python type `py_class` and the required `fields`.

    Use this instead of `define_proxy()` if the user does not want boxing
    logic defined.
    """
    # Build source code for the constructor
    params = ', '.join(fields)
    indent = ' ' * 8
    init_fields_buf = []
    for k in fields:
        init_fields_buf.append(f"st.{k} = {k}")
    init_fields = f'\n{indent}'.join(init_fields_buf)

    source = f"""
def ctor({params}):
    struct_type = struct_typeclass(list(zip({list(fields)}, [{params}])))
    def impl({params}):
        st = new(struct_type)
        {init_fields}
        return st
    return impl
"""

    glbs = dict(struct_typeclass=struct_typeclass, new=new)
    exec(source, glbs)
    ctor = glbs['ctor']
    # Make it an overload
    overload(py_class)(ctor)
    def test_overload_inline_always_with_literally_in_inlinee(self):
        # See issue #5887

        def foo_ovld(dtype):

            if not isinstance(dtype, types.StringLiteral):

                def foo_noop(dtype):
                    return literally(dtype)

                return foo_noop

            if dtype.literal_value == 'str':

                def foo_as_str_impl(dtype):
                    return 10

                return foo_as_str_impl

            if dtype.literal_value in ('int64', 'float64'):

                def foo_as_num_impl(dtype):
                    return 20

                return foo_as_num_impl

        # define foo for literal str 'str'
        def foo(dtype):
            return 10

        overload(foo, inline='always')(foo_ovld)

        def test_impl(dtype):
            return foo(dtype)

        # check literal dispatch on 'str'
        dtype = 'str'
        self.check(test_impl, dtype, inline_expect={'foo': True})

        # redefine foo to be correct for literal str 'int64'
        def foo(dtype):
            return 20

        overload(foo, inline='always')(foo_ovld)

        # check literal dispatch on 'int64'
        dtype = 'int64'
        self.check(test_impl, dtype, inline_expect={'foo': True})
Exemple #3
0
def overload_elementwise_unary_ufunc(ufunc, name=None, dtype=None):
    """
    Wrapper for unary ufuncs that returns an array
    """
    if name is None:
        name = ufunc.__name__
    globals()[name] = ufunc

    def unary_elementwise_ufunc_impl(a):
        nb_dtype = determine_dtype(a, dtype)
        typ = determine_input_type(a)

        if isinstance(a, ArrayPointer):
            def impl(a):
                sz = len(a)
                x = Array(sz, nb_dtype)
                for i in range(sz):
                    # Convert the value to type "typ"
                    cast = typ(a[i])
                    x[i] = nb_dtype(ufunc(cast))
                return x
            return impl
        else:
            def impl(a):
                # Convert the value to type typ
                cast = typ(a)
                return nb_dtype(ufunc(cast))
            return impl

    decorate = extending.overload(ufunc)

    def wrapper(overload_func):
        return decorate(unary_elementwise_ufunc_impl)

    return wrapper
def overload_binary_op(op, inplace=False):
    def omnisci_operator_impl(a, b):
        if isinstance(a, ArrayPointer) and isinstance(b, ArrayPointer):
            nb_dtype = a.eltype

            def impl(a, b):
                # XXX: raise exception if len(a) != len(b)
                sz = len(a)

                if inplace:
                    x = a
                else:
                    x = Array(sz, nb_dtype)

                for i in range(sz):
                    x[i] = nb_dtype(op(a[i], b[i]))
                return x

            return impl

    decorate = extending.overload(op)

    def wrapper(overload_func):
        return decorate(omnisci_operator_impl)

    return wrapper
def overload_binary_cmp_op(op):
    def omnisci_operator_impl(a, e):
        if isinstance(a, ArrayPointer):
            if isinstance(e, ArrayPointer):

                def impl(a, e):
                    if len(a) != len(e):
                        return False
                    for i in range(len(a)):
                        if not op(a[i], e[i]):
                            return False
                    return True
            elif isinstance(e, types.Number):

                def impl(a, e):
                    sz = len(a)
                    x = Array(sz, 'int8')
                    for i in range(sz):
                        x[i] = typesystem.boolean8(op(a[i], e))
                    return x

            return impl

    decorate = extending.overload(op)

    def wrapper(overload_func):
        return decorate(omnisci_operator_impl)

    return wrapper
Exemple #6
0
        def wrapper(overload_func):
            overload_func.__doc__ = self.format_docstring(
                overload_func, ufunc_name, api)
            functools.update_wrapper(fn, overload_func)

            decorate = extending.overload(fn)
            return decorate(unary_ufunc_impl)
Exemple #7
0
    def implements(self, func_name, api=API.ARRAY_API):
        fn = self.create_function(func_name)
        decorate = extending.overload(fn)

        def wrapper(overload_func):
            overload_func.__doc__ = self.format_docstring(
                overload_func, func_name, api)
            functools.update_wrapper(fn, overload_func)
            return decorate(overload_func)

        return wrapper
Exemple #8
0
def expose_and_overload(func):
    name = func.__name__
    s = f'def {name}(*args, **kwargs): pass'
    exec(s, globals())

    fn = globals()[name]
    decorate = extending.overload(fn)

    def wrapper(overload_func):
        return decorate(overload_func)

    return wrapper
Exemple #9
0
    def not_implemented(self, func_name, api=API.ARRAY_API):
        fn = self.create_function(func_name)
        decorate = extending.overload(fn)

        def unimplemented(*args, **kwargs):
            raise errors.NumbaNotImplementedError(
                f'Function "{func_name}" is not supported.\n'
                'Please, open a ticket on the RBC project '
                'and report this error if you need support for '
                'this function.')

        def wraps(overload_func):
            original_doc = self.format_docstring(overload_func, func_name, api)
            overload_func.__doc__ = f"❌ Not implemented\n{original_doc}"
            functools.update_wrapper(fn, overload_func)
            return decorate(unimplemented)

        return wraps
def overload_unary_op(op):
    def omnisci_operator_impl(a):
        if isinstance(a, ArrayPointer):
            nb_dtype = a.eltype

            def impl(a):
                sz = len(a)
                x = Array(sz, nb_dtype)
                for i in range(sz):
                    x[i] = nb_dtype(op(a[i]))
                return x

            return impl

    decorate = extending.overload(op)

    def wrapper(overload_func):
        return decorate(omnisci_operator_impl)

    return wrapper
Exemple #11
0
            def impl(a, b):
                return val

            return impl
        elif a_none ^ b_none:

            def impl(a, b):
                return not val

            return impl

    return none_equality


overload(operator.eq)(gen_non_eq(True))
overload(operator.ne)(gen_non_eq(False))

#-------------------------------------------------------------------------------


@lower_getattr_generic(types.DeferredType)
def deferred_getattr(context, builder, typ, value, attr):
    """
    Deferred.__getattr__ => redirect to the actual type.
    """
    inner_type = typ.get()
    val = context.cast(builder, value, typ, inner_type)
    imp = context.get_getattr(inner_type, attr)
    return imp(context, builder, inner_type, val, attr)
Exemple #12
0
def overload_elementwise_binary_ufunc(ufunc, name=None, dtype=None):
    """
    Wrapper for binary ufuncs that returns an array
    """
    if name is None:
        name = ufunc.__name__
    globals()[name] = ufunc

    def binary_ufunc_impl(a, b):
        typA = determine_input_type(a)
        typB = determine_input_type(b)

        # XXX: raise error if len(a) != len(b)
        @extending.register_jitable(_nrt=False)
        def binary_impl(a, b, nb_dtype):
            sz = len(a)
            x = Array(sz, nb_dtype)
            for i in range(sz):
                cast_a = typA(a[i])
                cast_b = typB(b[i])
                x[i] = nb_dtype(ufunc(cast_a, cast_b))
            return x

        @extending.register_jitable(_nrt=False)
        def broadcast(e, sz, dtype):
            b = Array(sz, dtype)
            b.fill(e)
            return b

        if isinstance(a, ArrayPointer) and isinstance(b, ArrayPointer):
            nb_dtype = determine_dtype(a, dtype)

            def impl(a, b):
                return binary_impl(a, b, nb_dtype)
            return impl
        elif isinstance(a, ArrayPointer):
            nb_dtype = determine_dtype(a, dtype)
            other_dtype = b

            def impl(a, b):
                b = broadcast(b, len(a), other_dtype)
                return binary_impl(a, b, nb_dtype)
            return impl
        elif isinstance(b, ArrayPointer):
            nb_dtype = determine_dtype(b, dtype)
            other_dtype = a

            def impl(a, b):
                a = broadcast(a, len(b), other_dtype)
                return binary_impl(a, b, nb_dtype)
            return impl
        else:
            nb_dtype = determine_dtype(a, dtype)

            def impl(a, b):
                cast_a = typA(a)
                cast_b = typB(b)
                return nb_dtype(ufunc(cast_a, cast_b))
            return impl

    decorate = extending.overload(ufunc)

    def wrapper(overload_func):
        return decorate(binary_ufunc_impl)

    return wrapper