def to_fixed_tuple(typingctx, array, length): """Convert *array* into a tuple of *length* Returns ``UniTuple(array.dtype, length)`` ** Warning ** - No boundchecking. If *length* is longer than *array.size*, the behavior is undefined. """ if not isinstance(length, types.Const): raise RequireConstValue('*length* argument must be a constant') if array.ndim != 1: raise TypingError("Not supported on array.ndim={}".format(array.ndim)) # Determine types tuple_size = int(length.value) tuple_type = types.UniTuple(dtype=array.dtype, count=tuple_size) sig = tuple_type(array, length) def codegen(context, builder, signature, args): def impl(array, length, empty_tuple): out = empty_tuple for i in range(length): out = tuple_setitem(out, i, array[i]) return out inner_argtypes = [signature.args[0], types.intp, tuple_type] inner_sig = typing.signature(tuple_type, *inner_argtypes) ll_idx_type = context.get_value_type(types.intp) # Allocate an empty tuple empty_tuple = context.get_constant_undef(tuple_type) inner_args = [args[0], ll_idx_type(tuple_size), empty_tuple] res = context.compile_internal(builder, impl, inner_sig, inner_args) return res return sig, codegen
def _gen_index_tuple(tyctx, shape_tuple, value, axis): """ Generates a tuple that can be used to index a specific slice from an array for sum with axis. shape_tuple is the size of the dimensions of the input array. 'value' is the value to put in the indexing tuple in the axis dimension and 'axis' is that dimension. For this to work, axis has to be a const. """ if not isinstance(axis, types.Const): raise RequireConstValue('axis argument must be a constant') # Get the value of the axis constant. axis_value = axis.value # The length of the indexing tuple to be output. nd = len(shape_tuple) # If the axis value is impossible for the given size array then # just fake it like it was for axis 0. This will stop compile errors # when it looks like it could be called from array_sum_axis but really # can't because that routine checks the axis mismatch and raise an # exception. if axis_value >= nd: axis_value = 0 # Calculate the type of the indexing tuple. All the non-axis # dimensions have slice2 type and the axis dimension has int type. before = axis_value after = nd - before - 1 types_list = ([types.slice2_type] * before) + \ [types.intp] + \ ([types.slice2_type] * after) # Creates the output type of the function. tupty = types.Tuple(types_list) # Defines the signature of the intrinsic. function_sig = tupty(shape_tuple, value, axis) def codegen(cgctx, builder, signature, args): lltupty = cgctx.get_value_type(tupty) # Create an empty indexing tuple. tup = cgutils.get_null_value(lltupty) # We only need value of the axis dimension here. # The rest are constants defined above. [_, value_arg, _] = args def create_full_slice(): return slice(None, None) # loop to fill the tuple with slice(None,None) before # the axis dimension. # compile and call create_full_slice slice_data = cgctx.compile_internal(builder, create_full_slice, types.slice2_type(), []) for i in range(0, axis_value): tup = builder.insert_value(tup, slice_data, i) # Add the axis dimension 'value'. tup = builder.insert_value(tup, value_arg, axis_value) # loop to fill the tuple with slice(None,None) after # the axis dimension. for i in range(axis_value + 1, nd): tup = builder.insert_value(tup, slice_data, i) return tup return function_sig, codegen