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
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
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)
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
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
def array_from_object(a): """ object -> array type: array_from_object(ASTNode([[1, 2], [3, 4]])) => int64[:, :] """ return array_from_type(get_type(a))
def array_from_object(a): """ object -> array type: array_from_object(ASTNode([[1, 2], [3, 4]])) => int64[:, :] """ return array_from_type(get_type(a))
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
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
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
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
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)
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)
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)
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)
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
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
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)
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
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
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)
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)
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)
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)
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)
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_
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_
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)
def _build_arg(pass_in_types, node): if pass_in_types: return get_type(node) return node
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)
def _build_arg(pass_in_types, node): if pass_in_types: return get_type(node) return node
def chr_(typesystem, node, expr): type = get_type(expr) if type.is_int: return nodes.CoercionNode(expr, char)
def abs_(typesystem, node, x): node.variable = Variable(abstype(get_type(x))) return node
def abs_(typesystem, node, x): node.variable = Variable(abstype(get_type(x))) return node
def abs_(context, node, x): node.variable = Variable(abstype(get_type(x))) return node
def abs_(context, node, x): node.variable = Variable(abstype(get_type(x))) return node
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)
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
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)
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)
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)
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
def chr_(typesystem, node, expr): type = get_type(expr) if type.is_int: return nodes.CoercionNode(expr, char)