Beispiel #1
0
def minmax(typesystem, args, op):
    if len(args) < 2:
        return

    res = args[0]
    for arg in args[1:]:
        lhs_type = get_type(res)
        rhs_type = get_type(arg)
        res_type = typesystem.promote(lhs_type, rhs_type)
        if lhs_type != res_type:
            res = nodes.CoercionNode(res, res_type)
        if rhs_type != res_type:
            arg = nodes.CoercionNode(arg, res_type)

        lhs_temp = nodes.TempNode(res_type)
        rhs_temp = nodes.TempNode(res_type)
        res_temp = nodes.TempNode(res_type)
        lhs = lhs_temp.load(invariant=True)
        rhs = rhs_temp.load(invariant=True)
        expr = ast.IfExp(ast.Compare(lhs, [op], [rhs]), lhs, rhs)
        body = [
            ast.Assign([lhs_temp.store()], res),
            ast.Assign([rhs_temp.store()], arg),
            ast.Assign([res_temp.store()], expr),
        ]
        res = nodes.ExpressionNode(body, res_temp.load(invariant=True))

    return res
Beispiel #2
0
def minmax(typesystem, args, op):
    if len(args) < 2:
        return

    res = args[0]
    for arg in args[1:]:
        lhs_type = get_type(res)
        rhs_type = get_type(arg)
        res_type = typesystem.promote(lhs_type, rhs_type)
        if lhs_type != res_type:
            res = nodes.CoercionNode(res, res_type)
        if rhs_type != res_type:
            arg = nodes.CoercionNode(arg, res_type)

        lhs_temp = nodes.TempNode(res_type)
        rhs_temp = nodes.TempNode(res_type)
        res_temp = nodes.TempNode(res_type)
        lhs = lhs_temp.load(invariant=True)
        rhs = rhs_temp.load(invariant=True)
        expr = ast.IfExp(ast.Compare(lhs, [op], [rhs]), lhs, rhs)
        body = [
            ast.Assign([lhs_temp.store()], res),
            ast.Assign([rhs_temp.store()], arg),
            ast.Assign([res_temp.store()], expr),
        ]
        res = nodes.ExpressionNode(body, res_temp.load(invariant=True))

    return res
Beispiel #3
0
def dispatch_on_value(context, call_node, func_type):
    """
    Dispatch a call of a module attribute by value.

    For instance, a method

        def empty(shape, dtype, order):
            ...

    would be called with those arguments. Parameters not present as
    arguments in user code are None.

    Returns the result type, or None
    """
    inferer, pass_in_types = get_inferer(func_type.value)

    argnames = inspect.getargspec(inferer).args
    if argnames[0] == "context":
        argnames.pop(0)
        args = (context,)
    else:
        args = ()

    method_kwargs = parse_args(call_node, argnames)

    if pass_in_types:
        for argname, node in method_kwargs.iteritems():
            if node is not None:
                method_kwargs[argname] = get_type(node)

    return inferer(*args, **method_kwargs)
Beispiel #4
0
def ord_(typesystem, node, expr):
    type = get_type(expr)
    if type.is_int and type.typename in ("char", "uchar"):
        return nodes.CoercionNode(expr, int_)
    elif type.is_string:
        # TODO:
        pass
Beispiel #5
0
def ord_(typesystem, node, expr):
    type = get_type(expr)
    if type.is_int and type.typename in ("char", "uchar"):
        return nodes.CoercionNode(expr, int_)
    elif type.is_string:
        # TODO:
        pass
Beispiel #6
0
def array_from_object(a):
    """
    object -> array type:

        array_from_object(ASTNode([[1, 2], [3, 4]])) => int64[:, :]
    """
    return array_from_type(get_type(a))
Beispiel #7
0
def array_from_object(a):
    """
    object -> array type:

        array_from_object(ASTNode([[1, 2], [3, 4]])) => int64[:, :]
    """
    return array_from_type(get_type(a))
Beispiel #8
0
def len_(typesystem, node, obj):
    # Simplify len(array) to ndarray.shape[0]
    argtype = get_type(obj)
    if argtype.is_array:
        shape_attr = nodes.ArrayAttributeNode('shape', node.args[0])
        new_node = nodes.index(shape_attr, 0)
        return new_node

    return Py_ssize_t
Beispiel #9
0
def len_(context, node, obj):
    # Simplify len(array) to ndarray.shape[0]
    argtype = get_type(obj)
    if argtype.is_array:
        shape_attr = nodes.ArrayAttributeNode('shape', node.args[0])
        new_node = nodes.index(shape_attr, 0)
        return new_node

    return Py_ssize_t
