def impl_extend(l, iterable): if not isinstance(l, types.ListType): return if not isinstance(iterable, types.IterableType): raise TypingError("extend argument must be iterable") _check_for_none_typed(l, 'insert') def select_impl(): if isinstance(iterable, types.ListType): def impl(l, iterable): # guard against l.extend(l) if l is iterable: iterable = iterable.copy() for i in iterable: l.append(i) return impl else: def impl(l, iterable): for i in iterable: l.append(i) return impl if l.is_precise(): # Handle the precise case. return select_impl() else: # Handle the imprecise case, try to 'guess' the underlying type of the # values in the iterable. if hasattr(iterable, "dtype"): # tuples and arrays ty = iterable.dtype elif hasattr(iterable, "item_type"): # lists ty = iterable.item_type elif hasattr(iterable, "yield_type"): # iterators and generators ty = iterable.yield_type else: raise TypingError("unable to extend list, iterable is missing " "either *dtype*, *item_type* or *yield_type*.") l = l.refine(ty) # Create the signature that we wanted this impl to have sig = typing.signature(types.void, l, iterable) return sig, select_impl()
def declare_device_function(name, restype, argtypes): from .descriptor import CUDATargetDesc typingctx = CUDATargetDesc.typingctx targetctx = CUDATargetDesc.targetctx sig = typing.signature(restype, *argtypes) extfn = ExternFunction(name, sig) class device_function_template(ConcreteTemplate): key = extfn cases = [sig] fndesc = funcdesc.ExternalFunctionDescriptor( name=name, restype=restype, argtypes=argtypes) typingctx.insert_user_function(extfn, device_function_template) targetctx.insert_user_function(extfn, fndesc) return extfn
def _context_builder_sig_args(self): typing_context = typing.Context() context = cpu.CPUContext(typing_context) lib = context.codegen().create_library('testing') with context.push_code_library(lib): module = lc.Module("test_module") sig = typing.signature(types.int32, types.int32) llvm_fnty = context.call_conv.get_function_type(sig.return_type, sig.args) function = module.get_or_insert_function(llvm_fnty, name='test_fn') args = context.call_conv.get_arguments(function) assert function.is_declaration entry_block = function.append_basic_block('entry') builder = lc.Builder(entry_block) yield context, builder, sig, args
def _do_work_getattr(self, state, work_list, block, i, expr): recv_type = state.type_annotation.typemap[expr.value.name] recv_type = types.unliteral(recv_type) matched = state.typingctx.find_matching_getattr_template( recv_type, expr.attr, ) if not matched: return False template = matched['template'] if getattr(template, 'is_method', False): # The attribute template is representing a method. # Don't inline the getattr. return False inline_type = getattr(template, '_inline', None) if inline_type is None: # inline not defined return False sig = typing.signature(matched['return_type'], recv_type) arg_typs = sig.args if not inline_type.is_never_inline: try: impl = template._overload_func(recv_type) if impl is None: raise Exception # abort for this template except Exception: return False else: return False is_method = False return self._run_inliner( state, inline_type, sig, template, arg_typs, expr, i, impl, block, work_list, is_method, )
def impl_insert(l, index, item): if not isinstance(l, types.ListType): return _check_for_none_typed(l, 'insert') # insert can refine if isinstance(item, NoneType): raise TypingError("method support for List[None] is limited") if index in index_types: def impl(l, index, item): # If the index is larger than the size of the list or if the list is # empty, just append. if index >= len(l) or len(l) == 0: l.append(item) # Else, do the insert dance else: # convert negative indices if index < 0: # if the index is still negative after conversion, use 0 index = max(len(l) + index, 0) # grow the list by one, make room for item to insert l.append(l[0]) # reverse iterate over the list and shift all elements i = len(l) - 1 while (i > index): l[i] = l[i - 1] i -= 1 # finally, insert the item l[index] = item if l.is_precise(): # Handle the precise case. return impl else: # Handle the imprecise case l = l.refine(item) # Re-bind the item type to match the arguments. itemty = l.item_type # Create the signature that we wanted this impl to have. sig = typing.signature(types.void, l, INDEXTY, itemty) return sig, impl else: raise TypingError("list insert indices must be integers")
def __init__(self, pyfunc, sig, locals, options, pipeline_class=compiler.Compiler): args, return_type = sig if return_type is None: raise TypeError("C callback needs an explicit return type") self.__name__ = pyfunc.__name__ self.__qualname__ = getattr(pyfunc, "__qualname__", self.__name__) self.__wrapped__ = pyfunc self._pyfunc = pyfunc self._sig = signature(return_type, *args) self._compiler = _CFuncCompiler( pyfunc, self._targetdescr, options, locals, pipeline_class=pipeline_class ) self._wrapper_name = None self._wrapper_address = None self._cache = NullCache() self._cache_hits = 0
def triangular_impl_2(context, builder, sig, args): fltty = sig.return_type low, high = args state_ptr = get_state_ptr(context, builder, "py") randval = get_next_double(context, builder, state_ptr) def triangular_impl_2(randval, low, high): u = randval c = 0.5 if u > c: u = 1.0 - u low, high = high, low return low + (high - low) * math.sqrt(u * c) res = context.compile_internal(builder, triangular_impl_2, signature(*(fltty, ) * 4), (randval, low, high)) return impl_ret_untracked(context, builder, sig.return_type, res)
def _context_builder_sig_args(self): typing_context = cpu_target.typing_context context = cpu_target.target_context lib = context.codegen().create_library('testing') with context.push_code_library(lib): module = ir.Module("test_module") sig = typing.signature(types.int32, types.int32) llvm_fnty = context.call_conv.get_function_type( sig.return_type, sig.args) function = cgutils.get_or_insert_function(module, llvm_fnty, 'test_fn') args = context.call_conv.get_arguments(function) assert function.is_declaration entry_block = function.append_basic_block('entry') builder = ir.IRBuilder(entry_block) yield context, builder, sig, args
def run_pass(self, state): """ Back-end: Packages lowering output in a compile result """ lowered = state['cr'] signature = typing.signature(state.return_type, *state.args) state.cr = cuda_compile_result( typing_context=state.typingctx, target_context=state.targetctx, typing_error=state.status.fail_reason, type_annotation=state.type_annotation, library=state.library, call_helper=lowered.call_helper, signature=signature, fndesc=lowered.fndesc, ) return True
def print_varargs_impl(context, builder, sig, args): """ A entire print() call. """ pyapi = context.get_python_api(builder) gil = pyapi.gil_ensure() for i, (argtype, argval) in enumerate(zip(sig.args, args)): signature = typing.signature(types.none, argtype) imp = context.get_function("print_item", signature) imp(builder, [argval]) if i < len(args) - 1: pyapi.print_string(' ') pyapi.print_string('\n') pyapi.gil_release(gil) res = context.get_dummy_value() return impl_ret_untracked(context, builder, sig.return_type, res)
def generic(self, args, kws): assert not kws assert len(args) == 1 column = types.unliteral(args[0]) ret_typ = column if (isinstance(column, types.List) and (isinstance(column.dtype, types.Number) or column.dtype == types.boolean)): ret_typ = types.Array(column.dtype, 1, 'C') if (isinstance(column, types.List) and (column.dtype == string_type or isinstance(column.dtype, types.Optional) and column.dtype.type == string_type)): ret_typ = string_array_type if isinstance(column, SeriesType): ret_typ = column.data # TODO: add other types return signature(ret_typ, column)
def intrin_alloc(typingctx, allocsize, align): """Intrinsic to call into the allocator for Array """ def codegen(context, builder, signature, args): [allocsize, align] = args # XXX: error are being eaten. # example: replace the next line with `align_u32 = align` align_u32 = cast_integer(context, builder, align, signature.args[1], types.uint32) meminfo = context.nrt.meminfo_alloc_aligned( builder, allocsize, align_u32) return meminfo from numba.core.typing import signature mip = types.MemInfoPointer(types.voidptr) # return untyped pointer sig = signature(mip, allocsize, align) return sig, codegen
def test_cache(self): def times2(i): return 2 * i def times3(i): return i * 3 with self._context_builder_sig_args() as ( context, builder, sig, args, ): # Ensure the cache is empty to begin with self.assertEqual(0, len(context.cached_internal_func)) # After one compile, it should contain one entry context.compile_internal(builder, times2, sig, args) self.assertEqual(1, len(context.cached_internal_func)) # After a second compilation of the same thing, it should still contain # one entry context.compile_internal(builder, times2, sig, args) self.assertEqual(1, len(context.cached_internal_func)) # After compilation of another function, the cache should have grown by # one more. context.compile_internal(builder, times3, sig, args) self.assertEqual(2, len(context.cached_internal_func)) sig2 = typing.signature(types.float64, types.float64) llvm_fnty2 = context.call_conv.get_function_type( sig2.return_type, sig2.args) function2 = cgutils.get_or_insert_function(builder.module, llvm_fnty2, 'test_fn_2') args2 = context.call_conv.get_arguments(function2) assert function2.is_declaration entry_block2 = function2.append_basic_block('entry') builder2 = ir.IRBuilder(entry_block2) # Ensure that the same function with a different signature does not # reuse an entry from the cache in error context.compile_internal(builder2, times3, sig2, args2) self.assertEqual(3, len(context.cached_internal_func))
def _triangular_impl_3(context, builder, sig, low, high, mode, state): fltty = sig.return_type state_ptr = get_state_ptr(context, builder, state) randval = get_next_double(context, builder, state_ptr) def triangular_impl_3(randval, low, high, mode): if high == low: return low u = randval c = (mode - low) / (high - low) if u > c: u = 1.0 - u c = 1.0 - c low, high = high, low return low + (high - low) * math.sqrt(u * c) return context.compile_internal(builder, triangular_impl_3, signature(*(fltty, ) * 5), (randval, low, high, mode))
def dpnp_sum_impl(a): name = "sum" dpnp_lowering.ensure_dpnp(name) ret_type = types.void """ dpnp source: https://github.com/IntelPython/dpnp/blob/0.6.1dev/dpnp/backend/kernels/dpnp_krnl_reduction.cpp#L59 Function declaration: void dpnp_sum_c(void* result_out, const void* input_in, const size_t* input_shape, const size_t input_shape_ndim, const long* axes, const size_t axes_ndim, const void* initial, const long* where) """ sig = signature( ret_type, types.voidptr, # void* result_out, types.voidptr, # const void* input_in, types.voidptr, # const size_t* input_shape, types.intp, # const size_t input_shape_ndim, types.voidptr, # const long* axes, types.intp, # const size_t axes_ndim, types.voidptr, # const void* initial, types.voidptr, # const long* where) ) dpnp_func = dpnp_ext.dpnp_func("dpnp_" + name, [a.dtype.name, "NONE"], sig) PRINT_DEBUG = dpnp_lowering.DEBUG def dpnp_impl(a): out = np.empty(1, dtype=a.dtype) common_impl(a, out, dpnp_func, PRINT_DEBUG) return out[0] return dpnp_impl
def dpnp_random_impl(mean=0.0, sigma=1.0, size=None): name = "lognormal" dpnp_lowering.ensure_dpnp(name) ret_type = types.void """ dpnp source: https://github.com/IntelPython/dpnp/blob/0.4.0/dpnp/backend/custom_kernels_random.cpp#L199 Function declaration: void custom_rng_lognormal_c(void* result, _DataType mean, _DataType stddev, size_t size) """ sig = signature(ret_type, types.voidptr, types.float64, types.float64, types.intp) dpnp_func = dpnp_ext.dpnp_func("dpnp_" + name, ["float64", "NONE"], sig) res_dtype = np.float64 PRINT_DEBUG = dpnp_lowering.DEBUG if not isinstance(mean, float): if not (isinstance(mean, types.Float)): raise ValueError("We only support scalar for input: loc") if not isinstance(sigma, float): if not (isinstance(sigma, types.Float)): raise ValueError("We only support scalar for input: scale") if size in (None, types.none): def dpnp_impl(mean=0.0, sigma=1.0, size=None): res = np.empty(1, dtype=res_dtype) common_impl_2_arg(mean, sigma, res, dpnp_func, PRINT_DEBUG) return res[0] else: def dpnp_impl(mean=0.0, sigma=1.0, size=None): res = np.empty(size, dtype=res_dtype) if res.size != 0: common_impl_2_arg(mean, sigma, res, dpnp_func, PRINT_DEBUG) return res return dpnp_impl
def run_pass(self, state): """ Just create a compile result for interpreter mode """ args = [types.pyobject] * len(state.args) signature = typing.signature(types.pyobject, *args) from numba.core.compiler import compile_result state.cr = compile_result( typing_context=state.typingctx, target_context=state.targetctx, entry_point=state.func_id.func, typing_error=state.status.fail_reason, type_annotation="<Interpreter mode function>", signature=signature, objectmode=False, interpmode=True, lifted=(), fndesc=None, ) return True
def init_series_groupby(typingctx, parent, by_data, data, sort): def codegen(context, builder, signature, args): parent_val, _, data_val, sort_val = args # create series struct and store values groupby_obj = cgutils.create_struct_proxy(signature.return_type)( context, builder) groupby_obj.parent = parent_val groupby_obj.data = data_val groupby_obj.sort = sort_val # increase refcount of stored values if context.enable_nrt: context.nrt.incref(builder, signature.args[0], parent_val) context.nrt.incref(builder, signature.args[2], data_val) return groupby_obj._getvalue() ret_typ = SeriesGroupByType(parent, by_data) sig = signature(ret_typ, parent, by_data, data, sort) return sig, codegen
def cuda_quaternion_psi(context, builder, sig, arg): # Computes math.atan(2 * (a * d + b * c) / (a * a + b * b - c * c - d * d)) a = builder.extract_value(arg, 0) b = builder.extract_value(arg, 1) c = builder.extract_value(arg, 2) d = builder.extract_value(arg, 3) a2 = builder.fmul(a, a) b2 = builder.fmul(b, b) c2 = builder.fmul(c, c) d2 = builder.fmul(d, d) numerator = builder.fadd(builder.fmul(a, d), builder.fmul(b, c)) denominator = builder.fsub(builder.fsub(builder.fadd(a2, b2), c2), d2) atan_sig = signature(types.float64, types.float64) atan_impl = context.get_function(math.atan, atan_sig) atan_arg = builder.fmul(context.get_constant(types.float64, 2), builder.fdiv(numerator, denominator)) return atan_impl(builder, [atan_arg])
def test_error_model(self): """ Caching must not mix up different error models. """ def inv(x): return 1.0 / x inv_sig = typing.signature(types.float64, types.float64) def compile_inv(context): return context.compile_subroutine(builder, inv, inv_sig) with self._context_builder_sig_args() as ( context, builder, sig, args, ): py_error_model = callconv.create_error_model('python', context) np_error_model = callconv.create_error_model('numpy', context) py_context1 = context.subtarget(error_model=py_error_model) py_context2 = context.subtarget(error_model=py_error_model) np_context = context.subtarget(error_model=np_error_model) initial_cache_size = len(context.cached_internal_func) # Note the parent context's cache is shared by subtargets self.assertEqual(initial_cache_size + 0, len(context.cached_internal_func)) # Compiling with the same error model reuses the same cache slot compile_inv(py_context1) self.assertEqual(initial_cache_size + 1, len(context.cached_internal_func)) compile_inv(py_context2) self.assertEqual(initial_cache_size + 1, len(context.cached_internal_func)) # Compiling with another error model creates a new cache slot compile_inv(np_context) self.assertEqual(initial_cache_size + 2, len(context.cached_internal_func))
def dpnp_random_impl(n, p, size=None): name = "binomial" dpnp_lowering.ensure_dpnp(name) ret_type = types.void """ dpnp source: https://github.com/IntelPython/dpnp/blob/0.4.0/dpnp/backend/custom_kernels_random.cpp#L56 Function declaration: void custom_rng_binomial_c(void* result, int ntrial, double p, size_t size) """ sig = signature(ret_type, types.voidptr, types.int32, types.float64, types.intp) dpnp_func = dpnp_ext.dpnp_func("dpnp_" + name, ["int32", "NONE"], sig) res_dtype = np.int32 PRINT_DEBUG = dpnp_lowering.DEBUG if not (isinstance(n, types.Integer)): raise ValueError("We only support scalar for input: n") if not (isinstance(p, types.Float)): raise ValueError("We only support scalar for input: p") if size in (None, types.none): def dpnp_impl(n, p, size=None): res = np.empty(1, dtype=res_dtype) common_impl_2_arg(n, p, res, dpnp_func, PRINT_DEBUG) return res[0] else: def dpnp_impl(n, p, size=None): res = np.empty(size, dtype=res_dtype) if res.size != 0: common_impl_2_arg(n, p, res, dpnp_func, PRINT_DEBUG) return res return dpnp_impl
def init_series(typingctx, data, index=None, name=None): """Create a Series with provided data, index and name values. Used as a single constructor for Series and assigning its data, so that optimization passes can look for init_series() to see if underlying data has changed, and get the array variables from init_series() args if not changed. """ index = types.none if index is None else index name = types.none if name is None else name is_named = False if name is types.none else True def codegen(context, builder, signature, args): data_val, index_val, name_val = args # create series struct and store values series = cgutils.create_struct_proxy( signature.return_type)(context, builder) series.data = data_val series.index = index_val if is_named: if isinstance(name, types.StringLiteral): series.name = numba.cpython.unicode.make_string_from_constant( context, builder, string_type, name.literal_value) else: series.name = name_val # increase refcount of stored values if context.enable_nrt: context.nrt.incref(builder, signature.args[0], data_val) context.nrt.incref(builder, signature.args[1], index_val) if is_named: context.nrt.incref(builder, signature.args[2], name_val) return series._getvalue() dtype = data.dtype # XXX pd.DataFrame() calls init_series for even Series since it's untyped data = if_series_to_array_type(data) ret_typ = SeriesType(dtype, data, index, is_named) sig = signature(ret_typ, data, index, name) return sig, codegen
def random_arr(context, builder, sig, args, typing_key=typing_key): arrty = sig.return_type dtype = arrty.dtype scalar_sig = signature(dtype, *sig.args[:-1]) scalar_args = args[:-1] # Allocate array... shapes = arrayobj._parse_shape(context, builder, sig.args[-1], args[-1]) arr = arrayobj._empty_nd_impl(context, builder, arrty, shapes) # ... and populate it in natural order scalar_impl = context.get_function(typing_key, scalar_sig) with cgutils.for_range(builder, arr.nitems) as loop: val = scalar_impl(builder, scalar_args) ptr = cgutils.gep(builder, arr.data, loop.index) arrayobj.store_item(context, builder, arrty, val, ptr) return impl_ret_new_ref(context, builder, sig.return_type, arr._getvalue())
def _get_attr_info(self, state, expr): recv_type = state.type_annotation.typemap[expr.value.name] recv_type = types.unliteral(recv_type) matched = state.typingctx.find_matching_getattr_template( recv_type, expr.attr, ) if not matched: return None template = matched['template'] if getattr(template, 'is_method', False): # The attribute template is representing a method. # Don't inline the getattr. return None templates = [template] sig = typing.signature(matched['return_type'], recv_type) arg_typs = sig.args is_method = False return templates, sig, arg_typs, is_method
def getitem(self, obj, index, typ) -> ir.Expr: """Makes a getitem call Parameters ---------- obj : ir.Var the object being indexed index : ir.Var the index val : ir.Var the ty Returns ------- res : ir.Expr the retrieved value """ tm = self._typemap getitem = ir.Expr.getitem(obj, index, loc=self._loc) self._lowerer.fndesc.calltypes[getitem] = signature( typ, tm[obj.name], tm[index.name], ) return getitem
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws* types. This enables the resolving of the return type. A (template, pysig, args, kws) tuple is returned. """ assert not kws self._legalize_arg_types(args) # Coerce to object mode args = [types.ffi_forced_object] * len(args) if self._can_compile: self.compile(tuple(args)) signatures = [typing.signature(self.output_types, *args)] pysig = None func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) call_template = typing.make_concrete_template( name, key=func_name, signatures=signatures) return call_template, pysig, args, kws
def setitem(self, obj, index, val) -> ir.SetItem: """Makes a setitem call Parameters ---------- obj : ir.Var the object being indexed index : ir.Var the index val : ir.Var the value to be stored Returns ------- res : ir.SetItem """ loc = self._loc tm = self._typemap setitem = ir.SetItem(obj, index, val, loc=loc) self._lowerer.fndesc.calltypes[setitem] = signature( types.none, tm[obj.name], tm[index.name], tm[val.name]) self._lowerer.lower_inst(setitem) return setitem
def dpnp_cumsum_impl(a): name = "cumsum" dpnp_lowering.ensure_dpnp(name) res_type = types.void """ dpnp source: https://github.com/IntelPython/dpnp/blob/0.5.1/dpnp/backend/kernels/dpnp_krnl_mathematical.cpp#L135 Function declaration: void dpnp_cumsum_c(void* array1_in, void* result1, size_t size) """ sig = signature(res_type, types.voidptr, types.voidptr, types.intp) dpnp_func = dpnp_ext.dpnp_func("dpnp_" + name, [a.dtype.name, "NONE"], sig) PRINT_DEBUG = dpnp_lowering.DEBUG def dpnp_impl(a): out = np.arange(0, a.size, 1, a.dtype) common_impl(a, out, dpnp_func, PRINT_DEBUG) return out return dpnp_impl
def dpnp_random_impl(low=0.0, high=1.0, size=None): name = "uniform" dpnp_lowering.ensure_dpnp(name) ret_type = types.void """ dpnp source: https://github.com/IntelPython/dpnp/blob/0.4.0/dpnp/backend/custom_kernels_random.cpp#L391 Function declaration: void custom_rng_uniform_c(void* result, long low, long high, size_t size) """ sig = signature(ret_type, types.voidptr, types.int64, types.int64, types.intp) dpnp_func = dpnp_ext.dpnp_func("dpnp_" + name, ["float64", "NONE"], sig) res_dtype = np.float64 PRINT_DEBUG = dpnp_lowering.DEBUG if size in (None, types.none): def dpnp_impl(low=0.0, high=1.0, size=None): res = np.empty(1, dtype=res_dtype) common_impl(low, high, res, dpnp_func, PRINT_DEBUG) return res else: def dpnp_impl(low=0.0, high=1.0, size=None): res = np.empty(size, dtype=res_dtype) if res.size != 0: common_impl(low, high, res, dpnp_func, PRINT_DEBUG) return res return dpnp_impl
def dpnp_random_impl(df, size=None): name = "chisquare" dpnp_lowering.ensure_dpnp(name) ret_type = types.void """ dpnp source: https://github.com/IntelPython/dpnp/blob/0.4.0/dpnp/backend/custom_kernels_random.cpp#L71 Function declaration: void custom_rng_chi_square_c(void* result, int df, size_t size) """ sig = signature(ret_type, types.voidptr, types.int32, types.intp) dpnp_func = dpnp_ext.dpnp_func("dpnp_" + name, ["float64", "NONE"], sig) res_dtype = np.float64 PRINT_DEBUG = dpnp_lowering.DEBUG if not (isinstance(df, types.Integer)): raise ValueError("We only support scalar for input: df") if size in (None, types.none): def dpnp_impl(df, size=None): res = np.empty(1, dtype=res_dtype) common_impl_1_arg(df, res, dpnp_func, PRINT_DEBUG) return res[0] else: def dpnp_impl(df, size=None): res = np.empty(size, dtype=res_dtype) if res.size != 0: common_impl_1_arg(df, res, dpnp_func, PRINT_DEBUG) return res return dpnp_impl