Beispiel #10
0
def len_(typesystem, node, obj):
    # Simplify len(array) to ndarray.shape[0]
    argtype = get_type(obj)
    if argtype.is_array:
        shape_attr = nodes.ArrayAttributeNode('shape', node.args[0])
        new_node = nodes.index(shape_attr, 0)
        return new_node
    elif argtype.is_string:
        return nodes.CoercionNode(nodes.typednode(node, size_t), Py_ssize_t)

    return Py_ssize_t # Object call
Beispiel #11
0
def len_(typesystem, node, obj):
    # Simplify len(array) to ndarray.shape[0]
    argtype = get_type(obj)
    if argtype.is_array:
        shape_attr = nodes.ArrayAttributeNode('shape', node.args[0])
        new_node = nodes.index(shape_attr, 0)
        return new_node
    elif argtype.is_string:
        return nodes.CoercionNode(nodes.typednode(node, size_t), Py_ssize_t)

    return Py_ssize_t # Object call
Beispiel #12
0
def abs_(context, node, x):
    import builtinmodule

    argtype = get_type(x)

    if argtype.is_array and argtype.is_numeric:
        # Handle np.abs() on arrays
        dtype = builtinmodule.abstype(argtype.dtype)
        result_type = argtype.copy(dtype=dtype)
        node.variable = Variable(result_type)
        return node

    return builtinmodule.abs_(context, node, x)
Beispiel #13
0
def abs_(typesystem, node, x):
    import builtinmodule

    argtype = get_type(x)

    if argtype.is_array and argtype.is_numeric:
        # Handle np.abs() on arrays
        dtype = builtinmodule.abstype(argtype.dtype)
        result_type = argtype.add("dtype", dtype)
        node.variable = Variable(result_type)
        return node

    return builtinmodule.abs_(typesystem, node, x)
Beispiel #14
0
def abs_(context, node, x):
    import builtinmodule

    argtype = get_type(x)

    if argtype.is_array and argtype.is_numeric:
        # Handle np.abs() on arrays
        dtype = builtinmodule.abstype(argtype.dtype)
        result_type = argtype.copy(dtype=dtype)
        node.variable = Variable(result_type)
        return node

    return builtinmodule.abs_(context, node, x)
Beispiel #15
0
def round_(typesystem, node, number, ndigits):
    argtype = get_type(number)

    if len(node.args) == 1 and argtype.is_int:
        # round(myint) -> float(myint)
        return nodes.CoercionNode(node.args[0], double)

    if argtype.is_float or argtype.is_int:
        dst_type = double
    else:
        dst_type = object_
        node.args[0] = nodes.CoercionNode(node.args[0], object_)

    node.variable = Variable(dst_type)
    return node # nodes.CoercionNode(node, double)
Beispiel #16
0
def infer_unary_math_call(context, call_node, arg, default_result_type=double):
    "Resolve calls to math functions to llvm.log.f32() etc"
    # signature is a generic signature, build a correct one
    type = get_type(call_node.args[0])

    if type.is_numeric and type.kind < default_result_type.kind:
        type = default_result_type
    elif type.is_array and type.dtype.is_int:
        type = type.copy(dtype=double)

    # signature = minitypes.FunctionType(return_type=type, args=[type])
    # result = nodes.MathNode(py_func, signature, call_node.args[0])
    nodes.annotate(context.env, call_node, is_math=True)
    call_node.variable = Variable(type)
    return call_node
Beispiel #17
0
def abs_(typesystem, node, x):
    from . import builtinmodule

    argtype = get_type(x)
    nodes.annotate(typesystem.env, node, is_math=True)

    if argtype.is_array and argtype.dtype.is_numeric:
        # Handle np.abs() on arrays
        dtype = builtinmodule.abstype(argtype.dtype)
        result_type = argtype.add('dtype', dtype)
        node.variable = Variable(result_type)
    else:
        node = builtinmodule.abs_(typesystem, node, x)

    return node
Beispiel #18
0
def round_(typesystem, node, number, ndigits):
    argtype = get_type(number)

    if len(node.args) == 1 and argtype.is_int:
        # round(myint) -> float(myint)
        return nodes.CoercionNode(node.args[0], double)

    if argtype.is_float or argtype.is_int:
        dst_type = double
    else:
        dst_type = object_
        node.args[0] = nodes.CoercionNode(node.args[0], object_)

    node.variable = Variable(dst_type)
    return node # nodes.CoercionNode(node, double)
Beispiel #19
0
def abs_(typesystem, node, x):
    from . import builtinmodule

    argtype = get_type(x)
    nodes.annotate(typesystem.env, node, is_math=True)

    if argtype.is_array and argtype.dtype.is_numeric:
        # Handle np.abs() on arrays
        dtype = builtinmodule.abstype(argtype.dtype)
        result_type = argtype.add('dtype', dtype)
        node.variable = Variable(result_type)
    else:
        node = builtinmodule.abs_(typesystem, node, x)

    return node
Beispiel #20
0
def infer_unary_math_call(context, call_node, arg, default_result_type=double):
    "Resolve calls to math functions to llvm.log.f32() etc"
    # signature is a generic signature, build a correct one
    type = get_type(call_node.args[0])

    if type.is_numeric and type.kind < default_result_type.kind:
        type = default_result_type
    elif type.is_array and type.dtype.is_int:
        type = type.copy(dtype=double)

    # signature = minitypes.FunctionType(return_type=type, args=[type])
    # result = nodes.MathNode(py_func, signature, call_node.args[0])
    nodes.annotate(context.env, call_node, is_math=True)
    call_node.variable = Variable(type)
    return call_node
Beispiel #21
0
def round_(context, node, number, ndigits):
    # is_math = is_math_function(node.args, round)
    argtype = get_type(number)

    if len(node.args) == 1 and argtype.is_int:
        # round(myint) -> float(myint)
        return nodes.CoercionNode(node.args[0], double)

    if argtype.is_float or argtype.is_int:
        dst_type = double
    else:
        dst_type = object_
        node.args[0] = nodes.CoercionNode(node.args[0], object_)

    node.variable = Variable(dst_type)
    return node # nodes.CoercionNode(node, double)
Beispiel #22
0
def round_(context, node, number, ndigits):
    # is_math = is_math_function(node.args, round)
    argtype = get_type(number)

    if len(node.args) == 1 and argtype.is_int:
        # round(myint) -> float(myint)
        return nodes.CoercionNode(node.args[0], double)

    if argtype.is_float or argtype.is_int:
        dst_type = double
    else:
        dst_type = object_
        node.args[0] = nodes.CoercionNode(node.args[0], object_)

    node.variable = Variable(dst_type)
    return node  # nodes.CoercionNode(node, double)
Beispiel #23
0
def is_math_function(func_args, py_func):
    if len(func_args) == 0 or len(func_args) > 1 or py_func is None:
        return False

    type = get_type(func_args[0])

    if type.is_array:
        type = type.dtype
        valid_type = type.is_float or type.is_int or type.is_complex
    else:
        valid_type = type.is_float or type.is_int

    math_name = get_funcname(py_func)
    is_math = math_name in libc_math_funcs
    if is_math and valid_type:
        actual_math_name = math_suffix(math_name, type)
        is_math = have_impl(actual_math_name) or have_double_impl(math_name)

    return valid_type and (is_intrinsic(py_func) or is_math)
Beispiel #24
0
def is_math_function(func_args, py_func):
    if len(func_args) == 0 or len(func_args) > 1 or py_func is None:
        return False

    type = get_type(func_args[0])

    if type.is_array:
        type = type.dtype
        valid_type = type.is_float or type.is_int or type.is_complex
    else:
        valid_type = type.is_float or type.is_int

    math_name = get_funcname(py_func)
    is_math = math_name in libc_math_funcs
    if is_math and valid_type:
        actual_math_name = math_suffix(math_name, type)
        is_math = have_impl(actual_math_name) or have_double_impl(math_name)

    return valid_type and (is_intrinsic(py_func) or is_math)
Beispiel #25
0
def abs_(context, node, x):
    # Result type of the substitution during late
    # specialization
    result_type = object_
    argtype = get_type(x)

    # What we actually get back regardless of implementation,
    # e.g. abs(complex) goes throught the object layer, but we know the result
    # will be a double
    dst_type = argtype

    is_math = mathmodule.is_math_function(node.args, abs)

    if argtype.is_complex:
        dst_type = double
    elif is_math and (argtype.is_float or argtype.is_int):
        result_type = argtype

    node.variable = Variable(result_type)
    return nodes.CoercionNode(node, dst_type)
Beispiel #26
0
def typedcontainer_infer(compile_typedcontainer, type_node, iterable_node):
    """
    Type inferer for typed containers, register with numba.register_inferer().

    :param compile_typedcontainer: item_type -> typed container extension class
    :param type_node: type parameter to typed container constructor
    :param iterable_node: value parameter to typed container constructor (optional)
    """
    assert type_node is not None

    type = get_type(type_node)
    if type.is_cast:
        elem_type = type.dst_type

        # Pre-compile typed list implementation
        typedcontainer_ctor = compile_typedcontainer(elem_type)

        # Inject the typedlist directly to avoid runtime implementation lookup
        iterable_node = iterable_node or nodes.const(None, object_)
        result = nodes.call_pyfunc(typedcontainer_ctor, (iterable_node,))
        return nodes.CoercionNode(result, typedcontainer_ctor.exttype)

    return object_
Beispiel #27
0
def typedcontainer_infer(compile_typedcontainer, type_node, iterable_node):
    """
    Type inferer for typed containers, register with numba.register_inferer().

    :param compile_typedcontainer: item_type -> typed container extension class
    :param type_node: type parameter to typed container constructor
    :param iterable_node: value parameter to typed container constructor (optional)
    """
    assert type_node is not None

    type = get_type(type_node)
    if type.is_cast:
        elem_type = type.dst_type

        # Pre-compile typed list implementation
        typedcontainer_ctor = compile_typedcontainer(elem_type)

        # Inject the typedlist directly to avoid runtime implementation lookup
        iterable_node = iterable_node or nodes.const(None, object_)
        result = nodes.call_pyfunc(typedcontainer_ctor, (iterable_node,))
        return nodes.CoercionNode(result, typedcontainer_ctor.exttype)

    return object_
Beispiel #28
0
def binop_type(context, x, y):
    "Binary result type for math operations"
    x_type = get_type(x)
    y_type = get_type(y)
    return context.promote_types(x_type, y_type)
Beispiel #29
0
def _build_arg(pass_in_types, node):
    if pass_in_types:
        return get_type(node)
    return node
Beispiel #30
0
def binop_type(typesystem, x, y):
    "Binary result type for math operations"
    x_type = get_type(x)
    y_type = get_type(y)
    return typesystem.promote(x_type, y_type)
Beispiel #31
0
def _build_arg(pass_in_types, node):
    if pass_in_types:
        return get_type(node)
    return node
Beispiel #32
0
def chr_(typesystem, node, expr):
    type = get_type(expr)
    if type.is_int:
        return nodes.CoercionNode(expr, char)
Beispiel #33
0
def abs_(typesystem, node, x):
    node.variable = Variable(abstype(get_type(x)))
    return node
Beispiel #34
0
def abs_(typesystem, node, x):
    node.variable = Variable(abstype(get_type(x)))
    return node
Beispiel #35
0
def abs_(context, node, x):
    node.variable = Variable(abstype(get_type(x)))
    return node
Beispiel #36
0
def abs_(context, node, x):
    node.variable = Variable(abstype(get_type(x)))
    return node
Beispiel #37
0
    def rewrite_array_iteration(self, node):
        """
        Convert 1D array iteration to for-range and indexing:

            for value in my_array:
                ...

        becomes

            for i in my_array.shape[0]:
                value = my_array[i]
                ...
        """
        logger.debug(ast.dump(node))

        orig_target = node.target
        orig_iter = node.iter

        #--------------------------------------------------------------------
        # Replace node.target with a temporary
        #--------------------------------------------------------------------

        target_name = orig_target.id + '.idx'
        target_temp = nodes.TempNode(Py_ssize_t)
        node.target = target_temp.store()

        #--------------------------------------------------------------------
        # Create range(A.shape[0])
        #--------------------------------------------------------------------

        call_func = ast.Name(id='range', ctx=ast.Load())
        nodes.typednode(call_func, typesystem.range_)

        shape_index = ast.Index(nodes.ConstNode(0, typesystem.Py_ssize_t))
        shape_index.type = typesystem.npy_intp

        stop = ast.Subscript(value=nodes.ShapeAttributeNode(orig_iter),
                             slice=shape_index,
                             ctx=ast.Load())
        nodes.typednode(stop, npy_intp)

        #--------------------------------------------------------------------
        # Create range iterator and replace node.iter
        #--------------------------------------------------------------------

        call_args = [nodes.ConstNode(0, typesystem.Py_ssize_t),
                     nodes.CoercionNode(stop, typesystem.Py_ssize_t),
                     nodes.ConstNode(1, typesystem.Py_ssize_t),]

        node.iter = ast.Call(func=call_func, args=call_args)
        nodes.typednode(node.iter, call_func.type)

        node.index = target_temp.load(invariant=True)

        #--------------------------------------------------------------------
        # Add assignment to new target variable at the start of the body
        #--------------------------------------------------------------------

        index = ast.Index(value=node.index)
        index.type = target_temp.type
        subscript = ast.Subscript(value=orig_iter,
                                  slice=index, ctx=ast.Load())
        nodes.typednode(subscript, get_type(orig_iter).dtype)

        #--------------------------------------------------------------------
        # Add assignment to new target variable at the start of the body
        #--------------------------------------------------------------------

        assign = ast.Assign(targets=[orig_target], value=subscript)
        node.body = [assign] + node.body

        #--------------------------------------------------------------------
        # Specialize new for loop through range iteration
        #--------------------------------------------------------------------

        return self.visit(node)
Beispiel #38
0
def abs_(typesystem, node, x):
    argtype = typesystem.promote(long_, get_type(x))
    dst_type = abstype(argtype)
    node.variable = Variable(dst_type)
    node.args = [nodes.CoercionNode(x, argtype)]
    return node
Beispiel #39
0
def binop_type(typesystem, x, y):
    "Binary result type for math operations"
    x_type = get_type(x)
    y_type = get_type(y)
    return typesystem.promote(x_type, y_type)
Beispiel #40
0
def binop_type(context, x, y):
    "Binary result type for math operations"
    x_type = get_type(x)
    y_type = get_type(y)
    return context.promote_types(x_type, y_type)
Beispiel #41
0
    def rewrite_array_iteration(self, node):
        """
        Convert 1D array iteration to for-range and indexing:

            for value in my_array:
                ...

        becomes

            for i in my_array.shape[0]:
                value = my_array[i]
                ...
        """
        logger.debug(ast.dump(node))

        orig_target = node.target
        orig_iter = node.iter

        #--------------------------------------------------------------------
        # Replace node.target with a temporary
        #--------------------------------------------------------------------

        target_name = orig_target.id + '.idx'
        target_temp = nodes.TempNode(Py_ssize_t)
        node.target = target_temp.store()

        #--------------------------------------------------------------------
        # Create range(A.shape[0])
        #--------------------------------------------------------------------

        call_func = ast.Name(id='range', ctx=ast.Load())
        nodes.typednode(call_func, typesystem.range_)

        shape_index = ast.Index(nodes.ConstNode(0, typesystem.Py_ssize_t))
        shape_index.type = typesystem.npy_intp

        stop = ast.Subscript(value=nodes.ShapeAttributeNode(orig_iter),
                             slice=shape_index,
                             ctx=ast.Load())
        nodes.typednode(stop, npy_intp)

        #--------------------------------------------------------------------
        # Create range iterator and replace node.iter
        #--------------------------------------------------------------------

        call_args = [
            nodes.ConstNode(0, typesystem.Py_ssize_t),
            nodes.CoercionNode(stop, typesystem.Py_ssize_t),
            nodes.ConstNode(1, typesystem.Py_ssize_t),
        ]

        node.iter = ast.Call(func=call_func, args=call_args)
        nodes.typednode(node.iter, call_func.type)

        node.index = target_temp.load(invariant=True)

        #--------------------------------------------------------------------
        # Add assignment to new target variable at the start of the body
        #--------------------------------------------------------------------

        index = ast.Index(value=node.index)
        index.type = target_temp.type
        subscript = ast.Subscript(value=orig_iter, slice=index, ctx=ast.Load())
        nodes.typednode(subscript, get_type(orig_iter).dtype)

        #--------------------------------------------------------------------
        # Add assignment to new target variable at the start of the body
        #--------------------------------------------------------------------

        assign = ast.Assign(targets=[orig_target], value=subscript)
        node.body = [assign] + node.body

        #--------------------------------------------------------------------
        # Specialize new for loop through range iteration
        #--------------------------------------------------------------------

        return self.visit(node)
Beispiel #42
0
def abs_(typesystem, node, x):
    argtype = typesystem.promote(long_, get_type(x))
    dst_type = abstype(argtype)
    node.variable = Variable(dst_type)
    node.args = [nodes.CoercionNode(x, argtype)]
    return node
Beispiel #43
0
def chr_(typesystem, node, expr):
    type = get_type(expr)
    if type.is_int:
        return nodes.CoercionNode(expr, char)